This commit is contained in:
Wes Kocher 2014-09-30 17:10:24 -07:00
Родитель c3dee3558d 4912aa7261
Коммит 4d9a345155
65 изменённых файлов: 1651 добавлений и 294 удалений

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

@ -827,8 +827,11 @@ pref("network.gonk.manage-offline-status", true);
// On Firefox Mulet, we can't enable shared JSM scope
// as it breaks most Firefox JSMs (see bug 961777)
#ifndef MOZ_MULET
// Break any JSMs or JS components that rely on shared scope
#ifndef DEBUG
pref("jsloader.reuseGlobal", true);
#endif
#endif
// Enable font inflation for browser tab content.
pref("font.size.inflation.minTwips", 120);

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

@ -486,6 +486,7 @@ let settingsToObserve = {
resetToPref: true
},
'dom.mozApps.use_reviewer_certs': false,
'dom.mozApps.signed_apps_installable_from': 'https://marketplace.firefox.com',
'layers.draw-borders': false,
'layers.draw-tile-borders': false,
'layers.dump': false,

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="77ef35f5429bc3dfe9ca192b9aacc3c0bf8857de"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0f7792c39ad26aedecf457117c21b16cc1aee879"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4f9042d3a705307849a6f63961eaaaa2e1d85d77"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
@ -133,7 +133,7 @@
<project name="platform/hardware/akm" path="hardware/akm" revision="6d3be412647b0eab0adff8a2768736cf4eb68039"/>
<project groups="invensense" name="platform/hardware/invensense" path="hardware/invensense" revision="e6d9ab28b4f4e7684f6c07874ee819c9ea0002a2"/>
<project name="platform/hardware/ril" path="hardware/ril" revision="865ce3b4a2ba0b3a31421ca671f4d6c5595f8690"/>
<project name="kernel/common" path="kernel" revision="28aab3bd1139b6beea545f50dee8903c0634de84"/>
<project name="kernel/common" path="kernel" revision="f365109310138f85bb91884b7dee60f6f0da042d"/>
<project name="platform/system/core" path="system/core" revision="53d584d4a4b4316e4de9ee5f210d662f89b44e7e"/>
<project name="u-boot" path="u-boot" revision="982c1fd67b89d5573317c1796cf5b0143de44e8a"/>
<project name="vendor/sprd/gps" path="vendor/sprd/gps" revision="6974f8e771d4d8e910357a6739ab124768891e8f"/>

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

@ -19,13 +19,13 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="77ef35f5429bc3dfe9ca192b9aacc3c0bf8857de"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0f7792c39ad26aedecf457117c21b16cc1aee879"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4f9042d3a705307849a6f63961eaaaa2e1d85d77"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>

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

@ -17,10 +17,10 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="77ef35f5429bc3dfe9ca192b9aacc3c0bf8857de"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0f7792c39ad26aedecf457117c21b16cc1aee879"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4f9042d3a705307849a6f63961eaaaa2e1d85d77"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->
@ -134,7 +134,7 @@
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d259117b4976decbe2f76eeed85218bf0109190f"/>
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9f28c4faea3b2f01db227b2467b08aeba96d9bec"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="2a5dc67db7c9e6651c5fff855a6f69c1f2061ca7"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="cf9376f0f59ca72333dd24a54efe887d527da612"/>
<project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
<project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
</manifest>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="77ef35f5429bc3dfe9ca192b9aacc3c0bf8857de"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0f7792c39ad26aedecf457117c21b16cc1aee879"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4f9042d3a705307849a6f63961eaaaa2e1d85d77"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>

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

@ -19,13 +19,13 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="77ef35f5429bc3dfe9ca192b9aacc3c0bf8857de"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0f7792c39ad26aedecf457117c21b16cc1aee879"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4f9042d3a705307849a6f63961eaaaa2e1d85d77"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
<project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="77ef35f5429bc3dfe9ca192b9aacc3c0bf8857de"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0f7792c39ad26aedecf457117c21b16cc1aee879"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4f9042d3a705307849a6f63961eaaaa2e1d85d77"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
@ -151,7 +151,7 @@
<project name="platform/hardware/ril" path="hardware/ril" revision="12b1977cc704b35f2e9db2bb423fa405348bc2f3"/>
<project name="platform/system/bluetooth" path="system/bluetooth" revision="985bf15264d865fe7b9c5b45f61c451cbaafa43d"/>
<project name="platform/system/core" path="system/core" revision="350eac5403124dacb2a5fd9e28ac290a59fc3b8e"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="2a5dc67db7c9e6651c5fff855a6f69c1f2061ca7"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="cf9376f0f59ca72333dd24a54efe887d527da612"/>
<project name="platform/system/qcom" path="system/qcom" revision="63e3f6f176caad587d42bba4c16b66d953fb23c2"/>
<project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="d8952a42771045fca73ec600e2b42a4c7129d723"/>
<project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="7704e16da545f4207812e593743d6743e1afb9c5"/>

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

@ -17,10 +17,10 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="77ef35f5429bc3dfe9ca192b9aacc3c0bf8857de"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0f7792c39ad26aedecf457117c21b16cc1aee879"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4f9042d3a705307849a6f63961eaaaa2e1d85d77"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->
@ -145,7 +145,7 @@
<project name="platform/hardware/ril" path="hardware/ril" revision="c4e2ac95907a5519a0e09f01a0d8e27fec101af0"/>
<project name="platform/system/bluetooth" path="system/bluetooth" revision="e1eb226fa3ad3874ea7b63c56a9dc7012d7ff3c2"/>
<project name="platform/system/core" path="system/core" revision="adc485d8755af6a61641d197de7cfef667722580"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="2a5dc67db7c9e6651c5fff855a6f69c1f2061ca7"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="cf9376f0f59ca72333dd24a54efe887d527da612"/>
<project name="platform/system/qcom" path="system/qcom" revision="1cdab258b15258b7f9657da70e6f06ebd5a2fc25"/>
<project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4ae5df252123591d5b941191790e7abed1bce5a4"/>
<project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="ce18b47b4a4f93a581d672bbd5cb6d12fe796ca9"/>

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

@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
"revision": "fb5a4aa15e266e9aa0e44281241ad081b528c75b",
"revision": "7f097f40e32ecba580890ce1d3df2a493641bdec",
"repo_path": "/integration/gaia-central"
}

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

@ -17,12 +17,12 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="77ef35f5429bc3dfe9ca192b9aacc3c0bf8857de"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0f7792c39ad26aedecf457117c21b16cc1aee879"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4f9042d3a705307849a6f63961eaaaa2e1d85d77"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
<project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>

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

@ -15,7 +15,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="77ef35f5429bc3dfe9ca192b9aacc3c0bf8857de"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>

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

@ -17,10 +17,10 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="77ef35f5429bc3dfe9ca192b9aacc3c0bf8857de"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0f7792c39ad26aedecf457117c21b16cc1aee879"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4f9042d3a705307849a6f63961eaaaa2e1d85d77"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->
@ -129,7 +129,7 @@
<project name="device-mako" path="device/lge/mako" remote="b2g" revision="78d17f0c117f0c66dd55ee8d5c5dde8ccc93ecba"/>
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
<project name="device/lge/mako-kernel" path="device/lge/mako-kernel" revision="d1729e53d71d711c8fde25eab8728ff2b9b4df0e"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="2a5dc67db7c9e6651c5fff855a6f69c1f2061ca7"/>
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="cf9376f0f59ca72333dd24a54efe887d527da612"/>
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
<project name="platform/hardware/broadcom/wlan" path="hardware/broadcom/wlan" revision="0e1929fa3aa38bf9d40e9e953d619fab8164c82e"/>

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

@ -17,12 +17,12 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="77ef35f5429bc3dfe9ca192b9aacc3c0bf8857de"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e280591881d44b80f456bc27e12d9114c218868"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="0f7792c39ad26aedecf457117c21b16cc1aee879"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="4f9042d3a705307849a6f63961eaaaa2e1d85d77"/>
<project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
<!-- Stock Android things -->
<project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>

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

@ -44,14 +44,14 @@ var gPluginHandler = {
switch (msg.name) {
case "PluginContent:ShowClickToPlayNotification":
this.showClickToPlayNotification(msg.target, msg.data.plugins, msg.data.showNow,
msg.principal, msg.data.host);
msg.principal, msg.data.host, msg.data.location);
break;
case "PluginContent:RemoveNotification":
this.removeNotification(msg.target, msg.data.name);
break;
case "PluginContent:UpdateHiddenPluginUI":
this.updateHiddenPluginUI(msg.target, msg.data.haveInsecure, msg.data.actions,
msg.principal, msg.data.host);
msg.principal, msg.data.host, msg.data.location);
break;
case "PluginContent:HideNotificationBar":
this.hideNotificationBar(msg.target, msg.data.name);
@ -139,11 +139,6 @@ var gPluginHandler = {
// list again
this.options.primaryPlugin = null;
}
else if (event == "removed") {
// Once the notification is removed, let the content script clear any
// caches it may have populated.
this.browser.messageManager.sendAsyncMessage("BrowserPlugins:NotificationRemoved");
}
},
/**
@ -221,7 +216,8 @@ var gPluginHandler = {
});
},
showClickToPlayNotification: function (browser, plugins, showNow, principal, host) {
showClickToPlayNotification: function (browser, plugins, showNow, principal,
host, location) {
// It is possible that we've received a message from the frame script to show
// a click to play notification for a principal that no longer matches the one
// that the browser's content now has assigned (ie, the browser has browsed away
@ -231,6 +227,15 @@ var gPluginHandler = {
return;
}
// Data URIs, when linked to from some page, inherit the principal of that
// page. That means that we also need to compare the actual locations to
// ensure we aren't getting a message from a Data URI that we're no longer
// looking at.
let receivedURI = BrowserUtils.makeURI(location);
if (!browser.documentURI.equalsExceptRef(receivedURI)) {
return;
}
let notification = PopupNotifications.getNotification("click-to-play-plugins", browser);
// If this is a new notification, create a pluginData map, otherwise append
@ -305,7 +310,8 @@ var gPluginHandler = {
notificationBox.removeNotification(notification, true);
},
updateHiddenPluginUI: function (browser, haveInsecure, actions, principal, host) {
updateHiddenPluginUI: function (browser, haveInsecure, actions, principal,
host, location) {
// It is possible that we've received a message from the frame script to show
// the hidden plugin notification for a principal that no longer matches the one
// that the browser's content now has assigned (ie, the browser has browsed away
@ -315,6 +321,15 @@ var gPluginHandler = {
return;
}
// Data URIs, when linked to from some page, inherit the principal of that
// page. That means that we also need to compare the actual locations to
// ensure we aren't getting a message from a Data URI that we're no longer
// looking at.
let receivedURI = BrowserUtils.makeURI(location);
if (!browser.documentURI.equalsExceptRef(receivedURI)) {
return;
}
// Set up the icon
document.getElementById("plugins-notification-icon").classList.
toggle("plugin-blocked", haveInsecure);

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

@ -1025,15 +1025,27 @@ if (Services.prefs.getBoolPref("privacy.panicButton.enabled")) {
// Workaround bug 451997 by hardcoding heights for (potentially) wrapped items:
_updateHeights: function(aContainer, aSetHeights) {
// Make sure we don't get stuck not finding anything because of the XBL binding between
// the popup and the radio/label elements:
// the popup and the radio/label/description elements:
let view = aContainer.ownerDocument.getElementById("PanelUI-panicView");
let variableHeightItems = view.querySelectorAll("radio, label");
let variableHeightItems = view.querySelectorAll("radio, label, description");
let win = aContainer.ownerDocument.defaultView;
for (let item of variableHeightItems) {
if (aSetHeights) {
item.style.height = win.getComputedStyle(item, null).getPropertyValue("height");
let height = win.getComputedStyle(item, null).getPropertyValue("height");
item.style.height = height;
// In the main menu panel, need to set the height of the container of this
// description because otherwise the text will overflow:
if (item.id == "PanelUI-panic-mainDesc" &&
view.getAttribute("current") == "true" &&
// Ensure we don't make this less than the size of the icon:
parseInt(height) > 32) {
item.parentNode.style.minHeight = height;
}
} else {
item.style.removeProperty("height");
if (item.id == "PanelUI-panic-mainDesc") {
item.parentNode.style.removeProperty("min-height");
}
}
}
},
@ -1041,9 +1053,14 @@ if (Services.prefs.getBoolPref("privacy.panicButton.enabled")) {
let view = aEvent.target;
let forgetButton = view.querySelector("#PanelUI-panic-view-button");
forgetButton.addEventListener("command", this);
// When the popup starts showing, fix the label and radio heights
// if we're in a standalone view (can't tell from here) - see updateHeights.
view.ownerDocument.addEventListener("popupshowing", this);
if (view.getAttribute("current") == "true") {
// In the main menupanel, fix heights immediately:
this._updateHeights(view, true);
} else {
// In a standalone panel, so fix the label and radio heights
// when the popup starts showing.
view.ownerDocument.addEventListener("popupshowing", this);
}
},
onViewHiding: function(aEvent) {
let view = aEvent.target;

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

@ -186,7 +186,7 @@
<vbox flex="1">
<hbox id="PanelUI-panic-header">
<image id="PanelUI-panic-timeframe-icon-small" alt=""/>
<description value="&panicButton.view.mainTimeframeDesc;" id="PanelUI-panic-mainDesc"/>
<description id="PanelUI-panic-mainDesc" flex="1">&panicButton.view.mainTimeframeDesc;</description>
</hbox>
<radiogroup id="PanelUI-panic-timeSpan" aria-labelledby="PanelUI-panic-mainDesc">
<radio id="PanelUI-panic-5min" label="&panicButton.view.5min;" selected="true"
@ -199,14 +199,14 @@
</vbox>
</hbox>
<vbox id="PanelUI-panic-explanations">
<label id="PanelUI-panic-actionlist-main-label" value="&panicButton.view.mainActionDesc;"/>
<label id="PanelUI-panic-actionlist-main-label">&panicButton.view.mainActionDesc;</label>
<label id="PanelUI-panic-actionlist-cookies" class="PanelUI-panic-actionlist">&panicButton.view.deleteCookies;</label>
<label id="PanelUI-panic-actionlist-history" class="PanelUI-panic-actionlist">&panicButton.view.deleteHistory;</label>
<label id="PanelUI-panic-actionlist-windows" class="PanelUI-panic-actionlist">&panicButton.view.deleteTabsAndWindows;</label>
<label id="PanelUI-panic-actionlist-newwindow" class="PanelUI-panic-actionlist">&panicButton.view.openNewWindow;</label>
<label id="PanelUI-panic-warning" value="&panicButton.view.undoWarning;"/>
<label id="PanelUI-panic-warning">&panicButton.view.undoWarning;</label>
</vbox>
<button id="PanelUI-panic-view-button"
label="&panicButton.view.forgetButton;"/>

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

@ -66,6 +66,32 @@ skip-if = e10s # Bug ?????? - test uses promiseTabLoadEvent() which isn't e10s f
[browser_943683_migration_test.js]
[browser_944887_destroyWidget_should_destroy_in_palette.js]
[browser_945739_showInPrivateBrowsing_customize_mode.js]
[browser_947914_button_addons.js]
skip-if = os == "linux" # Intermittent failures
[browser_947914_button_copy.js]
skip-if = os == "linux" # Intermittent failures
[browser_947914_button_cut.js]
skip-if = os == "linux" # Intermittent failures
[browser_947914_button_find.js]
skip-if = os == "linux" # Intermittent failures
[browser_947914_button_history.js]
skip-if = os == "linux" # Intermittent failures
[browser_947914_button_newPrivateWindow.js]
skip-if = os == "linux" # Intermittent failures
[browser_947914_button_newWindow.js]
skip-if = os == "linux" # Intermittent failures
[browser_947914_button_paste.js]
skip-if = os == "linux" # Intermittent failures
[browser_947914_button_print.js]
skip-if = os == "linux" # Intermittent failures
[browser_947914_button_savePage.js]
skip-if = os == "linux" # Intermittent failures
[browser_947914_button_zoomIn.js]
skip-if = os == "linux" # Intermittent failures
[browser_947914_button_zoomOut.js]
skip-if = os == "linux" # Intermittent failures
[browser_947914_button_zoomReset.js]
skip-if = os == "linux" # Intermittent failures
[browser_947987_removable_default.js]
[browser_948985_non_removable_defaultArea.js]
[browser_952963_areaType_getter_no_area.js]

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

@ -0,0 +1,33 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let initialLocation = gBrowser.currentURI.spec;
let newTab = null;
add_task(function() {
info("Check addons button existence and functionality");
yield PanelUI.show();
info("Menu panel was opened");
let addonsButton = document.getElementById("add-ons-button");
ok(addonsButton, "Add-ons button exists in Panel Menu");
addonsButton.click();
newTab = gBrowser.selectedTab;
yield waitForCondition(function() gBrowser.currentURI &&
gBrowser.currentURI.spec == "about:addons");
let addonsPage = gBrowser.selectedBrowser.contentWindow.document.
getElementById("addons-page");
ok(addonsPage, "Add-ons page was opened");
});
add_task(function asyncCleanup() {
gBrowser.addTab(initialLocation);
gBrowser.removeTab(gBrowser.selectedTab);
info("Tabs were restored");
});

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

@ -0,0 +1,64 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let initialLocation = gBrowser.currentURI.spec;
let globalClipboard;
add_task(function() {
info("Check copy button existence and functionality");
let testText = "copy text test";
gURLBar.focus();
info("The URL bar was focused");
yield PanelUI.show();
info("Menu panel was opened");
let copyButton = document.getElementById("copy-button");
ok(copyButton, "Copy button exists in Panel Menu");
is(copyButton.getAttribute("disabled"), "true", "Copy button is initially disabled");
// copy text from URL bar
gURLBar.value = testText;
gURLBar.focus();
gURLBar.select();
yield PanelUI.show();
info("Menu panel was opened");
ok(!copyButton.hasAttribute("disabled"), "Copy button gets enabled");
copyButton.click();
is(gURLBar.value, testText, "Selected text is unaltered when clicking copy");
// check that the text was added to the clipboard
let clipboard = Services.clipboard;
let transferable = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
globalClipboard = clipboard.kGlobalClipboard;
transferable.init(null);
transferable.addDataFlavor("text/unicode");
clipboard.getData(transferable, globalClipboard);
let str = {}, strLength = {};
transferable.getTransferData("text/unicode", str, strLength);
let clipboardValue = "";
if (str.value) {
str.value.QueryInterface(Ci.nsISupportsString);
clipboardValue = str.value.data;
}
is(clipboardValue, testText, "Data was copied to the clipboard.");
});
add_task(function asyncCleanup() {
// clear the clipboard
Services.clipboard.emptyClipboard(globalClipboard);
info("Clipboard was cleared");
// restore the tab as it was at the begining of the test
gBrowser.addTab(initialLocation);
gBrowser.removeTab(gBrowser.selectedTab);
info("Tabs were restored");
});

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

@ -0,0 +1,62 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let initialLocation = gBrowser.currentURI.spec;
let globalClipboard;
add_task(function() {
info("Check cut button existence and functionality");
let testText = "cut text test";
gURLBar.focus();
yield PanelUI.show();
info("Menu panel was opened");
let cutButton = document.getElementById("cut-button");
ok(cutButton, "Cut button exists in Panel Menu");
ok(cutButton.getAttribute("disabled"), "Cut button is disabled");
// cut text from URL bar
gURLBar.value = testText;
gURLBar.focus();
gURLBar.select();
yield PanelUI.show();
info("Menu panel was opened");
ok(!cutButton.hasAttribute("disabled"), "Cut button gets enabled");
cutButton.click();
is(gURLBar.value, "", "Selected text is removed from source when clicking on cut");
// check that the text was added to the clipboard
let clipboard = Services.clipboard;
let transferable = Cc["@mozilla.org/widget/transferable;1"].createInstance(Ci.nsITransferable);
globalClipboard = clipboard.kGlobalClipboard;
transferable.init(null);
transferable.addDataFlavor("text/unicode");
clipboard.getData(transferable, globalClipboard);
let str = {}, strLength = {};
transferable.getTransferData("text/unicode", str, strLength);
let clipboardValue = "";
if (str.value) {
str.value.QueryInterface(Ci.nsISupportsString);
clipboardValue = str.value.data;
}
is(clipboardValue, testText, "Data was copied to the clipboard.");
});
add_task(function asyncCleanup() {
// clear the clipboard
Services.clipboard.emptyClipboard(globalClipboard);
info("Clipboard was cleared");
// restore the tab as it was at the begining of the test
gBrowser.addTab(initialLocation);
gBrowser.removeTab(gBrowser.selectedTab);
info("Tabs were restored");
});

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

@ -0,0 +1,22 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
add_task(function() {
info("Check find button existence and functionality");
yield PanelUI.show();
info("Menu panel was opened");
let findButton = document.getElementById("find-button");
ok(findButton, "Find button exists in Panel Menu");
findButton.click();
ok(!gFindBar.hasAttribute("hidden"), "Findbar opened successfully");
// close find bar
gFindBar.close();
info("Findbar was closed");
});

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

@ -0,0 +1,24 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
add_task(function() {
info("Check history button existence and functionality");
yield PanelUI.show();
info("Menu panel was opened");
let historyButton = document.getElementById("history-panelmenu");
ok(historyButton, "History button appears in Panel Menu");
historyButton.click();
let historyPanel = document.getElementById("PanelUI-history");
ok(historyPanel.getAttribute("current"), "History Panel is in view");
let panelHiddenPromise = promisePanelHidden(window);
PanelUI.hide();
yield panelHiddenPromise
info("Menu panel was closed");
});

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

@ -0,0 +1,48 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
add_task(function() {
info("Check private browsing button existence and functionality");
yield PanelUI.show();
info("Menu panel was opened");
let windowWasHandled = false;
let privateWindow = null;
let observerWindowOpened = {
observe: function(aSubject, aTopic, aData) {
if (aTopic == "domwindowopened") {
privateWindow = aSubject.QueryInterface(Components.interfaces.nsIDOMWindow);
privateWindow.addEventListener("load", function newWindowHandler() {
privateWindow.removeEventListener("load", newWindowHandler, false);
is(privateWindow.location.href, "chrome://browser/content/browser.xul",
"A new browser window was opened");
ok(PrivateBrowsingUtils.isWindowPrivate(privateWindow), "Window is private");
windowWasHandled = true;
}, false);
}
}
}
Services.ww.registerNotification(observerWindowOpened);
let privateBrowsingButton = document.getElementById("privatebrowsing-button");
ok(privateBrowsingButton, "Private browsing button exists in Panel Menu");
privateBrowsingButton.click();
try {
yield waitForCondition(() => windowWasHandled);
yield promiseWindowClosed(privateWindow);
info("The new private window was closed");
}
catch(e) {
ok(false, "The new private browser window was not properly handled");
}
finally {
Services.ww.unregisterNotification(observerWindowOpened);
}
});

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

@ -0,0 +1,47 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
add_task(function() {
info("Check new window button existence and functionality");
yield PanelUI.show();
info("Menu panel was opened");
let windowWasHandled = false;
let newWindow = null;
let observerWindowOpened = {
observe: function(aSubject, aTopic, aData) {
if (aTopic == "domwindowopened") {
newWindow = aSubject.QueryInterface(Components.interfaces.nsIDOMWindow);
newWindow.addEventListener("load", function newWindowHandler() {
newWindow.removeEventListener("load", newWindowHandler, false);
is(newWindow.location.href, "chrome://browser/content/browser.xul",
"A new browser window was opened");
ok(!PrivateBrowsingUtils.isWindowPrivate(newWindow), "Window is not private");
windowWasHandled = true;
}, false);
}
}
}
Services.ww.registerNotification(observerWindowOpened);
let newWindowButton = document.getElementById("new-window-button");
ok(newWindowButton, "New Window button exists in Panel Menu");
newWindowButton.click();
try {
yield waitForCondition(() => windowWasHandled);
yield promiseWindowClosed(newWindow);
info("The new window was closed");
}
catch(e) {
ok(false, "The new browser window was not properly handled");
}
finally {
Services.ww.unregisterNotification(observerWindowOpened);
}
});

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

@ -0,0 +1,47 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let initialLocation = gBrowser.currentURI.spec;
let globalClipboard;
add_task(function() {
info("Check paste button existence and functionality");
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper);
globalClipboard = Services.clipboard.kGlobalClipboard;
yield PanelUI.show();
info("Menu panel was opened");
let pasteButton = document.getElementById("paste-button");
ok(pasteButton, "Paste button exists in Panel Menu");
// add text to clipboard
let text = "Sample text for testing";
clipboard.copyString(text);
// test paste button by pasting text to URL bar
gURLBar.focus();
yield PanelUI.show();
info("Menu panel was opened");
ok(!pasteButton.hasAttribute("disabled"), "Paste button is enabled");
pasteButton.click();
is(gURLBar.value, text, "Text pasted successfully");
});
add_task(function asyncCleanup() {
// clear the clipboard
Services.clipboard.emptyClipboard(globalClipboard);
info("Clipboard was cleared");
// restore the tab as it was at the begining of the test
gBrowser.addTab(initialLocation);
gBrowser.removeTab(gBrowser.selectedTab);
info("Tabs were restored");
});

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

@ -0,0 +1,41 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const isOSX = (Services.appinfo.OS === "Darwin");
add_task(function() {
info("Check print button existence and functionality");
yield PanelUI.show();
info("Menu panel was opened");
yield waitForCondition(() => document.getElementById("print-button") != null);
let printButton = document.getElementById("print-button");
ok(printButton, "Print button exists in Panel Menu");
if (isOSX) {
let panelHiddenPromise = promisePanelHidden(window);
PanelUI.hide();
yield panelHiddenPromise;
info("Menu panel was closed");
}
else {
printButton.click();
yield waitForCondition(() => gInPrintPreviewMode);
ok(gInPrintPreviewMode, "Entered print preview mode");
}
});
add_task(function asyncCleanup() {
// close print preview
if (gInPrintPreviewMode) {
PrintUtils.exitPrintPreview();
yield waitForCondition(() => !window.gInPrintPreviewMode);
info("Exited print preview")
}
});

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

@ -0,0 +1,20 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
add_task(function() {
info("Check save page button existence");
yield PanelUI.show();
info("Menu panel was opened");
let savePageButton = document.getElementById("save-page-button");
ok(savePageButton, "Save Page button exists in Panel Menu");
let panelHiddenPromise = promisePanelHidden(window);
PanelUI.hide();
yield panelHiddenPromise;
info("Menu panel was closed");
});

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

@ -0,0 +1,37 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let initialPageZoom = ZoomManager.zoom;
add_task(function() {
info("Check zoom in button existence and functionality");
is(initialPageZoom, 1, "Initial zoom factor should be 1");
yield PanelUI.show();
info("Menu panel was opened");
let zoomInButton = document.getElementById("zoom-in-button");
ok(zoomInButton, "Zoom in button exists in Panel Menu");
zoomInButton.click();
let pageZoomLevel = parseInt(ZoomManager.zoom * 100);
let zoomResetButton = document.getElementById("zoom-reset-button");
let expectedZoomLevel = parseInt(zoomResetButton.getAttribute("label"), 10);
ok(pageZoomLevel > 100 && pageZoomLevel == expectedZoomLevel, "Page zoomed in correctly");
// close the Panel
let panelHiddenPromise = promisePanelHidden(window);
PanelUI.hide();
yield panelHiddenPromise;
info("Menu panel was closed");
});
add_task(function asyncCleanup() {
// reset zoom level
ZoomManager.zoom = initialPageZoom;
info("Zoom level was restored");
});

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

@ -0,0 +1,38 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let initialPageZoom = ZoomManager.zoom;
add_task(function() {
info("Check zoom out button existence and functionality");
is(initialPageZoom, 1, "Initial zoom factor should be 1");
yield PanelUI.show();
info("Menu panel was opened");
let zoomOutButton = document.getElementById("zoom-out-button");
ok(zoomOutButton, "Zoom out button exists in Panel Menu");
zoomOutButton.click();
let pageZoomLevel = Math.round(ZoomManager.zoom * 100);
let zoomResetButton = document.getElementById("zoom-reset-button");
let expectedZoomLevel = parseInt(zoomResetButton.getAttribute("label"), 10);
ok(pageZoomLevel < 100 && pageZoomLevel == expectedZoomLevel, "Page zoomed out correctly");
// close the panel
let panelHiddenPromise = promisePanelHidden(window);
PanelUI.hide();
yield panelHiddenPromise;
info("Menu panel was closed");
});
add_task(function asyncCleanup() {
// reset zoom level
ZoomManager.zoom = initialPageZoom;
info("Zoom level was restored");
});

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

@ -0,0 +1,38 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
let initialPageZoom = ZoomManager.zoom;
add_task(function() {
info("Check zoom reset button existence and functionality");
is(initialPageZoom, 1, "Page zoom reset correctly");
ZoomManager.zoom = 0.5;
yield PanelUI.show();
info("Menu panel was opened");
let zoomResetButton = document.getElementById("zoom-reset-button");
ok(zoomResetButton, "Zoom reset button exists in Panel Menu");
zoomResetButton.click();
let pageZoomLevel = Math.floor(ZoomManager.zoom * 100);
let expectedZoomLevel = 100;
let buttonZoomLevel = parseInt(zoomResetButton.getAttribute("label"), 10);
is(pageZoomLevel, expectedZoomLevel, "Page zoom reset correctly");
is(pageZoomLevel, buttonZoomLevel, "Button displays the correct zoom level");
// close the panel
let panelHiddenPromise = promisePanelHidden(window);
PanelUI.hide();
yield panelHiddenPromise;
info("Menu panel was closed");
});
add_task(function asyncCleanup() {
// reset zoom level
ZoomManager.zoom = initialPageZoom;
info("Zoom level was restored");
});

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

@ -17,15 +17,123 @@ loop.contacts = (function(_, mozL10n) {
// Number of contacts to add to the list at the same time.
const CONTACTS_CHUNK_SIZE = 100;
const ContactDetail = React.createClass({displayName: 'ContactDetail',
const ContactDropdown = React.createClass({displayName: 'ContactDropdown',
propTypes: {
handleContactClick: React.PropTypes.func,
handleAction: React.PropTypes.func.isRequired,
canEdit: React.PropTypes.bool
},
getInitialState: function () {
return {
openDirUp: false,
};
},
componentDidMount: function () {
// This method is called once when the dropdown menu is added to the DOM
// inside the contact item. If the menu extends outside of the visible
// area of the scrollable list, it is re-rendered in different direction.
let menuNode = this.getDOMNode();
let menuNodeRect = menuNode.getBoundingClientRect();
let listNode = document.getElementsByClassName("contact-list")[0];
let listNodeRect = listNode.getBoundingClientRect();
if (menuNodeRect.top + menuNodeRect.height >=
listNodeRect.top + listNodeRect.height) {
this.setState({
openDirUp: true,
});
}
},
onItemClick: function(event) {
this.props.handleAction(event.currentTarget.dataset.action);
},
render: function() {
var cx = React.addons.classSet;
let blockAction = this.props.blocked ? "unblock" : "block";
let blockLabel = this.props.blocked ? "unblock_contact_menu_button"
: "block_contact_menu_button";
return (
React.DOM.ul({className: cx({ "dropdown-menu": true,
"dropdown-menu-up": this.state.openDirUp })},
React.DOM.li({className: cx({ "dropdown-menu-item": true,
"disabled": true }),
onClick: this.onItemClick, 'data-action': "video-call"},
React.DOM.i({className: "icon icon-video-call"}),
mozL10n.get("video_call_menu_button")
),
React.DOM.li({className: cx({ "dropdown-menu-item": true,
"disabled": true }),
onClick: this.onItemClick, 'data-action': "audio-call"},
React.DOM.i({className: "icon icon-audio-call"}),
mozL10n.get("audio_call_menu_button")
),
React.DOM.li({className: cx({ "dropdown-menu-item": true,
"disabled": !this.props.canEdit }),
onClick: this.onItemClick, 'data-action': "edit"},
React.DOM.i({className: "icon icon-edit"}),
mozL10n.get("edit_contact_menu_button")
),
React.DOM.li({className: "dropdown-menu-item",
onClick: this.onItemClick, 'data-action': blockAction},
React.DOM.i({className: "icon icon-" + blockAction}),
mozL10n.get(blockLabel)
),
React.DOM.li({className: cx({ "dropdown-menu-item": true,
"disabled": !this.props.canEdit }),
onClick: this.onItemClick, 'data-action': "remove"},
React.DOM.i({className: "icon icon-remove"}),
mozL10n.get("remove_contact_menu_button")
)
)
);
}
});
const ContactDetail = React.createClass({displayName: 'ContactDetail',
getInitialState: function() {
return {
showMenu: false,
};
},
propTypes: {
handleContactAction: React.PropTypes.func,
contact: React.PropTypes.object.isRequired
},
handleContactClick: function() {
if (this.props.handleContactClick) {
this.props.handleContactClick(this.props.key);
_onBodyClick: function() {
// Hide the menu after other click handlers have been invoked.
setTimeout(this.hideDropdownMenu, 10);
},
showDropdownMenu: function() {
document.body.addEventListener("click", this._onBodyClick);
this.setState({showMenu: true});
},
hideDropdownMenu: function() {
document.body.removeEventListener("click", this._onBodyClick);
// Since this call may be deferred, we need to guard it, for example in
// case the contact was removed in the meantime.
if (this.isMounted()) {
this.setState({showMenu: false});
}
},
componentWillUnmount: function() {
document.body.removeEventListener("click", this._onBodyClick);
},
handleAction: function(actionName) {
if (this.props.handleContactAction) {
this.props.handleContactAction(this.props.contact, actionName);
}
},
@ -56,6 +164,12 @@ loop.contacts = (function(_, mozL10n) {
return email;
},
canEdit: function() {
// We cannot modify imported contacts. For the moment, the check for
// determining whether the contact is imported is based on its category.
return this.props.contact.category[0] != "google";
},
render: function() {
let names = this.getContactNames();
let email = this.getPreferredEmail();
@ -66,7 +180,7 @@ loop.contacts = (function(_, mozL10n) {
});
return (
React.DOM.li({onClick: this.handleContactClick, className: contactCSSClass},
React.DOM.li({className: contactCSSClass, onMouseLeave: this.hideDropdownMenu},
React.DOM.div({className: "avatar"},
React.DOM.img({src: navigator.mozLoop.getUserAvatar(email.value)})
),
@ -78,9 +192,17 @@ loop.contacts = (function(_, mozL10n) {
React.DOM.div({className: "email"}, email.value)
),
React.DOM.div({className: "icons"},
React.DOM.i({className: "icon icon-video"}),
React.DOM.i({className: "icon icon-caret-down"})
)
React.DOM.i({className: "icon icon-video",
onClick: this.handleAction.bind(null, "video-call")}),
React.DOM.i({className: "icon icon-caret-down",
onClick: this.showDropdownMenu})
),
this.state.showMenu
? ContactDropdown({handleAction: this.handleAction,
canEdit: this.canEdit(),
blocked: this.props.contact.blocked})
: null
)
);
}
@ -158,6 +280,27 @@ loop.contacts = (function(_, mozL10n) {
this.props.startForm("contacts_add");
},
handleContactAction: function(contact, actionName) {
switch (actionName) {
case "edit":
this.props.startForm("contacts_edit", contact);
break;
case "remove":
case "block":
case "unblock":
// Invoke the API named like the action.
navigator.mozLoop.contacts[actionName](contact._guid, err => {
if (err) {
throw err;
}
});
break;
default:
console.error("Unrecognized action: " + actionName);
break;
}
},
sortContacts: function(contact1, contact2) {
let comp = contact1.name[0].localeCompare(contact2.name[0]);
if (comp !== 0) {
@ -170,17 +313,17 @@ loop.contacts = (function(_, mozL10n) {
render: function() {
let viewForItem = item => {
return ContactDetail({key: item._guid, contact: item})
return ContactDetail({key: item._guid, contact: item,
handleContactAction: this.handleContactAction})
};
let shownContacts = _.groupBy(this.state.contacts, function(contact) {
return contact.blocked ? "blocked" : "available";
});
// Buttons are temporarily hidden using "style".
return (
React.DOM.div(null,
React.DOM.div({className: "content-area", style: {display: "none"}},
React.DOM.div({className: "content-area"},
ButtonGroup(null,
Button({caption: mozL10n.get("import_contacts_button"),
disabled: true,
@ -223,7 +366,11 @@ loop.contacts = (function(_, mozL10n) {
initForm: function(contact) {
let state = this.getInitialState();
state.contact = contact || null;
if (contact) {
state.contact = contact;
state.name = contact.name[0];
state.email = contact.email[0].value;
}
this.setState(state);
},
@ -244,6 +391,13 @@ loop.contacts = (function(_, mozL10n) {
switch (this.props.mode) {
case "edit":
this.state.contact.name[0] = this.state.name.trim();
this.state.contact.email[0].value = this.state.email.trim();
contactsAPI.update(this.state.contact, err => {
if (err) {
throw err;
}
});
this.setState({
contact: null,
});
@ -275,7 +429,9 @@ loop.contacts = (function(_, mozL10n) {
let cx = React.addons.classSet;
return (
React.DOM.div({className: "content-area contact-form"},
React.DOM.header(null, mozL10n.get("add_contact_button")),
React.DOM.header(null, this.props.mode == "add"
? mozL10n.get("add_contact_button")
: mozL10n.get("edit_contact_title")),
React.DOM.label(null, mozL10n.get("edit_contact_name_label")),
React.DOM.input({ref: "name", required: true, pattern: "\\s*\\S.*",
className: cx({pristine: this.state.pristine}),
@ -289,7 +445,9 @@ loop.contacts = (function(_, mozL10n) {
caption: mozL10n.get("cancel_button"),
onClick: this.handleCancelButtonClick}),
Button({additionalClass: "button-accept",
caption: mozL10n.get("add_contact_button"),
caption: this.props.mode == "add"
? mozL10n.get("add_contact_button")
: mozL10n.get("edit_contact_done_button"),
onClick: this.handleAcceptButtonClick})
)
)

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

@ -17,15 +17,123 @@ loop.contacts = (function(_, mozL10n) {
// Number of contacts to add to the list at the same time.
const CONTACTS_CHUNK_SIZE = 100;
const ContactDetail = React.createClass({
const ContactDropdown = React.createClass({
propTypes: {
handleContactClick: React.PropTypes.func,
handleAction: React.PropTypes.func.isRequired,
canEdit: React.PropTypes.bool
},
getInitialState: function () {
return {
openDirUp: false,
};
},
componentDidMount: function () {
// This method is called once when the dropdown menu is added to the DOM
// inside the contact item. If the menu extends outside of the visible
// area of the scrollable list, it is re-rendered in different direction.
let menuNode = this.getDOMNode();
let menuNodeRect = menuNode.getBoundingClientRect();
let listNode = document.getElementsByClassName("contact-list")[0];
let listNodeRect = listNode.getBoundingClientRect();
if (menuNodeRect.top + menuNodeRect.height >=
listNodeRect.top + listNodeRect.height) {
this.setState({
openDirUp: true,
});
}
},
onItemClick: function(event) {
this.props.handleAction(event.currentTarget.dataset.action);
},
render: function() {
var cx = React.addons.classSet;
let blockAction = this.props.blocked ? "unblock" : "block";
let blockLabel = this.props.blocked ? "unblock_contact_menu_button"
: "block_contact_menu_button";
return (
<ul className={cx({ "dropdown-menu": true,
"dropdown-menu-up": this.state.openDirUp })}>
<li className={cx({ "dropdown-menu-item": true,
"disabled": true })}
onClick={this.onItemClick} data-action="video-call">
<i className="icon icon-video-call" />
{mozL10n.get("video_call_menu_button")}
</li>
<li className={cx({ "dropdown-menu-item": true,
"disabled": true })}
onClick={this.onItemClick} data-action="audio-call">
<i className="icon icon-audio-call" />
{mozL10n.get("audio_call_menu_button")}
</li>
<li className={cx({ "dropdown-menu-item": true,
"disabled": !this.props.canEdit })}
onClick={this.onItemClick} data-action="edit">
<i className="icon icon-edit" />
{mozL10n.get("edit_contact_menu_button")}
</li>
<li className="dropdown-menu-item"
onClick={this.onItemClick} data-action={blockAction}>
<i className={"icon icon-" + blockAction} />
{mozL10n.get(blockLabel)}
</li>
<li className={cx({ "dropdown-menu-item": true,
"disabled": !this.props.canEdit })}
onClick={this.onItemClick} data-action="remove">
<i className="icon icon-remove" />
{mozL10n.get("remove_contact_menu_button")}
</li>
</ul>
);
}
});
const ContactDetail = React.createClass({
getInitialState: function() {
return {
showMenu: false,
};
},
propTypes: {
handleContactAction: React.PropTypes.func,
contact: React.PropTypes.object.isRequired
},
handleContactClick: function() {
if (this.props.handleContactClick) {
this.props.handleContactClick(this.props.key);
_onBodyClick: function() {
// Hide the menu after other click handlers have been invoked.
setTimeout(this.hideDropdownMenu, 10);
},
showDropdownMenu: function() {
document.body.addEventListener("click", this._onBodyClick);
this.setState({showMenu: true});
},
hideDropdownMenu: function() {
document.body.removeEventListener("click", this._onBodyClick);
// Since this call may be deferred, we need to guard it, for example in
// case the contact was removed in the meantime.
if (this.isMounted()) {
this.setState({showMenu: false});
}
},
componentWillUnmount: function() {
document.body.removeEventListener("click", this._onBodyClick);
},
handleAction: function(actionName) {
if (this.props.handleContactAction) {
this.props.handleContactAction(this.props.contact, actionName);
}
},
@ -56,6 +164,12 @@ loop.contacts = (function(_, mozL10n) {
return email;
},
canEdit: function() {
// We cannot modify imported contacts. For the moment, the check for
// determining whether the contact is imported is based on its category.
return this.props.contact.category[0] != "google";
},
render: function() {
let names = this.getContactNames();
let email = this.getPreferredEmail();
@ -66,7 +180,7 @@ loop.contacts = (function(_, mozL10n) {
});
return (
<li onClick={this.handleContactClick} className={contactCSSClass}>
<li className={contactCSSClass} onMouseLeave={this.hideDropdownMenu}>
<div className="avatar">
<img src={navigator.mozLoop.getUserAvatar(email.value)} />
</div>
@ -78,9 +192,17 @@ loop.contacts = (function(_, mozL10n) {
<div className="email">{email.value}</div>
</div>
<div className="icons">
<i className="icon icon-video" />
<i className="icon icon-caret-down" />
<i className="icon icon-video"
onClick={this.handleAction.bind(null, "video-call")} />
<i className="icon icon-caret-down"
onClick={this.showDropdownMenu} />
</div>
{this.state.showMenu
? <ContactDropdown handleAction={this.handleAction}
canEdit={this.canEdit()}
blocked={this.props.contact.blocked} />
: null
}
</li>
);
}
@ -158,6 +280,27 @@ loop.contacts = (function(_, mozL10n) {
this.props.startForm("contacts_add");
},
handleContactAction: function(contact, actionName) {
switch (actionName) {
case "edit":
this.props.startForm("contacts_edit", contact);
break;
case "remove":
case "block":
case "unblock":
// Invoke the API named like the action.
navigator.mozLoop.contacts[actionName](contact._guid, err => {
if (err) {
throw err;
}
});
break;
default:
console.error("Unrecognized action: " + actionName);
break;
}
},
sortContacts: function(contact1, contact2) {
let comp = contact1.name[0].localeCompare(contact2.name[0]);
if (comp !== 0) {
@ -170,17 +313,17 @@ loop.contacts = (function(_, mozL10n) {
render: function() {
let viewForItem = item => {
return <ContactDetail key={item._guid} contact={item} />
return <ContactDetail key={item._guid} contact={item}
handleContactAction={this.handleContactAction} />
};
let shownContacts = _.groupBy(this.state.contacts, function(contact) {
return contact.blocked ? "blocked" : "available";
});
// Buttons are temporarily hidden using "style".
return (
<div>
<div className="content-area" style={{display: "none"}}>
<div className="content-area">
<ButtonGroup>
<Button caption={mozL10n.get("import_contacts_button")}
disabled
@ -223,7 +366,11 @@ loop.contacts = (function(_, mozL10n) {
initForm: function(contact) {
let state = this.getInitialState();
state.contact = contact || null;
if (contact) {
state.contact = contact;
state.name = contact.name[0];
state.email = contact.email[0].value;
}
this.setState(state);
},
@ -244,6 +391,13 @@ loop.contacts = (function(_, mozL10n) {
switch (this.props.mode) {
case "edit":
this.state.contact.name[0] = this.state.name.trim();
this.state.contact.email[0].value = this.state.email.trim();
contactsAPI.update(this.state.contact, err => {
if (err) {
throw err;
}
});
this.setState({
contact: null,
});
@ -275,7 +429,9 @@ loop.contacts = (function(_, mozL10n) {
let cx = React.addons.classSet;
return (
<div className="content-area contact-form">
<header>{mozL10n.get("add_contact_button")}</header>
<header>{this.props.mode == "add"
? mozL10n.get("add_contact_button")
: mozL10n.get("edit_contact_title")}</header>
<label>{mozL10n.get("edit_contact_name_label")}</label>
<input ref="name" required pattern="\s*\S.*"
className={cx({pristine: this.state.pristine})}
@ -289,7 +445,9 @@ loop.contacts = (function(_, mozL10n) {
caption={mozL10n.get("cancel_button")}
onClick={this.handleCancelButtonClick} />
<Button additionalClass="button-accept"
caption={mozL10n.get("add_contact_button")}
caption={this.props.mode == "add"
? mozL10n.get("add_contact_button")
: mozL10n.get("edit_contact_done_button")}
onClick={this.handleAcceptButtonClick} />
</ButtonGroup>
</div>

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

@ -6,8 +6,10 @@
border-top: 1px solid #ccc;
overflow-x: hidden;
overflow-y: auto;
/* Show six contacts and scroll for the rest */
max-height: 305px;
/* We need enough space to show the context menu of the first contact. */
min-height: 204px;
/* Show six contacts and scroll for the rest. */
max-height: 306px;
}
.contact,
@ -44,7 +46,7 @@
.contact:hover > .icons {
display: block;
z-index: 1000;
z-index: 1;
}
.contact > .avatar {
@ -146,6 +148,52 @@
height: 16px;
}
.contact > .dropdown-menu {
z-index: 2;
top: 10px;
bottom: auto;
right: 3em;
left: auto;
}
.contact > .dropdown-menu-up {
bottom: 10px;
top: auto;
}
.contact > .dropdown-menu > .dropdown-menu-item > .icon {
display: inline-block;
width: 20px;
height: 10px;
background-position: center left;
background-size: 10px 10px;
background-repeat: no-repeat;
}
.contact > .dropdown-menu > .dropdown-menu-item > .icon-audio-call {
background-image: url("../img/icons-16x16.svg#audio");
}
.contact > .dropdown-menu > .dropdown-menu-item > .icon-video-call {
background-image: url("../img/icons-16x16.svg#video");
}
.contact > .dropdown-menu > .dropdown-menu-item > .icon-edit {
background-image: url("../img/icons-16x16.svg#contacts");
}
.contact > .dropdown-menu > .dropdown-menu-item > .icon-block {
background-image: url("../img/icons-16x16.svg#block");
}
.contact > .dropdown-menu > .dropdown-menu-item > .icon-unblock {
background-image: url("../img/icons-16x16.svg#unblock");
}
.contact > .dropdown-menu > .dropdown-menu-item > .icon-remove {
background-image: url("../img/icons-16x16.svg#delete");
}
.contact-form > .button-group {
margin-top: 14px;
}

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

@ -38,12 +38,11 @@ PluginContent.prototype = {
global.addEventListener("PluginOutdated", this, true);
global.addEventListener("PluginInstantiated", this, true);
global.addEventListener("PluginRemoved", this, true);
global.addEventListener("pagehide", this, true);
global.addEventListener("pageshow", this, true);
global.addEventListener("unload", this);
global.addEventListener("pageshow", (event) => this.onPageShow(event), true);
global.addMessageListener("BrowserPlugins:ActivatePlugins", this);
global.addMessageListener("BrowserPlugins:NotificationRemoved", this);
global.addMessageListener("BrowserPlugins:NotificationShown", this);
global.addMessageListener("BrowserPlugins:ContextMenuCommand", this);
},
@ -58,9 +57,6 @@ PluginContent.prototype = {
case "BrowserPlugins:ActivatePlugins":
this.activatePlugins(msg.data.pluginInfo, msg.data.newState);
break;
case "BrowserPlugins:NotificationRemoved":
this.clearPluginDataCache();
break;
case "BrowserPlugins:NotificationShown":
setTimeout(() => this.updateNotificationUI(), 0);
break;
@ -79,7 +75,7 @@ PluginContent.prototype = {
onPageShow: function (event) {
// Ignore events that aren't from the main document.
if (this.global.content && event.target != this.global.content.document) {
if (!this.content || event.target != this.content.document) {
return;
}
@ -91,6 +87,15 @@ PluginContent.prototype = {
}
},
onPageHide: function (event) {
// Ignore events that aren't from the main document.
if (!this.content || event.target != this.content.document) {
return;
}
this.clearPluginDataCache();
},
getPluginUI: function (plugin, anonid) {
return plugin.ownerDocument.
getAnonymousElementByAttribute(plugin, "anonid", anonid);
@ -284,6 +289,16 @@ PluginContent.prototype = {
return;
}
if (eventType == "pagehide") {
this.onPageHide(event);
return;
}
if (eventType == "pageshow") {
this.onPageShow(event);
return;
}
if (eventType == "PluginRemoved") {
this.updateNotificationUI(event.target);
return;
@ -647,7 +662,7 @@ PluginContent.prototype = {
// If plugin is null, that means the user has navigated back to a page with
// plugins, and we need to collect all the plugins.
if (plugin === null) {
let contentWindow = this.global.content;
let contentWindow = this.content;
let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
// cwu.plugins may contain non-plugin <object>s, filter them out
@ -664,8 +679,9 @@ PluginContent.prototype = {
let pluginData = this.pluginData;
let principal = this.global.content.document.nodePrincipal;
let principal = this.content.document.nodePrincipal;
let principalHost = this._getHostFromPrincipal(principal);
let location = this.content.document.location.href;
for (let p of plugins) {
let pluginInfo = this._getPluginInfo(p);
@ -695,6 +711,7 @@ PluginContent.prototype = {
plugins: [... this.pluginData.values()],
showNow: showNow,
host: principalHost,
location: location,
}, null, principal);
},
@ -710,16 +727,13 @@ PluginContent.prototype = {
* to the current top-level document.
*/
updateNotificationUI: function (document) {
let principal;
document = document || this.content.document;
if (document) {
// We're only interested in the top-level document, since that's
// the one that provides the Principal that we send back to the
// parent.
principal = document.defaultView.top.document.nodePrincipal;
} else {
principal = this.content.document.nodePrincipal;
}
// We're only interested in the top-level document, since that's
// the one that provides the Principal that we send back to the
// parent.
let principal = document.defaultView.top.document.nodePrincipal;
let location = document.location.href;
// Make a copy of the actions from the last popup notification.
let haveInsecure = false;
@ -780,6 +794,7 @@ PluginContent.prototype = {
haveInsecure: haveInsecure,
actions: [... actions.values()],
host: this._getHostFromPrincipal(principal),
location: location,
}, null, principal);
},

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

@ -1468,14 +1468,16 @@ notification[value="translation"] menulist > .menulist-dropmarker {
}
.ac-result-type-keyword,
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage) {
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage),
richlistitem[type~="action"][actiontype="searchengine"] > .ac-title-box > .ac-site-icon {
list-style-image: url(chrome://global/skin/icons/autocomplete-search.svg#search-icon);
width: 16px;
height: 16px;
}
.ac-result-type-keyword[selected="true"],
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage, selected) {
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage, selected),
richlistitem[type~="action"][actiontype="searchengine"][selected="true"] > .ac-title-box > .ac-site-icon {
list-style-image: url(chrome://global/skin/icons/autocomplete-search.svg#search-icon-inverted);
}
@ -1505,14 +1507,6 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
padding: 0 3px;
}
richlistitem[type~="action"][actiontype="searchengine"] > .ac-title-box > .ac-site-icon {
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon");
}
richlistitem[type~="action"][actiontype="searchengine"][selected="true"] > .ac-title-box > .ac-site-icon {
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon-inverted");
}
.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {
color: GrayText;
}

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

@ -161,6 +161,19 @@ toolbarseparator {
z-index: 1;
}
/* Always draw a border on Yosemite to ensure the border is well-defined there
* (the default border is too light). */
@media (-moz-mac-yosemite-theme) {
#main-window[tabsintitlebar] #TabsToolbar:not([collapsed="true"]) + #nav-bar:not(:-moz-lwtheme) {
border-top: 1px solid hsla(0,0%,0%,.2);
background-clip: padding-box;
margin-top: -@tabToolbarNavbarOverlap@;
/* Position the toolbar above the bottom of background tabs */
position: relative;
z-index: 1;
}
}
#nav-bar-customization-target {
padding: 4px;
}
@ -2212,14 +2225,16 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
}
.ac-result-type-keyword,
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage) {
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage),
richlistitem[type~="action"][actiontype="searchengine"] > .ac-title-box > .ac-site-icon {
list-style-image: url(chrome://global/skin/icons/autocomplete-search.svg#search-icon);
width: 16px;
height: 16px;
}
.ac-result-type-keyword[selected="true"],
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage, selected) {
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage, selected),
richlistitem[type~="action"][actiontype="searchengine"][selected="true"] > .ac-title-box > .ac-site-icon {
list-style-image: url(chrome://global/skin/icons/autocomplete-search.svg#search-icon-inverted);
}
@ -2256,14 +2271,6 @@ richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-
-moz-image-region: rect(11px, 16px, 22px, 0);
}
richlistitem[type~="action"][actiontype="searchengine"] > .ac-title-box > .ac-site-icon {
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon");
}
richlistitem[type~="action"][actiontype="searchengine"][selected="true"] > .ac-title-box > .ac-site-icon {
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon-inverted");
}
@media (min-resolution: 2dppx) {
.ac-result-type-bookmark {
list-style-image: url("chrome://browser/skin/places/star-icons@2x.png");

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

@ -1394,7 +1394,8 @@ richlistitem[selected="true"][current="true"] > .ac-title-box > .ac-result-type-
}
.ac-result-type-keyword,
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage) {
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage),
richlistitem[type~="action"][actiontype="searchengine"] > .ac-title-box > .ac-site-icon {
list-style-image: url(chrome://global/skin/icons/autocomplete-search.svg#search-icon);
width: 16px;
height: 16px;
@ -1404,7 +1405,8 @@ richlistitem[selected="true"][current="true"] > .ac-title-box > .ac-result-type-
@media not all and (-moz-windows-default-theme) {
%endif
.ac-result-type-keyword[selected="true"],
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage, selected) {
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage, selected),
richlistitem[type~="action"][actiontype="searchengine"][selected="true"] > .ac-title-box > .ac-site-icon {
list-style-image: url(chrome://global/skin/icons/autocomplete-search.svg#search-icon-inverted);
}
%ifdef WINDOWS_AERO
@ -1463,20 +1465,6 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
}
%endif
richlistitem[type~="action"][actiontype="searchengine"] > .ac-title-box > .ac-site-icon {
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon");
}
%ifdef WINDOWS_AERO
@media not all and (-moz-windows-default-theme) {
%endif
richlistitem[type~="action"][actiontype="searchengine"][selected="true"] > .ac-title-box > .ac-site-icon {
list-style-image: url("chrome://global/skin/icons/autocomplete-search.svg#search-icon-inverted");
}
%ifdef WINDOWS_AERO
}
%endif
.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {
color: GrayText;
}

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

@ -27,6 +27,7 @@
#include "nsRadioInterfaceLayer.h"
#include "nsServiceManagerUtils.h"
#include "nsThreadUtils.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/SettingChangeNotificationBinding.h"
#define MOZSETTINGS_CHANGED_ID "mozsettings-changed"

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

@ -23,6 +23,7 @@
#include "nsIObserverService.h"
#include "nsISettingsService.h"
#include "nsServiceManagerUtils.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/SettingChangeNotificationBinding.h"
#ifdef MOZ_B2G_RIL

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

@ -50,7 +50,6 @@ const NFCCONTENTHELPER_CID =
const NFC_IPC_MSG_NAMES = [
"NFC:ReadNDEFResponse",
"NFC:WriteNDEFResponse",
"NFC:GetDetailsNDEFResponse",
"NFC:MakeReadOnlyNDEFResponse",
"NFC:ConnectResponse",
"NFC:CloseResponse",
@ -64,17 +63,6 @@ XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsISyncMessageSender");
function GetDetailsNDEFResponse(details) {
this.canBeMadeReadOnly = details.canBeMadeReadOnly;
this.isReadOnly = details.isReadOnly;
this.maxSupportedLength = details.maxSupportedLength;
}
GetDetailsNDEFResponse.prototype = {
__exposedProps__ : {canBeMadeReadOnly: 'r',
isReadOnly: 'r',
maxSupportedLength: 'r'}
};
function NfcContentHelper() {
this.initDOMRequestHelper(/* aWindow */ null, NFC_IPC_MSG_NAMES);
Services.obs.addObserver(this, "xpcom-shutdown", false);
@ -127,22 +115,6 @@ NfcContentHelper.prototype = {
},
// NFCTag interface
getDetailsNDEF: function getDetailsNDEF(window, sessionToken) {
if (window == null) {
throw Components.Exception("Can't get window object",
Cr.NS_ERROR_UNEXPECTED);
}
let request = Services.DOMRequest.createRequest(window);
let requestId = btoa(this.getRequestId(request));
this._requestMap[requestId] = window;
cpmm.sendAsyncMessage("NFC:GetDetailsNDEF", {
requestId: requestId,
sessionToken: sessionToken
});
return request;
},
readNDEF: function readNDEF(window, sessionToken) {
if (window == null) {
throw Components.Exception("Can't get window object",
@ -395,9 +367,6 @@ NfcContentHelper.prototype = {
case "NFC:ReadNDEFResponse":
this.handleReadNDEFResponse(result);
break;
case "NFC:GetDetailsNDEFResponse":
this.handleGetDetailsNDEFResponse(result);
break;
case "NFC:CheckP2PRegistrationResponse":
this.handleCheckP2PRegistrationResponse(result);
break;
@ -452,16 +421,6 @@ NfcContentHelper.prototype = {
this.fireRequestSuccess(requestId, ndefMsg);
},
handleGetDetailsNDEFResponse: function handleGetDetailsNDEFResponse(result) {
if (result.errorMsg) {
this.fireRequestError(atob(result.requestId), result.errorMsg);
return;
}
let requestId = atob(result.requestId);
this.fireRequestSuccess(requestId, new GetDetailsNDEFResponse(result));
},
handleCheckP2PRegistrationResponse: function handleCheckP2PRegistrationResponse(result) {
// Privilaged status API. Always fire success to avoid using exposed props.
// The receiver must check the boolean mapped status code to handle.

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

@ -57,7 +57,6 @@ const NFC_IPC_MSG_NAMES = [
const NFC_IPC_READ_PERM_MSG_NAMES = [
"NFC:ReadNDEF",
"NFC:GetDetailsNDEF",
"NFC:Connect",
"NFC:Close",
];
@ -263,7 +262,7 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
if (message.name == "child-process-shutdown") {
this.removePeerTarget(message.target);
this.nfc.removeTarget(message.target);
this.removeEventTarget(msg.target);
this.removeEventTarget(message.target);
return null;
}
@ -538,7 +537,6 @@ Nfc.prototype = {
break;
case "ConnectResponse": // Fall through.
case "CloseResponse":
case "GetDetailsNDEFResponse":
case "ReadNDEFResponse":
case "MakeReadOnlyNDEFResponse":
case "WriteNDEFResponse":
@ -608,9 +606,6 @@ Nfc.prototype = {
this.setConfig({powerLevel: NFC.NFC_POWER_LEVEL_DISABLED,
requestId: message.data.requestId});
break;
case "NFC:GetDetailsNDEF":
this.sendToNfcService("getDetailsNDEF", message.data);
break;
case "NFC:ReadNDEF":
this.sendToNfcService("readNDEF", message.data);
break;

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

@ -8,13 +8,12 @@
namespace mozilla {
#define NFCD_MAJOR_VERSION 1
#define NFCD_MINOR_VERSION 9
#define NFCD_MINOR_VERSION 10
enum NfcRequest {
ConfigReq = 0,
ConnectReq,
CloseReq,
GetDetailsNDEFReq,
ReadNDEFReq,
WriteNDEFReq,
MakeReadOnlyNDEFReq,
@ -23,7 +22,6 @@ enum NfcRequest {
enum NfcResponse {
GeneralRsp = 1000,
ConfigRsp,
GetDetailsNDEFRsp,
ReadNDEFRsp,
};

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

@ -17,7 +17,6 @@ using namespace mozilla;
using namespace mozilla::dom;
static const char* kConfigRequest = "config";
static const char* kGetDetailsNDEF = "getDetailsNDEF";
static const char* kReadNDEFRequest = "readNDEF";
static const char* kWriteNDEFRequest = "writeNDEF";
static const char* kMakeReadOnlyNDEFRequest = "makeReadOnlyNDEF";
@ -25,7 +24,6 @@ static const char* kConnectRequest = "connect";
static const char* kCloseRequest = "close";
static const char* kConfigResponse = "ConfigResponse";
static const char* kGetDetailsNDEFResponse = "GetDetailsNDEFResponse";
static const char* kReadNDEFResponse = "ReadNDEFResponse";
static const char* kWriteNDEFResponse = "WriteNDEFResponse";
static const char* kMakeReadOnlyNDEFResponse = "MakeReadOnlyNDEFResponse";
@ -46,8 +44,6 @@ NfcMessageHandler::Marshall(Parcel& aParcel, const CommandOptions& aOptions)
if (!strcmp(type, kConfigRequest)) {
result = ConfigRequest(aParcel, aOptions);
} else if (!strcmp(type, kGetDetailsNDEF)) {
result = GetDetailsNDEFRequest(aParcel, aOptions);
} else if (!strcmp(type, kReadNDEFRequest)) {
result = ReadNDEFRequest(aParcel, aOptions);
} else if (!strcmp(type, kWriteNDEFRequest)) {
@ -83,9 +79,6 @@ NfcMessageHandler::Unmarshall(const Parcel& aParcel, EventOptions& aOptions)
case NfcResponse::ConfigRsp:
result = ConfigResponse(aParcel, aOptions);
break;
case NfcResponse::GetDetailsNDEFRsp:
result = GetDetailsNDEFResponse(aParcel, aOptions);
break;
case NfcResponse::ReadNDEFRsp:
result = ReadNDEFResponse(aParcel, aOptions);
break;
@ -171,35 +164,6 @@ NfcMessageHandler::ConfigResponse(const Parcel& aParcel, EventOptions& aOptions)
return true;
}
bool
NfcMessageHandler::GetDetailsNDEFRequest(Parcel& aParcel, const CommandOptions& aOptions)
{
aParcel.writeInt32(NfcRequest::GetDetailsNDEFReq);
aParcel.writeInt32(aOptions.mSessionId);
mRequestIdQueue.AppendElement(aOptions.mRequestId);
return true;
}
bool
NfcMessageHandler::GetDetailsNDEFResponse(const Parcel& aParcel, EventOptions& aOptions)
{
aOptions.mType = NS_ConvertUTF8toUTF16(kGetDetailsNDEFResponse);
aOptions.mStatus = aParcel.readInt32();
aOptions.mSessionId = aParcel.readInt32();
if (aOptions.mStatus == NfcErrorCode::Success) {
int readOnly = aParcel.readInt32();
aOptions.mIsReadOnly = readOnly & 0xff;
aOptions.mCanBeMadeReadOnly = (readOnly >> 8) & 0xff;
aOptions.mMaxSupportedLength = aParcel.readInt32();
}
NS_ENSURE_TRUE(!mRequestIdQueue.IsEmpty(), false);
aOptions.mRequestId = mRequestIdQueue[0];
mRequestIdQueue.RemoveElementAt(0);
return true;
}
bool
NfcMessageHandler::ReadNDEFRequest(Parcel& aParcel, const CommandOptions& aOptions)
{

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

@ -27,8 +27,6 @@ private:
bool GeneralResponse(const android::Parcel& aParcel, EventOptions& aOptions);
bool ConfigRequest(android::Parcel& aParcel, const CommandOptions& options);
bool ConfigResponse(const android::Parcel& aParcel, EventOptions& aOptions);
bool GetDetailsNDEFRequest(android::Parcel& aParcel, const CommandOptions& options);
bool GetDetailsNDEFResponse(const android::Parcel& aParcel, EventOptions& aOptions);
bool ReadNDEFRequest(android::Parcel& aParcel, const CommandOptions& options);
bool ReadNDEFResponse(const android::Parcel& aParcel, EventOptions& aOptions);
bool WriteNDEFRequest(android::Parcel& aParcel, const CommandOptions& options);

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

@ -27,7 +27,7 @@ interface nsINfcDOMEventTarget : nsISupports
void notifyPeerLost(in DOMString sessionToken);
};
[scriptable, uuid(7eaf4c31-e1d1-422e-aa55-181f4eb156b0)]
[scriptable, uuid(d3f1bdc1-048f-44a8-abe2-bc386edce40b)]
interface nsINfcContentHelper : nsISupports
{
const long NFC_EVENT_PEER_READY = 0x01;
@ -35,7 +35,6 @@ interface nsINfcContentHelper : nsISupports
boolean checkSessionToken(in DOMString sessionToken);
nsIDOMDOMRequest getDetailsNDEF(in nsIDOMWindow window, in DOMString sessionToken);
nsIDOMDOMRequest readNDEF(in nsIDOMWindow window, in DOMString sessionToken);
nsIDOMDOMRequest writeNDEF(in nsIDOMWindow window, in nsIVariant records, in DOMString sessionToken);
nsIDOMDOMRequest makeReadOnlyNDEF(in nsIDOMWindow window, in DOMString sessionToken);

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

@ -14,6 +14,7 @@ const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
Cu.import("resource://gre/modules/IndexedDBHelper.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.importGlobalProperties(["indexedDB"]);
XPCOMUtils.defineLazyServiceGetter(this, "appsService",
"@mozilla.org/AppsService;1",

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

@ -2650,6 +2650,7 @@ bool AsyncPanZoomController::IsCurrentlyCheckerboarding() const {
CSSPoint currentScrollOffset = mFrameMetrics.GetScrollOffset() + mTestAsyncScrollOffset;
CSSRect painted = mLastContentPaintMetrics.mDisplayPort + mLastContentPaintMetrics.GetScrollOffset();
painted.Inflate(CSSMargin::FromAppUnits(nsMargin(1, 1, 1, 1))); // fuzz for rounding error
CSSRect visible = CSSRect(currentScrollOffset, mFrameMetrics.CalculateCompositedSizeInCssPixels());
return !painted.Contains(visible);
}

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

@ -389,7 +389,8 @@ mozJSComponentLoader::ReallyInit()
// XXXkhuey B2G child processes have some sort of preferences race that
// results in getting the wrong value.
// But we don't want that on Firefox Mulet as it break most Firefox JSMs...
#if defined(MOZ_B2G) && !defined(MOZ_MULET)
// Also disable on debug builds to break js components that rely on this.
#if defined(MOZ_B2G) && !defined(MOZ_MULET) && !defined(DEBUG)
mReuseLoaderGlobal = true;
#endif

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

@ -139,6 +139,13 @@ public class GeckoAppShell
private static final Queue<GeckoEvent> PENDING_EVENTS = new ConcurrentLinkedQueue<GeckoEvent>();
private static final Map<String, String> ALERT_COOKIES = new ConcurrentHashMap<String, String>();
@SuppressWarnings("serial")
private static final List<String> UNKNOWN_MIME_TYPES = new ArrayList<String>(3) {{
add("application/octet-stream"); // This will be used as a default mime type for unknown files
add("application/unknown");
add("application/octet-stream"); // Github uses this for APK files
}};
private static volatile boolean locationHighAccuracyEnabled;
// Accessed by NotificationHelper. This should be encapsulated.
@ -1795,24 +1802,41 @@ public class GeckoAppShell
@WrapElementForJNI
public static void scanMedia(final String aFile, String aMimeType) {
String mimeType = aMimeType;
if (UNKNOWN_MIME_TYPES.contains(mimeType)) {
// If this is a generic undefined mimetype, erase it so that we can try to determine
// one from the file extension below.
mimeType = "";
}
// If the platform didn't give us a mimetype, try to guess one from the filename
if (TextUtils.isEmpty(aMimeType)) {
if (TextUtils.isEmpty(mimeType)) {
int extPosition = aFile.lastIndexOf(".");
if (extPosition > 0 && extPosition < aFile.length() - 1) {
aMimeType = getMimeTypeFromExtension(aFile.substring(extPosition+1));
mimeType = getMimeTypeFromExtension(aFile.substring(extPosition+1));
}
}
// addCompletedDownload will throw if it received any null parameters. Use aMimeType or a default
// if we still don't have one.
if (TextUtils.isEmpty(mimeType)) {
if (TextUtils.isEmpty(aMimeType)) {
mimeType = UNKNOWN_MIME_TYPES.get(0);
} else {
mimeType = aMimeType;
}
}
final File f = new File(aFile);
if (AppConstants.ANDROID_DOWNLOADS_INTEGRATION) {
final File f = new File(aFile);
final DownloadManager dm = (DownloadManager) getContext().getSystemService(Context.DOWNLOAD_SERVICE);
dm.addCompletedDownload(f.getName(),
f.getName(),
!TextUtils.isEmpty(aMimeType),
true, // Media scanner should scan this
aMimeType,
f.getAbsolutePath(),
f.length(),
false);
Math.max(0, f.length()),
false); // Don't show a notification.
} else {
Context context = getContext();
GeckoMediaScannerClient.startScan(context, aFile, aMimeType);

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

@ -37,7 +37,7 @@ import android.util.Log;
public class GeckoNetworkManager extends BroadcastReceiver implements NativeEventListener {
private static final String LOGTAG = "GeckoNetworkManager";
static private GeckoNetworkManager sInstance = new GeckoNetworkManager();
static private GeckoNetworkManager sInstance;
public static void destroy() {
if (sInstance != null) {
@ -90,6 +90,10 @@ public class GeckoNetworkManager extends BroadcastReceiver implements NativeEven
private volatile Context mApplicationContext;
public static GeckoNetworkManager getInstance() {
if (sInstance == null) {
sInstance = new GeckoNetworkManager();
}
return sInstance;
}

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

@ -9,11 +9,18 @@ import java.util.Set;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.AppConstants.Versions;
import java.lang.StringBuilder;
import java.util.ArrayList;
import java.util.List;
import java.util.HashSet;
import org.mozilla.gecko.mozglue.RobocopTarget;
import org.mozilla.gecko.AppConstants.Versions;
import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.os.UserManager;
import android.util.Log;
@ -22,7 +29,34 @@ import android.util.Log;
public class RestrictedProfiles {
private static final String LOGTAG = "GeckoRestrictedProfiles";
// These constants should be in sync with the ones from toolkit/components/parentalcontrols/nsIParentalControlServices.java
private static Boolean inGuest = null;
@SuppressWarnings("serial")
private static final List<String> BANNED_SCHEMES = new ArrayList<String>() {{
add("file");
add("chrome");
add("resource");
add("jar");
add("wyciwyg");
}};
private static boolean getInGuest() {
if (inGuest == null) {
inGuest = GeckoAppShell.getGeckoInterface().getProfile().inGuestMode();
}
return inGuest;
}
@SuppressWarnings("serial")
private static final List<String> BANNED_URLS = new ArrayList<String>() {{
add("about:config");
}};
/* This is a list of things we can restrict you from doing. Some of these are reflected in Android UserManager constants.
* Others are specific to us.
* These constants should be in sync with the ones from toolkit/components/parentalcontrols/nsIParentalControlServices.idl
*/
public static enum Restriction {
DISALLOW_DOWNLOADS(1, "no_download_files"),
DISALLOW_INSTALL_EXTENSIONS(2, "no_install_extensions"),
@ -43,10 +77,10 @@ public class RestrictedProfiles {
}
}
private static String geckoActionToRestriction(int action) {
private static Restriction geckoActionToRestriction(int action) {
for (Restriction rest : Restriction.values()) {
if (rest.id == action) {
return rest.name;
return rest;
}
}
@ -59,10 +93,42 @@ public class RestrictedProfiles {
return mgr.getUserRestrictions();
}
private static boolean canLoadUrl(final String url) {
// Null urls are always allowed
if (url == null) {
return true;
}
try {
// If we're not in guest mode, and the system restriction isn't in place, everything is allowed.
if (!getInGuest() &&
!getRestrictions().getBoolean(Restriction.DISALLOW_BROWSE_FILES.name, false)) {
return true;
}
} catch(IllegalArgumentException ex) {
Log.i(LOGTAG, "Invalid action", ex);
}
final Uri u = Uri.parse(url);
final String scheme = u.getScheme();
if (BANNED_SCHEMES.contains(scheme)) {
return false;
}
for (String banned : BANNED_URLS) {
if (url.startsWith(banned)) {
return false;
}
}
// TODO: The UserManager should support blacklisting urls by the device owner.
return true;
}
@WrapElementForJNI
public static boolean isUserRestricted() {
// Guest mode is supported in all Android versions
if (GeckoAppShell.getGeckoInterface().getProfile().inGuestMode()) {
if (getInGuest()) {
return true;
}
@ -79,8 +145,19 @@ public class RestrictedProfiles {
@WrapElementForJNI
public static boolean isAllowed(int action, String url) {
final Restriction restriction;
try {
restriction = geckoActionToRestriction(action);
} catch(IllegalArgumentException ex) {
return true;
}
if (Restriction.DISALLOW_BROWSE_FILES == restriction) {
return canLoadUrl(url);
}
// ALl actions are blocked in Guest mode
if (GeckoAppShell.getGeckoInterface().getProfile().inGuestMode()) {
if (getInGuest()) {
return false;
}
@ -90,8 +167,7 @@ public class RestrictedProfiles {
try {
// NOTE: Restrictions hold the opposite intention, so we need to flip it
final String restriction = geckoActionToRestriction(action);
return !getRestrictions().getBoolean(restriction, false);
return !getRestrictions().getBoolean(restriction.name, false);
} catch(IllegalArgumentException ex) {
Log.i(LOGTAG, "Invalid action", ex);
}
@ -102,7 +178,7 @@ public class RestrictedProfiles {
@WrapElementForJNI
public static String getUserRestrictions() {
// Guest mode is supported in all Android versions
if (GeckoAppShell.getGeckoInterface().getProfile().inGuestMode()) {
if (getInGuest()) {
StringBuilder builder = new StringBuilder("{ ");
for (Restriction restriction : Restriction.values()) {

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

@ -32,7 +32,7 @@ public class testAppMenuPathways extends UITest {
message.put("baseDomain", "webmfiles.org");
message.put("type", "Content:LocationChange");
message.put("sameDocument", false);
message.put("userSearch", "");
message.put("userRequested", "");
message.put("uri", getAbsoluteIpUrl("/big-buck-bunny_trailer.webm"));
message.put("tabID", 0);
} catch (Exception ex) {

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

@ -4218,16 +4218,12 @@ Tab.prototype = {
} catch (ex) { }
// In restricted profiles, we refuse to let you open any file urls.
if (!ParentalControls.isAllowed(ParentalControls.VISIT_FILE_URLS)) {
let bannedSchemes = ["file", "chrome", "resource", "jar", "wyciwyg"];
if (!ParentalControls.isAllowed(ParentalControls.VISIT_FILE_URLS, fixedURI)) {
aRequest.cancel(Cr.NS_BINDING_ABORTED);
if (bannedSchemes.indexOf(fixedURI.scheme) > -1) {
aRequest.cancel(Cr.NS_BINDING_ABORTED);
aRequest = this.browser.docShell.displayLoadError(Cr.NS_ERROR_UNKNOWN_PROTOCOL, fixedURI, null);
if (aRequest) {
fixedURI = aRequest.URI;
}
aRequest = this.browser.docShell.displayLoadError(Cr.NS_ERROR_UNKNOWN_PROTOCOL, fixedURI, null);
if (aRequest) {
fixedURI = aRequest.URI;
}
}

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

@ -116,6 +116,7 @@ nsAutoCompleteController::SetInput(nsIAutoCompleteInput *aInput)
// Reset all search state members to default values
mSearchString = newValue;
mPlaceholderCompletionString.Truncate();
mDefaultIndexCompleted = false;
mBackspaced = false;
mSearchStatus = nsIAutoCompleteController::STATUS_NONE;
@ -230,8 +231,10 @@ nsAutoCompleteController::HandleText()
// We need to throw away previous results so we don't try to search through them again
ClearResults();
mBackspaced = true;
} else
mPlaceholderCompletionString.Truncate();
} else {
mBackspaced = false;
}
mSearchString = newValue;
@ -1111,6 +1114,46 @@ nsAutoCompleteController::StopSearch()
return NS_OK;
}
void
nsAutoCompleteController::MaybeCompletePlaceholder()
{
MOZ_ASSERT(mInput);
if (!mInput) { // or mInput depending on what you choose
MOZ_ASSERT_UNREACHABLE("Input should always be valid at this point");
return;
}
int32_t selectionStart;
mInput->GetSelectionStart(&selectionStart);
int32_t selectionEnd;
mInput->GetSelectionEnd(&selectionEnd);
// Check if the current input should be completed with the placeholder string
// from the last completion until the actual search results come back.
// The new input string needs to be compatible with the last completed string.
// E.g. if the new value is "fob", but the last completion was "foobar",
// then the last completion is incompatible.
// If the search string is the same as the last completion value, then don't
// complete the value again (this prevents completion to happen e.g. if the
// cursor is moved and StartSeaches() is invoked).
// In addition, the selection must be at the end of the current input to
// trigger the placeholder completion.
bool usePlaceholderCompletion =
!mPlaceholderCompletionString.IsEmpty() &&
mPlaceholderCompletionString.Length() > mSearchString.Length() &&
selectionEnd == selectionStart &&
selectionEnd == (int32_t)mSearchString.Length() &&
StringBeginsWith(mPlaceholderCompletionString, mSearchString,
nsCaseInsensitiveStringComparator());
if (usePlaceholderCompletion) {
CompleteValue(mPlaceholderCompletionString);
} else {
mPlaceholderCompletionString.Truncate();
}
}
nsresult
nsAutoCompleteController::StartSearches()
{
@ -1120,6 +1163,10 @@ nsAutoCompleteController::StartSearches()
if (mTimer || !mInput)
return NS_OK;
// Check if the current input should be completed with the placeholder string
// from the last completion until the actual search results come back.
MaybeCompletePlaceholder();
nsCOMPtr<nsIAutoCompleteInput> input(mInput);
// Get the timeout for delayed searches.
@ -1457,10 +1504,18 @@ nsAutoCompleteController::CompleteDefaultIndex(int32_t aResultIndex)
int32_t selectionEnd;
input->GetSelectionEnd(&selectionEnd);
bool isPlaceholderSelected =
selectionEnd == (int32_t)mPlaceholderCompletionString.Length() &&
selectionStart == (int32_t)mSearchString.Length() &&
StringBeginsWith(mPlaceholderCompletionString,
mSearchString, nsCaseInsensitiveStringComparator());
// Don't try to automatically complete to the first result if there's already
// a selection or the cursor isn't at the end of the input
if (selectionEnd != selectionStart ||
selectionEnd != (int32_t)mSearchString.Length())
// a selection or the cursor isn't at the end of the input. In case the
// selection is from the current placeholder completion value, then still
// automatically complete.
if (!isPlaceholderSelected && (selectionEnd != selectionStart ||
selectionEnd != (int32_t)mSearchString.Length()))
return NS_OK;
bool shouldComplete;
@ -1603,6 +1658,7 @@ nsAutoCompleteController::CompleteValue(nsString &aValue)
// aValue is empty (we were asked to clear mInput), or mSearchString
// matches the beginning of aValue. In either case we can simply
// autocomplete to aValue.
mPlaceholderCompletionString = aValue;
input->SetTextValue(aValue);
} else {
nsresult rv;
@ -1623,9 +1679,9 @@ nsAutoCompleteController::CompleteValue(nsString &aValue)
return NS_OK;
}
input->SetTextValue(mSearchString +
Substring(aValue, mSearchStringLength + findIndex,
endSelect));
mPlaceholderCompletionString = mSearchString +
Substring(aValue, mSearchStringLength + findIndex, endSelect);
input->SetTextValue(mPlaceholderCompletionString);
endSelect -= findIndex; // We're skipping this many characters of aValue.
} else {
@ -1635,6 +1691,9 @@ nsAutoCompleteController::CompleteValue(nsString &aValue)
input->SetTextValue(mSearchString + NS_LITERAL_STRING(" >> ") + aValue);
endSelect = mSearchString.Length() + 4 + aValue.Length();
// Reset the last search completion.
mPlaceholderCompletionString.Truncate();
}
}

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

@ -48,6 +48,7 @@ protected:
nsresult StartSearches();
void AfterSearches();
nsresult ClearSearchTimer();
void MaybeCompletePlaceholder();
nsresult ProcessResult(int32_t aSearchIndex, nsIAutoCompleteResult *aResult);
nsresult PostSearchCleanup();
@ -134,6 +135,7 @@ protected:
nsCOMPtr<nsITreeBoxObject> mTree;
nsString mSearchString;
nsString mPlaceholderCompletionString;
bool mDefaultIndexCompleted;
bool mBackspaced;
bool mPopupClosedByCompositionStart;

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

@ -957,6 +957,18 @@ this.PlacesDBUtils = {
{ histogram: "PLACES_ANNOS_PAGES_SIZE_KB",
query: "SELECT SUM(LENGTH(content))/1024 FROM moz_annos" },
{ histogram: "PLACES_MAINTENANCE_DAYSFROMLAST",
callback: function () {
try {
let lastMaintenance = Services.prefs.getIntPref("places.database.lastMaintenance");
let nowSeconds = parseInt(Date.now() / 1000);
return parseInt((nowSeconds - lastMaintenance) / 86400);
} catch (ex) {
return 60;
}
}
},
];
let params = {

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

@ -1921,6 +1921,7 @@ XPCOMUtils.defineLazyGetter(this, "gAsyncDBConnPromised", () => {
catch(ex) {
// It's too late to block shutdown, just close the connection.
return conn.close();
throw (ex);
}
return Promise.resolve();
}).then(null, Cu.reportError);

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

@ -11,7 +11,6 @@
const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
const TOPIC_SHUTDOWN = "places-shutdown";
const TOPIC_PREFCHANGED = "nsPref:changed";
const DEFAULT_BEHAVIOR = 0;
@ -629,7 +628,9 @@ Search.prototype = {
},
/**
* Used to cancel this search, will stop providing results.
* Cancels this search.
* After invoking this method, we won't run any more searches or heuristics,
* and no new matches may be added to the current result.
*/
cancel: function () {
if (this._sleepTimer)
@ -980,6 +981,10 @@ Search.prototype = {
break;
}
this._addMatch(match);
// If the search has been canceled by the user or by _addMatch reaching the
// maximum number of results, we can stop the underlying Sqlite query.
if (!this.pending)
throw StopIteration;
},
_maybeRestyleSearchMatch: function (match) {
@ -1041,22 +1046,19 @@ Search.prototype = {
match.comment,
match.icon || PlacesUtils.favicons.defaultFavicon.spec,
match.style,
match.finalCompleteValue);
match.finalCompleteValue || "");
notifyResults = true;
}
if (this._result.matchCount == 6)
TelemetryStopwatch.finish(TELEMETRY_6_FIRST_RESULTS);
if (this._result.matchCount == Prefs.maxRichResults || !this.pending) {
if (this._result.matchCount == Prefs.maxRichResults) {
// We have enough results, so stop running our search.
// We don't need to notify results in this case, cause the main promise
// chain will do that for us when finishSearch is invoked.
this.cancel();
// This tells Sqlite.jsm to stop providing us results and cancel the
// underlying query.
throw StopIteration;
}
if (notifyResults) {
} else if (notifyResults) {
// Notify about results if we've gotten them.
this.notifyResults(true);
}
@ -1460,19 +1462,9 @@ Search.prototype = {
//// component @mozilla.org/autocomplete/search;1?name=unifiedcomplete
function UnifiedComplete() {
Services.obs.addObserver(this, TOPIC_SHUTDOWN, true);
}
UnifiedComplete.prototype = {
//////////////////////////////////////////////////////////////////////////////
//// nsIObserver
observe: function (subject, topic, data) {
if (topic === TOPIC_SHUTDOWN) {
this.ensureShutdown();
}
},
//////////////////////////////////////////////////////////////////////////////
//// Database handling
@ -1497,6 +1489,18 @@ UnifiedComplete.prototype = {
readOnly: true
});
try {
Sqlite.shutdown.addBlocker("Places UnifiedComplete.js clone closing",
Task.async(function* () {
SwitchToTabStorage.shutdown();
yield conn.close();
}));
} catch (ex) {
// It's too late to block shutdown, just close the connection.
yield conn.close();
throw ex;
}
// Autocomplete often fallbacks to a table scan due to lack of text
// indices. A larger cache helps reducing IO and improving performance.
// The value used here is larger than the default Storage value defined
@ -1512,20 +1516,6 @@ UnifiedComplete.prototype = {
return this._promiseDatabase;
},
/**
* Used to stop running queries and close the database handle.
*/
ensureShutdown: function () {
if (this._promiseDatabase) {
Task.spawn(function* () {
let conn = yield this.getDatabaseHandle();
SwitchToTabStorage.shutdown();
yield conn.close()
}.bind(this)).then(null, Cu.reportError);
this._promiseDatabase = null;
}
},
//////////////////////////////////////////////////////////////////////////////
//// mozIPlacesAutoComplete

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

@ -27,6 +27,7 @@ let histograms = {
PLACES_ANNOS_PAGES_COUNT: function (val) do_check_eq(val, 1),
PLACES_ANNOS_PAGES_SIZE_KB: function (val) do_check_eq(val, 1),
PLACES_FRECENCY_CALC_TIME_MS: function (val) do_check_true(val >= 0),
PLACES_MAINTENANCE_DAYSFROMLAST: function (val) do_check_true(val >= 0),
}
function run_test()

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

@ -3408,6 +3408,14 @@
"extended_statistics_ok": true,
"description": "PLACES: Time to calculate frecency of a page (ms)"
},
"PLACES_MAINTENANCE_DAYSFROMLAST": {
"expires_in_version" : "never",
"kind": "exponential",
"low": 7,
"high": 60,
"n_buckets" : 10,
"description": "PLACES: Days from last maintenance"
},
"UPDATER_BACKGROUND_CHECK_CODE_EXTERNAL": {
"expires_in_version": "default",
"kind": "enumerated",

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

@ -55,6 +55,7 @@ support-files =
[test_autocomplete_delayOnPaste.xul]
[test_autocomplete_with_composition_on_input.html]
[test_autocomplete_with_composition_on_textbox.xul]
[test_autocomplete_placehold_last_complete.xul]
[test_browser_drop.xul]
skip-if = buildapp == 'mulet'
[test_bug253481.xul]

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

@ -0,0 +1,309 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
<window title="Autocomplete Widget Test"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="runTest();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
<script type="application/javascript"
src="chrome://global/content/globalOverlay.js"/>
<textbox id="autocomplete"
type="autocomplete"
completedefaultindex="true"
timeout="0"
autocompletesearch="simple"/>
<script class="testbody" type="application/javascript">
<![CDATA[
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
function autoCompleteSimpleResult(aString, searchId) {
this.searchString = aString;
this.searchResult = Components.interfaces.nsIAutoCompleteResult.RESULT_SUCCESS;
this.matchCount = 1;
if (aString.startsWith('ret')) {
this._param = autoCompleteSimpleResult.retireCompletion;
} else {
this._param = "Result";
}
this._searchId = searchId;
}
autoCompleteSimpleResult.retireCompletion = "Retire";
autoCompleteSimpleResult.prototype = {
_param: "",
searchString: null,
searchResult: Components.interfaces.nsIAutoCompleteResult.RESULT_FAILURE,
defaultIndex: 0,
errorDescription: null,
matchCount: 0,
getValueAt: function() { return this._param; },
getCommentAt: function() { return null; },
getStyleAt: function() { return null; },
getImageAt: function() { return null; },
getLabelAt: function() { return null; },
removeValueAt: function() {}
};
var searchCounter = 0;
// A basic autocomplete implementation that returns one result.
let autoCompleteSimple = {
classID: Components.ID("0a2afbdb-f30e-47d1-9cb1-0cd160240aca"),
contractID: "@mozilla.org/autocomplete/search;1?name=simple",
searchAsync: false,
pendingSearch: null,
QueryInterface: XPCOMUtils.generateQI([
Components.interfaces.nsIFactory,
Components.interfaces.nsIAutoCompleteSearch
]),
createInstance: function (outer, iid) {
return this.QueryInterface(iid);
},
registerFactory: function () {
let registrar =
Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
registrar.registerFactory(this.classID, "Test Simple Autocomplete",
this.contractID, this);
},
unregisterFactory: function () {
let registrar =
Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
registrar.unregisterFactory(this.classID, this);
},
startSearch: function (aString, aParam, aResult, aListener) {
let result = new autoCompleteSimpleResult(aString);
if (this.searchAsync) {
// Simulate an async search by using a timeout before invoking the
// |onSearchResult| callback.
// Store the searchTimeout such that it can be canceled if stopSearch is called.
this.pendingSearch = setTimeout(() => {
this.pendingSearch = null;
aListener.onSearchResult(this, result);
// Move to the next step in the async test.
asyncTest.next();
}, 0);
} else {
aListener.onSearchResult(this, result);
}
},
stopSearch: function () {
clearTimeout(this.pendingSearch);
}
};
SimpleTest.waitForExplicitFinish();
// XPFE AutoComplete needs to register early.
autoCompleteSimple.registerFactory();
let gACTimer;
let gAutoComplete;
let asyncTest;
let searchCompleteTimeoutId = null;
function finishTest() {
// Unregister the factory so that we don't get in the way of other tests
autoCompleteSimple.unregisterFactory();
SimpleTest.finish();
}
function runTest() {
gAutoComplete = $("autocomplete");
gAutoComplete.focus();
// Return the search results synchronous, which also makes the completion
// happen synchronous.
autoCompleteSimple.searchAsync = false;
synthesizeKey("r", {});
is(gAutoComplete.value, "result", "Value should be autocompleted immediately");
synthesizeKey("e", {});
is(gAutoComplete.value, "result", "Value should be autocompleted immediately");
synthesizeKey("VK_DELETE", {});
is(gAutoComplete.value, "re", "Deletion should not complete value");
synthesizeKey("VK_BACK_SPACE", {});
is(gAutoComplete.value, "r", "Backspace should not complete value");
synthesizeKey("VK_LEFT", {});
is(gAutoComplete.value, "r", "Value should stay same when navigating with cursor");
runAsyncTest();
}
function* asyncTestGenerator() {
synthesizeKey("r", {});
synthesizeKey("e", {});
is(gAutoComplete.value, "re", "Value should not be autocompleted immediately");
// Calling |yield undefined| makes this generator function wait until
// |asyncTest.next();| is called. This happens from within the
// |autoCompleteSimple.startSearch()| function once the simulated async
// search has finished.
// Therefore, the effect of the |yield undefined;| here (and the ones) below
// is to wait until the async search result comes back.
yield undefined;
is(gAutoComplete.value, "result", "Value should be autocompleted");
// Test if typing the `s` character completes directly based on the last
// completion
synthesizeKey("s", {});
is(gAutoComplete.value, "result", "Value should be completed immediately");
yield undefined;
is(gAutoComplete.value, "result", "Value should be autocompleted to same value");
synthesizeKey("VK_DELETE", {});
is(gAutoComplete.value, "res", "Deletion should not complete value");
// No |yield undefined| needed here as no completion is triggered by the deletion.
is(gAutoComplete.value, "res", "Still no complete value after deletion");
synthesizeKey("VK_BACK_SPACE", {});
is(gAutoComplete.value, "re", "Backspace should not complete value");
yield undefined;
is(gAutoComplete.value, "re", "Value after search due to backspace should stay the same"); (3)
// Typing a character that is not like the previous match. In this case, the
// completion cannot happen directly and therefore the value will be completed
// only after the search has finished.
synthesizeKey("t", {});
is(gAutoComplete.value, "ret", "Value should not be autocompleted immediately");
yield undefined;
is(gAutoComplete.value, "retire", "Value should be autocompleted");
synthesizeKey("i", {});
is(gAutoComplete.value, "retire", "Value should be autocompleted immediately");
yield undefined;
is(gAutoComplete.value, "retire", "Value should be autocompleted to the same value");
// Setup the scene to test how the completion behaves once the placeholder
// completion and the result from the search do not agree with each other.
gAutoComplete.value = 'r';
// Need to type two characters as the input was reset and the autocomplete
// controller things, ther user hit the backspace button, in which case
// no completion is performed. But as a completion is desired, another
// character `t` is typed afterwards.
synthesizeKey("e", {});
yield undefined;
synthesizeKey("t", {});
is(gAutoComplete.value, "ret", "Value should not be autocompleted");
yield undefined;
is(gAutoComplete.value, "retire", "Value should be autocompleted");
// The placeholder string is now set to "retire". Changing the completion
// string to "retirement" and see what the completion will turn out like.
autoCompleteSimpleResult.retireCompletion = "Retirement";
synthesizeKey("i", {});
is(gAutoComplete.value, "retire", "Value should be autocompleted based on placeholder");
yield undefined;
is(gAutoComplete.value, "retirement", "Value should be autocompleted based on search result");
// Change the search result to `Retire` again and see if the new result is
// complited.
autoCompleteSimpleResult.retireCompletion = "Retire";
synthesizeKey("r", {});
is(gAutoComplete.value, "retirement", "Value should be autocompleted based on placeholder");
yield undefined;
is(gAutoComplete.value, "retire", "Value should be autocompleted based on search result");
// Complete the value
gAutoComplete.value = 're';
synthesizeKey("t", {});
yield undefined;
synthesizeKey("i", {});
is(gAutoComplete.value, "reti", "Value should not be autocompleted");
yield undefined;
is(gAutoComplete.value, "retire", "Value should be autocompleted");
// Remove the selected text "re" (1) and the "et" (2). Afterwards, add it again (3).
// This should not cause the completion to kick in.
synthesizeKey("VK_DELETE", {}); // (1)
is(gAutoComplete.value, "reti", "Value should not complete after deletion");
gAutoComplete.selectionStart = 1;
gAutoComplete.selectionEnd = 3;
synthesizeKey("VK_DELETE", {}); // (2)
is(gAutoComplete.value, "ri", "Value should stay unchanged after removing character in the middle");
yield undefined;
synthesizeKey("e", {}); // (3.1)
is(gAutoComplete.value, "rei", "Inserting a character in the middle should not complete the value");
yield undefined;
synthesizeKey("t", {}); // (3.2)
is(gAutoComplete.value, "reti", "Inserting a character in the middle should not complete the value");
yield undefined;
// Adding a new character at the end should not cause the completion to happen again
// as the completion failed before.
gAutoComplete.selectionStart = 4;
gAutoComplete.selectionEnd = 4;
synthesizeKey("r", {});
is(gAutoComplete.value, "retir", "Value should not be autocompleted immediately");
yield undefined;
is(gAutoComplete.value, "retire", "Value should be autocompleted");
finishTest();
yield undefined;
}
function runAsyncTest() {
gAutoComplete.value = '';
autoCompleteSimple.searchAsync = true;
asyncTest = asyncTestGenerator();
asyncTest.next();
}
]]>
</script>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display">
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</window>

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

@ -200,7 +200,7 @@ void
LogDispatch(uint64_t aTaskId, uint64_t aParentTaskId, uint64_t aSourceEventId,
SourceEventType aSourceEventType)
{
NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId);
NS_ENSURE_TRUE_VOID(IsInitialized());
// Log format:
// [0 taskId dispatchTime sourceEventId sourceEventType parentTaskId]
@ -209,7 +209,7 @@ LogDispatch(uint64_t aTaskId, uint64_t aParentTaskId, uint64_t aSourceEventId,
void
LogBegin(uint64_t aTaskId, uint64_t aSourceEventId)
{
NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId);
NS_ENSURE_TRUE_VOID(IsInitialized());
// Log format:
// [1 taskId beginTime processId threadId]
@ -218,7 +218,7 @@ LogBegin(uint64_t aTaskId, uint64_t aSourceEventId)
void
LogEnd(uint64_t aTaskId, uint64_t aSourceEventId)
{
NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId);
NS_ENSURE_TRUE_VOID(IsInitialized());
// Log format:
// [2 taskId endTime]
@ -227,7 +227,7 @@ LogEnd(uint64_t aTaskId, uint64_t aSourceEventId)
void
LogVirtualTablePtr(uint64_t aTaskId, uint64_t aSourceEventId, int* aVptr)
{
NS_ENSURE_TRUE_VOID(IsInitialized() && aSourceEventId);
NS_ENSURE_TRUE_VOID(IsInitialized());
// Log format:
// [4 taskId address]

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

@ -349,8 +349,13 @@ IsExpired(const MultiTouchInput& aTouch)
void
GeckoTouchDispatcher::DispatchTouchEvent(MultiTouchInput& aMultiTouch)
{
if (aMultiTouch.mType == MultiTouchInput::MULTITOUCH_START &&
if ((aMultiTouch.mType == MultiTouchInput::MULTITOUCH_END ||
aMultiTouch.mType == MultiTouchInput::MULTITOUCH_CANCEL) &&
aMultiTouch.mTouches.Length() == 1) {
MutexAutoLock lock(mTouchQueueLock);
mTouchMoveEvents.clear();
} else if (aMultiTouch.mType == MultiTouchInput::MULTITOUCH_START &&
aMultiTouch.mTouches.Length() == 1) {
mTouchEventsFiltered = IsExpired(aMultiTouch);
}