зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound.
This commit is contained in:
Коммит
6735b2344d
|
@ -12,7 +12,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="258ae6472bd0e87ae074a6b9b464273dc9cfc8d6"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ac06cfbd2baf6494ffbb668cc599e3892cd5e17b"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
<project name="platform/system/vold" path="system/vold" revision="919829940468066a32f403980b43f6ebfee5d314"/>
|
<project name="platform/system/vold" path="system/vold" revision="919829940468066a32f403980b43f6ebfee5d314"/>
|
||||||
<!-- Emulator specific things -->
|
<!-- Emulator specific things -->
|
||||||
<project name="android-development" path="development" remote="b2g" revision="4e236e65a5d652a66ac32590f69f2123d17cb4ad"/>
|
<project name="android-development" path="development" remote="b2g" revision="4e236e65a5d652a66ac32590f69f2123d17cb4ad"/>
|
||||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="5be0a9c4b3c6c004786917fdb5bee248960d045b"/>
|
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="e7e8734fdd8bf41e48a56c1c85e0f7dac60aaa9f"/>
|
||||||
<project name="platform/external/iproute2" path="external/iproute2" revision="c66c5716d5335e450f7a7b71ccc6a604fb2f41d2"/>
|
<project name="platform/external/iproute2" path="external/iproute2" revision="c66c5716d5335e450f7a7b71ccc6a604fb2f41d2"/>
|
||||||
<project name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="d2685281e2e54ca14d1df304867aa82c37b27162"/>
|
<project name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="d2685281e2e54ca14d1df304867aa82c37b27162"/>
|
||||||
<project name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="627f9b20fc518937b93747a7ff1ed4f5ed46e06f"/>
|
<project name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="627f9b20fc518937b93747a7ff1ed4f5ed46e06f"/>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="258ae6472bd0e87ae074a6b9b464273dc9cfc8d6"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="ac06cfbd2baf6494ffbb668cc599e3892cd5e17b"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="258ae6472bd0e87ae074a6b9b464273dc9cfc8d6"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ac06cfbd2baf6494ffbb668cc599e3892cd5e17b"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
<project name="platform/system/vold" path="system/vold" revision="919829940468066a32f403980b43f6ebfee5d314"/>
|
<project name="platform/system/vold" path="system/vold" revision="919829940468066a32f403980b43f6ebfee5d314"/>
|
||||||
<!-- Emulator specific things -->
|
<!-- Emulator specific things -->
|
||||||
<project name="android-development" path="development" remote="b2g" revision="4e236e65a5d652a66ac32590f69f2123d17cb4ad"/>
|
<project name="android-development" path="development" remote="b2g" revision="4e236e65a5d652a66ac32590f69f2123d17cb4ad"/>
|
||||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="5be0a9c4b3c6c004786917fdb5bee248960d045b"/>
|
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="e7e8734fdd8bf41e48a56c1c85e0f7dac60aaa9f"/>
|
||||||
<project name="platform/external/iproute2" path="external/iproute2" revision="c66c5716d5335e450f7a7b71ccc6a604fb2f41d2"/>
|
<project name="platform/external/iproute2" path="external/iproute2" revision="c66c5716d5335e450f7a7b71ccc6a604fb2f41d2"/>
|
||||||
<project name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="d2685281e2e54ca14d1df304867aa82c37b27162"/>
|
<project name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="d2685281e2e54ca14d1df304867aa82c37b27162"/>
|
||||||
<project name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="627f9b20fc518937b93747a7ff1ed4f5ed46e06f"/>
|
<project name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="627f9b20fc518937b93747a7ff1ed4f5ed46e06f"/>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
"revision": "8d15cd3ac0d07cde9ff36ce611ae47e6ef30d9b0",
|
"revision": "a8b221aeef715c5d8159faa5b31f3ee15e5c3c5a",
|
||||||
"repo_path": "/integration/gaia-central"
|
"repo_path": "/integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="258ae6472bd0e87ae074a6b9b464273dc9cfc8d6"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ac06cfbd2baf6494ffbb668cc599e3892cd5e17b"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="258ae6472bd0e87ae074a6b9b464273dc9cfc8d6"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ac06cfbd2baf6494ffbb668cc599e3892cd5e17b"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="258ae6472bd0e87ae074a6b9b464273dc9cfc8d6"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ac06cfbd2baf6494ffbb668cc599e3892cd5e17b"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="258ae6472bd0e87ae074a6b9b464273dc9cfc8d6"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ac06cfbd2baf6494ffbb668cc599e3892cd5e17b"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="258ae6472bd0e87ae074a6b9b464273dc9cfc8d6"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="ac06cfbd2baf6494ffbb668cc599e3892cd5e17b"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="3d5c964015967ca8c86abe6dbbebee3cb82b1609"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a314508e397c8f1814228d36259ea8708034444e"/>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="258ae6472bd0e87ae074a6b9b464273dc9cfc8d6"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="ac06cfbd2baf6494ffbb668cc599e3892cd5e17b"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="78b908b493bfe0b477e3d4f6edec8c46a2c0d096"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
|
||||||
|
|
|
@ -468,7 +468,6 @@ pref("browser.tabs.closeButtons", 1);
|
||||||
pref("browser.tabs.selectOwnerOnClose", true);
|
pref("browser.tabs.selectOwnerOnClose", true);
|
||||||
|
|
||||||
pref("browser.ctrlTab.previews", false);
|
pref("browser.ctrlTab.previews", false);
|
||||||
pref("browser.ctrlTab.recentlyUsedLimit", 7);
|
|
||||||
|
|
||||||
// By default, do not export HTML at shutdown.
|
// By default, do not export HTML at shutdown.
|
||||||
// If true, at shutdown the bookmarks in your menu and toolbar will
|
// If true, at shutdown the bookmarks in your menu and toolbar will
|
||||||
|
@ -1371,6 +1370,9 @@ pref("identity.fxaccounts.remote.uri", "https://accounts.firefox.com/?service=sy
|
||||||
// should be fetched. Must use HTTPS.
|
// should be fetched. Must use HTTPS.
|
||||||
pref("identity.fxaccounts.remote.force_auth.uri", "https://accounts.firefox.com/force_auth?service=sync&context=fx_desktop_v1");
|
pref("identity.fxaccounts.remote.force_auth.uri", "https://accounts.firefox.com/force_auth?service=sync&context=fx_desktop_v1");
|
||||||
|
|
||||||
|
// The remote content URL shown for signin in. Must use HTTPS.
|
||||||
|
pref("identity.fxaccounts.remote.signin.uri", "https://accounts.firefox.com/signin?service=sync&context=fx_desktop_v1");
|
||||||
|
|
||||||
// The URL we take the user to when they opt to "manage" their Firefox Account.
|
// The URL we take the user to when they opt to "manage" their Firefox Account.
|
||||||
// Note that this will always need to be in the same TLD as the
|
// Note that this will always need to be in the same TLD as the
|
||||||
// "identity.fxaccounts.remote.uri" pref.
|
// "identity.fxaccounts.remote.uri" pref.
|
||||||
|
|
|
@ -250,6 +250,9 @@ function openPrefs() {
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
if (window.location.href.contains("action=signin")) {
|
if (window.location.href.contains("action=signin")) {
|
||||||
|
show("remote");
|
||||||
|
wrapper.init(fxAccounts.getAccountsSignInURI());
|
||||||
|
} else if (window.location.href.contains("action=signup")) {
|
||||||
show("remote");
|
show("remote");
|
||||||
wrapper.init();
|
wrapper.init();
|
||||||
} else if (window.location.href.contains("action=reauth")) {
|
} else if (window.location.href.contains("action=reauth")) {
|
||||||
|
|
|
@ -161,10 +161,6 @@ var ctrlTab = {
|
||||||
delete this.previews;
|
delete this.previews;
|
||||||
return this.previews = this.panel.getElementsByClassName("ctrlTab-preview");
|
return this.previews = this.panel.getElementsByClassName("ctrlTab-preview");
|
||||||
},
|
},
|
||||||
get recentlyUsedLimit () {
|
|
||||||
delete this.recentlyUsedLimit;
|
|
||||||
return this.recentlyUsedLimit = gPrefService.getIntPref("browser.ctrlTab.recentlyUsedLimit");
|
|
||||||
},
|
|
||||||
get keys () {
|
get keys () {
|
||||||
var keys = {};
|
var keys = {};
|
||||||
["close", "find", "selectAll"].forEach(function (key) {
|
["close", "find", "selectAll"].forEach(function (key) {
|
||||||
|
@ -187,31 +183,7 @@ var ctrlTab = {
|
||||||
get canvasHeight () Math.round(this.canvasWidth * tabPreviews.aspectRatio),
|
get canvasHeight () Math.round(this.canvasWidth * tabPreviews.aspectRatio),
|
||||||
|
|
||||||
get tabList () {
|
get tabList () {
|
||||||
if (this._tabList)
|
return this._recentlyUsedTabs;
|
||||||
return this._tabList;
|
|
||||||
|
|
||||||
// Using gBrowser.tabs instead of gBrowser.visibleTabs, as the latter
|
|
||||||
// exlcudes closing tabs, breaking the following loop in case the the
|
|
||||||
// selected tab is closing.
|
|
||||||
let list = Array.filter(gBrowser.tabs, function (tab) !tab.hidden);
|
|
||||||
|
|
||||||
// Rotate the list until the selected tab is first
|
|
||||||
while (!list[0].selected)
|
|
||||||
list.push(list.shift());
|
|
||||||
|
|
||||||
list = list.filter(function (tab) !tab.closing);
|
|
||||||
|
|
||||||
if (this.recentlyUsedLimit != 0) {
|
|
||||||
let recentlyUsedTabs = this._recentlyUsedTabs;
|
|
||||||
if (this.recentlyUsedLimit > 0)
|
|
||||||
recentlyUsedTabs = this._recentlyUsedTabs.slice(0, this.recentlyUsedLimit);
|
|
||||||
for (let i = recentlyUsedTabs.length - 1; i >= 0; i--) {
|
|
||||||
list.splice(list.indexOf(recentlyUsedTabs[i]), 1);
|
|
||||||
list.unshift(recentlyUsedTabs[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._tabList = list;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
init: function ctrlTab_init() {
|
init: function ctrlTab_init() {
|
||||||
|
@ -340,6 +312,9 @@ var ctrlTab = {
|
||||||
},
|
},
|
||||||
|
|
||||||
attachTab: function ctrlTab_attachTab(aTab, aPos) {
|
attachTab: function ctrlTab_attachTab(aTab, aPos) {
|
||||||
|
if (aTab.closing)
|
||||||
|
return;
|
||||||
|
|
||||||
if (aPos == 0)
|
if (aPos == 0)
|
||||||
this._recentlyUsedTabs.unshift(aTab);
|
this._recentlyUsedTabs.unshift(aTab);
|
||||||
else if (aPos)
|
else if (aPos)
|
||||||
|
@ -347,6 +322,7 @@ var ctrlTab = {
|
||||||
else
|
else
|
||||||
this._recentlyUsedTabs.push(aTab);
|
this._recentlyUsedTabs.push(aTab);
|
||||||
},
|
},
|
||||||
|
|
||||||
detachTab: function ctrlTab_detachTab(aTab) {
|
detachTab: function ctrlTab_detachTab(aTab) {
|
||||||
var i = this._recentlyUsedTabs.indexOf(aTab);
|
var i = this._recentlyUsedTabs.indexOf(aTab);
|
||||||
if (i >= 0)
|
if (i >= 0)
|
||||||
|
@ -417,8 +393,6 @@ var ctrlTab = {
|
||||||
Array.forEach(this.previews, function (preview) {
|
Array.forEach(this.previews, function (preview) {
|
||||||
this.updatePreview(preview, null);
|
this.updatePreview(preview, null);
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
this._tabList = null;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onKeyPress: function ctrlTab_onKeyPress(event) {
|
onKeyPress: function ctrlTab_onKeyPress(event) {
|
||||||
|
@ -472,7 +446,6 @@ var ctrlTab = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._tabList = null;
|
|
||||||
this.updatePreviews();
|
this.updatePreviews();
|
||||||
|
|
||||||
if (this.selected.hidden)
|
if (this.selected.hidden)
|
||||||
|
|
|
@ -46,7 +46,7 @@ var gConnectionsDialog = {
|
||||||
proxyTypeChanged: function ()
|
proxyTypeChanged: function ()
|
||||||
{
|
{
|
||||||
var proxyTypePref = document.getElementById("network.proxy.type");
|
var proxyTypePref = document.getElementById("network.proxy.type");
|
||||||
|
|
||||||
// Update http
|
// Update http
|
||||||
var httpProxyURLPref = document.getElementById("network.proxy.http");
|
var httpProxyURLPref = document.getElementById("network.proxy.http");
|
||||||
httpProxyURLPref.disabled = proxyTypePref.value != 1;
|
httpProxyURLPref.disabled = proxyTypePref.value != 1;
|
||||||
|
@ -58,10 +58,11 @@ var gConnectionsDialog = {
|
||||||
|
|
||||||
var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings");
|
var shareProxiesPref = document.getElementById("network.proxy.share_proxy_settings");
|
||||||
shareProxiesPref.disabled = proxyTypePref.value != 1;
|
shareProxiesPref.disabled = proxyTypePref.value != 1;
|
||||||
|
var autologinProxyPref = document.getElementById("signon.autologin.proxy");
|
||||||
|
autologinProxyPref.disabled = proxyTypePref.value == 0;
|
||||||
var noProxiesPref = document.getElementById("network.proxy.no_proxies_on");
|
var noProxiesPref = document.getElementById("network.proxy.no_proxies_on");
|
||||||
noProxiesPref.disabled = proxyTypePref.value != 1;
|
noProxiesPref.disabled = proxyTypePref.value != 1;
|
||||||
|
|
||||||
var autoconfigURLPref = document.getElementById("network.proxy.autoconfig_url");
|
var autoconfigURLPref = document.getElementById("network.proxy.autoconfig_url");
|
||||||
autoconfigURLPref.disabled = proxyTypePref.value != 2;
|
autoconfigURLPref.disabled = proxyTypePref.value != 2;
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,10 @@
|
||||||
<preference id="network.proxy.share_proxy_settings"
|
<preference id="network.proxy.share_proxy_settings"
|
||||||
name="network.proxy.share_proxy_settings"
|
name="network.proxy.share_proxy_settings"
|
||||||
type="bool"/>
|
type="bool"/>
|
||||||
|
<preference id="signon.autologin.proxy"
|
||||||
|
name="signon.autologin.proxy"
|
||||||
|
type="bool"/>
|
||||||
|
|
||||||
<preference id="pref.advanced.proxies.disable_button.reload"
|
<preference id="pref.advanced.proxies.disable_button.reload"
|
||||||
name="pref.advanced.proxies.disable_button.reload"
|
name="pref.advanced.proxies.disable_button.reload"
|
||||||
type="bool"/>
|
type="bool"/>
|
||||||
|
@ -159,6 +162,13 @@
|
||||||
</hbox>
|
</hbox>
|
||||||
</radiogroup>
|
</radiogroup>
|
||||||
</groupbox>
|
</groupbox>
|
||||||
|
<separator class="thin"/>
|
||||||
|
<checkbox id="autologinProxy"
|
||||||
|
label="&autologinproxy.label;"
|
||||||
|
accesskey="&autologinproxy.accesskey;"
|
||||||
|
preference="signon.autologin.proxy"
|
||||||
|
tooltiptext="&autologinproxy.tooltip;"/>
|
||||||
|
<separator/>
|
||||||
</prefpane>
|
</prefpane>
|
||||||
</prefwindow>
|
</prefwindow>
|
||||||
|
|
||||||
|
|
|
@ -256,6 +256,10 @@ let gSyncPane = {
|
||||||
window.close();
|
window.close();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
signUp: function() {
|
||||||
|
this.openContentInBrowser("about:accounts?action=signup");
|
||||||
|
},
|
||||||
|
|
||||||
signIn: function() {
|
signIn: function() {
|
||||||
this.openContentInBrowser("about:accounts?action=signin");
|
this.openContentInBrowser("about:accounts?action=signin");
|
||||||
},
|
},
|
||||||
|
|
|
@ -188,7 +188,7 @@
|
||||||
<vbox id="noFxaAccount">
|
<vbox id="noFxaAccount">
|
||||||
<description>&welcome.description;</description>
|
<description>&welcome.description;</description>
|
||||||
<label class="text-link"
|
<label class="text-link"
|
||||||
onclick="gSyncPane.signIn(); return false;"
|
onclick="gSyncPane.signUp(); return false;"
|
||||||
value="&welcome.createAccount.label;"/>
|
value="&welcome.createAccount.label;"/>
|
||||||
<label class="text-link"
|
<label class="text-link"
|
||||||
onclick="gSyncPane.signIn(); return false;"
|
onclick="gSyncPane.signIn(); return false;"
|
||||||
|
@ -207,7 +207,7 @@
|
||||||
<deck id="fxaLoginStatus">
|
<deck id="fxaLoginStatus">
|
||||||
|
|
||||||
<!-- logged in and verified and all is good -->
|
<!-- logged in and verified and all is good -->
|
||||||
<hbox flex="1">
|
<hbox>
|
||||||
<label id="fxaEmailAddress1"/>
|
<label id="fxaEmailAddress1"/>
|
||||||
<label class="text-link"
|
<label class="text-link"
|
||||||
onclick="gSyncPane.manageFirefoxAccount();"
|
onclick="gSyncPane.manageFirefoxAccount();"
|
||||||
|
|
|
@ -67,7 +67,10 @@
|
||||||
<p class="project-validation valid">&projects.valid;</p>
|
<p class="project-validation valid">&projects.valid;</p>
|
||||||
<p class="project-validation warning">&projects.warning;</p>
|
<p class="project-validation warning">&projects.warning;</p>
|
||||||
<p class="project-validation error">&projects.error;</p>
|
<p class="project-validation error">&projects.error;</p>
|
||||||
<p class="project-type" template='{"type":"textContent","path":"type"}'></p>
|
</div>
|
||||||
|
<div class="project-status" template='{"type":"attribute","path":"type","name":"type"}'>
|
||||||
|
<p class="project-type hosted">&projects.hosted;</p>
|
||||||
|
<p class="project-type packaged">&projects.packaged;</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span template='{"type":"textContent","path":"manifest.developer.name"}'></span>
|
<span template='{"type":"textContent","path":"manifest.developer.name"}'></span>
|
||||||
|
|
|
@ -133,10 +133,11 @@ Spectrum.rgbToHsv = function(r, g, b, a) {
|
||||||
Spectrum.getOffset = function(el) {
|
Spectrum.getOffset = function(el) {
|
||||||
let curleft = 0, curtop = 0;
|
let curleft = 0, curtop = 0;
|
||||||
if (el.offsetParent) {
|
if (el.offsetParent) {
|
||||||
do {
|
while (el) {
|
||||||
curleft += el.offsetLeft;
|
curleft += el.offsetLeft;
|
||||||
curtop += el.offsetTop;
|
curtop += el.offsetTop;
|
||||||
} while (el = el.offsetParent);
|
el = el.offsetParent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
left: curleft,
|
left: curleft,
|
||||||
|
|
|
@ -83,6 +83,8 @@
|
||||||
<!ENTITY projects.valid "Valid">
|
<!ENTITY projects.valid "Valid">
|
||||||
<!ENTITY projects.error "Error">
|
<!ENTITY projects.error "Error">
|
||||||
<!ENTITY projects.warning "Warning">
|
<!ENTITY projects.warning "Warning">
|
||||||
|
<!ENTITY projects.hosted "Hosted">
|
||||||
|
<!ENTITY projects.packaged "Packaged">
|
||||||
|
|
||||||
<!ENTITY help.title "App Manager">
|
<!ENTITY help.title "App Manager">
|
||||||
<!ENTITY help.close "Close">
|
<!ENTITY help.close "Close">
|
||||||
|
|
|
@ -44,3 +44,6 @@
|
||||||
<!ENTITY noproxyExplain.label "Example: .mozilla.org, .net.nz, 192.168.1.0/24">
|
<!ENTITY noproxyExplain.label "Example: .mozilla.org, .net.nz, 192.168.1.0/24">
|
||||||
<!ENTITY shareproxy.label "Use this proxy server for all protocols">
|
<!ENTITY shareproxy.label "Use this proxy server for all protocols">
|
||||||
<!ENTITY shareproxy.accesskey "s">
|
<!ENTITY shareproxy.accesskey "s">
|
||||||
|
<!ENTITY autologinproxy.label "Do not prompt for authentication if password is saved">
|
||||||
|
<!ENTITY autologinproxy.accesskey "a">
|
||||||
|
<!ENTITY autologinproxy.tooltip "This option silently authenticates you to proxies when you have saved credentials for them. You will be prompted if authentication fails.">
|
||||||
|
|
|
@ -15,15 +15,32 @@
|
||||||
|
|
||||||
<content>
|
<content>
|
||||||
<xul:stack>
|
<xul:stack>
|
||||||
<xul:toolbarbutton anonid="progressButton" class="circularprogressindicator-progressButton"/>
|
<xul:toolbarbutton anonid="progressButton"
|
||||||
<html:div anonid="progressTrack" xbl:inherits="progress" class="circularprogressindicator-progressTrack"></html:div>
|
class="circularprogressindicator-progressButton"/>
|
||||||
<html:canvas anonid="progressRing" xbl:inherits="progress" class="circularprogressindicator-progressRing" width="40" height="40"></html:canvas>
|
<html:div anonid="progressTrack"
|
||||||
|
xbl:inherits="progress"
|
||||||
|
class="circularprogressindicator-progressTrack">
|
||||||
|
</html:div>
|
||||||
|
<html:canvas anonid="progressRing"
|
||||||
|
xbl:inherits="progress"
|
||||||
|
class="circularprogressindicator-progressRing"
|
||||||
|
width="40"
|
||||||
|
height="40">
|
||||||
|
</html:canvas>
|
||||||
|
<html:div anonid="progressNotification"
|
||||||
|
xbl:inherits="progress"
|
||||||
|
class="circularprogressindicator-progressNotification">
|
||||||
|
</html:div>
|
||||||
</xul:stack>
|
</xul:stack>
|
||||||
</content>
|
</content>
|
||||||
|
|
||||||
<implementation>
|
<implementation>
|
||||||
<field name="_progressCanvas">
|
<field name="_progressCanvas">
|
||||||
document.getAnonymousElementByAttribute(this, "anonid", "progressRing");
|
document.getAnonymousElementByAttribute(this, "anonid", "progressRing");
|
||||||
|
</field>
|
||||||
|
<field name="_progressNotification">
|
||||||
|
document.getAnonymousElementByAttribute(this, "anonid",
|
||||||
|
"progressNotification");
|
||||||
</field>
|
</field>
|
||||||
<field name="_progressCircleCtx">null</field>
|
<field name="_progressCircleCtx">null</field>
|
||||||
<field name="_img">null</field>
|
<field name="_img">null</field>
|
||||||
|
@ -92,6 +109,26 @@
|
||||||
]]>
|
]]>
|
||||||
</body>
|
</body>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="notify">
|
||||||
|
<body>
|
||||||
|
<![CDATA[
|
||||||
|
this.addEventListener("transitionend", this._onNotificationEnd);
|
||||||
|
|
||||||
|
this._progressNotification.classList.add(
|
||||||
|
"progressNotification-active");
|
||||||
|
]]>
|
||||||
|
</body>
|
||||||
|
</method>
|
||||||
|
<method name="_onNotificationEnd">
|
||||||
|
<body>
|
||||||
|
<![CDATA[
|
||||||
|
this.removeEventListener("transitionend", this._onNotificationEnd);
|
||||||
|
|
||||||
|
this._progressNotification.classList.remove(
|
||||||
|
"progressNotification-active");
|
||||||
|
]]>
|
||||||
|
</body>
|
||||||
|
</method>
|
||||||
</implementation>
|
</implementation>
|
||||||
</binding>
|
</binding>
|
||||||
</bindings>
|
</bindings>
|
||||||
|
|
|
@ -532,7 +532,11 @@ var MetroDownloadsView = {
|
||||||
let notn = this._progressNotification;
|
let notn = this._progressNotification;
|
||||||
if (notn)
|
if (notn)
|
||||||
this._notificationBox.removeNotification(notn);
|
this._notificationBox.removeNotification(notn);
|
||||||
|
|
||||||
|
ContextUI.displayNavbar();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._downloadProgressIndicator.notify();
|
||||||
break;
|
break;
|
||||||
case "dl-failed":
|
case "dl-failed":
|
||||||
download = aSubject.QueryInterface(Ci.nsIDownload);
|
download = aSubject.QueryInterface(Ci.nsIDownload);
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
|
|
||||||
.circularprogressindicator-progressButton,
|
.circularprogressindicator-progressButton,
|
||||||
.circularprogressindicator-progressRing,
|
.circularprogressindicator-progressRing,
|
||||||
.circularprogressindicator-progressTrack {
|
.circularprogressindicator-progressTrack,
|
||||||
|
.circularprogressindicator-progressNotification {
|
||||||
margin: 0 @toolbar_horizontal_spacing@;
|
margin: 0 @toolbar_horizontal_spacing@;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +26,21 @@
|
||||||
background-image: url(chrome://browser/skin/images/progresscircle-bg.png);
|
background-image: url(chrome://browser/skin/images/progresscircle-bg.png);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.circularprogressindicator-progressNotification {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background-image: url(chrome://browser/skin/images/navbar-download-finished.png);
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circularprogressindicator-progressNotification.progressNotification-active {
|
||||||
|
visibility: visible;
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(2);
|
||||||
|
transition: opacity @metro_animation_duration@,
|
||||||
|
transform @metro_animation_duration@;
|
||||||
|
}
|
||||||
|
|
||||||
.circularprogressindicator-progressRing:not([progress]),
|
.circularprogressindicator-progressRing:not([progress]),
|
||||||
.circularprogressindicator-progressRing[progress="100"],
|
.circularprogressindicator-progressRing[progress="100"],
|
||||||
.circularprogressindicator-progressTrack:not([progress]),
|
.circularprogressindicator-progressTrack:not([progress]),
|
||||||
|
|
|
@ -360,10 +360,6 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
|
||||||
width: 0; /* Fancy cropping solution for flexbox. */
|
width: 0; /* Fancy cropping solution for flexbox. */
|
||||||
}
|
}
|
||||||
|
|
||||||
#PanelUI-fxa-status[signedin] {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
#PanelUI-help,
|
#PanelUI-help,
|
||||||
#PanelUI-quit {
|
#PanelUI-quit {
|
||||||
min-width: 46px;
|
min-width: 46px;
|
||||||
|
|
|
@ -337,6 +337,14 @@ strong {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.project-type {
|
||||||
|
display: none;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
[type="hosted"] > .project-type.hosted,
|
||||||
|
[type="packaged"] > .project-type.packaged {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
/********* PROJECT BUTTONS ***********/
|
/********* PROJECT BUTTONS ***********/
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,8 @@
|
||||||
/* We want a 4px gap between the TabsToolbar and the toolbar-menubar when the
|
/* We want a 4px gap between the TabsToolbar and the toolbar-menubar when the
|
||||||
toolbar-menu is displayed, and a 16px gap when it is not. 1px is taken care
|
toolbar-menu is displayed, and a 16px gap when it is not. 1px is taken care
|
||||||
of by the (light) outer shadow of the tab, the remaining 3/15 are these margins. */
|
of by the (light) outer shadow of the tab, the remaining 3/15 are these margins. */
|
||||||
#toolbar-menubar:not([autohide="true"]) ~ #TabsToolbar,
|
#toolbar-menubar:not([moz-collapsed=true]):not([autohide=true]) ~ #TabsToolbar,
|
||||||
#toolbar-menubar[autohide="true"]:not([inactive]) ~ #TabsToolbar {
|
#toolbar-menubar:not([moz-collapsed=true])[autohide=true]:not([inactive]) ~ #TabsToolbar {
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ ValidatePlane(const VideoData::YCbCrBuffer::Plane& aPlane)
|
||||||
aPlane.mStride > 0;
|
aPlane.mStride > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#ifdef MOZ_WIDGET_GONK
|
||||||
static bool
|
static bool
|
||||||
IsYV12Format(const VideoData::YCbCrBuffer::Plane& aYPlane,
|
IsYV12Format(const VideoData::YCbCrBuffer::Plane& aYPlane,
|
||||||
const VideoData::YCbCrBuffer::Plane& aCbPlane,
|
const VideoData::YCbCrBuffer::Plane& aCbPlane,
|
||||||
|
@ -103,6 +103,45 @@ VideoData* VideoData::ShallowCopyUpdateDuration(VideoData* aOther,
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
void VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
||||||
|
VideoInfo& aInfo,
|
||||||
|
const YCbCrBuffer &aBuffer,
|
||||||
|
const IntRect& aPicture,
|
||||||
|
bool aCopyData)
|
||||||
|
{
|
||||||
|
if (!aVideoImage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
|
||||||
|
const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
|
||||||
|
const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2];
|
||||||
|
|
||||||
|
PlanarYCbCrData data;
|
||||||
|
data.mYChannel = Y.mData + Y.mOffset;
|
||||||
|
data.mYSize = IntSize(Y.mWidth, Y.mHeight);
|
||||||
|
data.mYStride = Y.mStride;
|
||||||
|
data.mYSkip = Y.mSkip;
|
||||||
|
data.mCbChannel = Cb.mData + Cb.mOffset;
|
||||||
|
data.mCrChannel = Cr.mData + Cr.mOffset;
|
||||||
|
data.mCbCrSize = IntSize(Cb.mWidth, Cb.mHeight);
|
||||||
|
data.mCbCrStride = Cb.mStride;
|
||||||
|
data.mCbSkip = Cb.mSkip;
|
||||||
|
data.mCrSkip = Cr.mSkip;
|
||||||
|
data.mPicX = aPicture.x;
|
||||||
|
data.mPicY = aPicture.y;
|
||||||
|
data.mPicSize = aPicture.Size();
|
||||||
|
data.mStereoMode = aInfo.mStereoMode;
|
||||||
|
|
||||||
|
aVideoImage->SetDelayedConversion(true);
|
||||||
|
if (aCopyData) {
|
||||||
|
aVideoImage->SetData(data);
|
||||||
|
} else {
|
||||||
|
aVideoImage->SetDataNoCopy(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
VideoData* VideoData::Create(VideoInfo& aInfo,
|
VideoData* VideoData::Create(VideoInfo& aInfo,
|
||||||
ImageContainer* aContainer,
|
ImageContainer* aContainer,
|
||||||
Image* aImage,
|
Image* aImage,
|
||||||
|
@ -164,14 +203,16 @@ VideoData* VideoData::Create(VideoInfo& aInfo,
|
||||||
aKeyframe,
|
aKeyframe,
|
||||||
aTimecode,
|
aTimecode,
|
||||||
aInfo.mDisplay.ToIntSize()));
|
aInfo.mDisplay.ToIntSize()));
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
|
const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
|
||||||
const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
|
const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
|
||||||
const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2];
|
const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2];
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!aImage) {
|
if (!aImage) {
|
||||||
// Currently our decoder only knows how to output to ImageFormat::PLANAR_YCBCR
|
// Currently our decoder only knows how to output to ImageFormat::PLANAR_YCBCR
|
||||||
// format.
|
// format.
|
||||||
#if 0
|
#ifdef MOZ_WIDGET_GONK
|
||||||
if (IsYV12Format(Y, Cb, Cr)) {
|
if (IsYV12Format(Y, Cb, Cr)) {
|
||||||
v->mImage = aContainer->CreateImage(ImageFormat::GRALLOC_PLANAR_YCBCR);
|
v->mImage = aContainer->CreateImage(ImageFormat::GRALLOC_PLANAR_YCBCR);
|
||||||
}
|
}
|
||||||
|
@ -191,32 +232,30 @@ VideoData* VideoData::Create(VideoInfo& aInfo,
|
||||||
"Wrong format?");
|
"Wrong format?");
|
||||||
PlanarYCbCrImage* videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get());
|
PlanarYCbCrImage* videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get());
|
||||||
|
|
||||||
PlanarYCbCrData data;
|
|
||||||
data.mYChannel = Y.mData + Y.mOffset;
|
|
||||||
data.mYSize = IntSize(Y.mWidth, Y.mHeight);
|
|
||||||
data.mYStride = Y.mStride;
|
|
||||||
data.mYSkip = Y.mSkip;
|
|
||||||
data.mCbChannel = Cb.mData + Cb.mOffset;
|
|
||||||
data.mCrChannel = Cr.mData + Cr.mOffset;
|
|
||||||
data.mCbCrSize = IntSize(Cb.mWidth, Cb.mHeight);
|
|
||||||
data.mCbCrStride = Cb.mStride;
|
|
||||||
data.mCbSkip = Cb.mSkip;
|
|
||||||
data.mCrSkip = Cr.mSkip;
|
|
||||||
data.mPicX = aPicture.x;
|
|
||||||
data.mPicY = aPicture.y;
|
|
||||||
data.mPicSize = aPicture.Size();
|
|
||||||
data.mStereoMode = aInfo.mStereoMode;
|
|
||||||
|
|
||||||
videoImage->SetDelayedConversion(true);
|
|
||||||
if (!aImage) {
|
if (!aImage) {
|
||||||
videoImage->SetData(data);
|
VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
|
||||||
|
true /* aCopyData */);
|
||||||
} else {
|
} else {
|
||||||
videoImage->SetDataNoCopy(data);
|
VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
|
||||||
|
false /* aCopyData */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
if (!videoImage->IsValid() && !aImage && IsYV12Format(Y, Cb, Cr)) {
|
||||||
|
// Failed to allocate gralloc. Try fallback.
|
||||||
|
v->mImage = aContainer->CreateImage(ImageFormat::PLANAR_YCBCR);
|
||||||
|
if (!v->mImage) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get());
|
||||||
|
VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
|
||||||
|
true /* aCopyData */);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return v.forget();
|
return v.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
VideoData* VideoData::Create(VideoInfo& aInfo,
|
VideoData* VideoData::Create(VideoInfo& aInfo,
|
||||||
ImageContainer* aContainer,
|
ImageContainer* aContainer,
|
||||||
int64_t aOffset,
|
int64_t aOffset,
|
||||||
|
@ -231,6 +270,7 @@ VideoData* VideoData::Create(VideoInfo& aInfo,
|
||||||
aKeyframe, aTimecode, aPicture);
|
aKeyframe, aTimecode, aPicture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
VideoData* VideoData::Create(VideoInfo& aInfo,
|
VideoData* VideoData::Create(VideoInfo& aInfo,
|
||||||
Image* aImage,
|
Image* aImage,
|
||||||
int64_t aOffset,
|
int64_t aOffset,
|
||||||
|
@ -245,6 +285,7 @@ VideoData* VideoData::Create(VideoInfo& aInfo,
|
||||||
aKeyframe, aTimecode, aPicture);
|
aKeyframe, aTimecode, aPicture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
VideoData* VideoData::CreateFromImage(VideoInfo& aInfo,
|
VideoData* VideoData::CreateFromImage(VideoInfo& aInfo,
|
||||||
ImageContainer* aContainer,
|
ImageContainer* aContainer,
|
||||||
int64_t aOffset,
|
int64_t aOffset,
|
||||||
|
@ -266,6 +307,7 @@ VideoData* VideoData::CreateFromImage(VideoInfo& aInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_OMX_DECODER
|
#ifdef MOZ_OMX_DECODER
|
||||||
|
/* static */
|
||||||
VideoData* VideoData::Create(VideoInfo& aInfo,
|
VideoData* VideoData::Create(VideoInfo& aInfo,
|
||||||
ImageContainer* aContainer,
|
ImageContainer* aContainer,
|
||||||
int64_t aOffset,
|
int64_t aOffset,
|
||||||
|
|
|
@ -102,6 +102,7 @@ public:
|
||||||
|
|
||||||
namespace layers {
|
namespace layers {
|
||||||
class GraphicBufferLocked;
|
class GraphicBufferLocked;
|
||||||
|
class PlanarYCbCrImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
class VideoInfo;
|
class VideoInfo;
|
||||||
|
@ -113,6 +114,7 @@ public:
|
||||||
typedef gfx::IntSize IntSize;
|
typedef gfx::IntSize IntSize;
|
||||||
typedef layers::ImageContainer ImageContainer;
|
typedef layers::ImageContainer ImageContainer;
|
||||||
typedef layers::Image Image;
|
typedef layers::Image Image;
|
||||||
|
typedef layers::PlanarYCbCrImage PlanarYCbCrImage;
|
||||||
|
|
||||||
// YCbCr data obtained from decoding the video. The index's are:
|
// YCbCr data obtained from decoding the video. The index's are:
|
||||||
// 0 = Y
|
// 0 = Y
|
||||||
|
@ -202,6 +204,14 @@ public:
|
||||||
static VideoData* ShallowCopyUpdateDuration(VideoData* aOther,
|
static VideoData* ShallowCopyUpdateDuration(VideoData* aOther,
|
||||||
int64_t aDuration);
|
int64_t aDuration);
|
||||||
|
|
||||||
|
// Initialize PlanarYCbCrImage. Only When aCopyData is true,
|
||||||
|
// video data is copied to PlanarYCbCrImage.
|
||||||
|
static void SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
||||||
|
VideoInfo& aInfo,
|
||||||
|
const YCbCrBuffer &aBuffer,
|
||||||
|
const IntRect& aPicture,
|
||||||
|
bool aCopyData);
|
||||||
|
|
||||||
// Constructs a duplicate VideoData object. This intrinsically tells the
|
// Constructs a duplicate VideoData object. This intrinsically tells the
|
||||||
// player that it does not need to update the displayed frame when this
|
// player that it does not need to update the displayed frame when this
|
||||||
// frame is played; this frame is identical to the previous.
|
// frame is played; this frame is identical to the previous.
|
||||||
|
|
|
@ -112,12 +112,16 @@ OmxVideoTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
|
||||||
|
|
||||||
// Send the EOS signal to OMXCodecWrapper.
|
// Send the EOS signal to OMXCodecWrapper.
|
||||||
if (mEndOfStream && iter.IsEnded() && !mEosSetInEncoder) {
|
if (mEndOfStream && iter.IsEnded() && !mEosSetInEncoder) {
|
||||||
mEosSetInEncoder = true;
|
|
||||||
uint64_t totalDurationUs = mTotalFrameDuration * USECS_PER_S / mTrackRate;
|
uint64_t totalDurationUs = mTotalFrameDuration * USECS_PER_S / mTrackRate;
|
||||||
layers::Image* img = (!mLastFrame.GetImage() || mLastFrame.GetForceBlack())
|
layers::Image* img = (!mLastFrame.GetImage() || mLastFrame.GetForceBlack())
|
||||||
? nullptr : mLastFrame.GetImage();
|
? nullptr : mLastFrame.GetImage();
|
||||||
mEncoder->Encode(img, mFrameWidth, mFrameHeight, totalDurationUs,
|
nsresult result = mEncoder->Encode(img, mFrameWidth, mFrameHeight,
|
||||||
OMXCodecWrapper::BUFFER_EOS);
|
totalDurationUs,
|
||||||
|
OMXCodecWrapper::BUFFER_EOS);
|
||||||
|
// Keep sending EOS signal until OMXVideoEncoder gets it.
|
||||||
|
if (result == NS_OK) {
|
||||||
|
mEosSetInEncoder = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dequeue an encoded frame from the output buffers of OMXCodecWrapper.
|
// Dequeue an encoded frame from the output buffers of OMXCodecWrapper.
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "TrackEncoder.h"
|
#include "TrackEncoder.h"
|
||||||
|
|
||||||
#include <binder/ProcessState.h>
|
#include <binder/ProcessState.h>
|
||||||
|
#include <cutils/properties.h>
|
||||||
#include <media/ICrypto.h>
|
#include <media/ICrypto.h>
|
||||||
#include <media/IOMX.h>
|
#include <media/IOMX.h>
|
||||||
#include <OMX_Component.h>
|
#include <OMX_Component.h>
|
||||||
|
@ -110,6 +111,15 @@ OMXCodecWrapper::Stop()
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check system property to see if we're running on emulator.
|
||||||
|
static
|
||||||
|
bool IsRunningOnEmulator()
|
||||||
|
{
|
||||||
|
char qemu[PROPERTY_VALUE_MAX];
|
||||||
|
property_get("ro.kernel.qemu", qemu, "");
|
||||||
|
return strncmp(qemu, "1", 1) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
OMXVideoEncoder::Configure(int aWidth, int aHeight, int aFrameRate)
|
OMXVideoEncoder::Configure(int aWidth, int aHeight, int aFrameRate)
|
||||||
{
|
{
|
||||||
|
@ -118,6 +128,19 @@ OMXVideoEncoder::Configure(int aWidth, int aHeight, int aFrameRate)
|
||||||
NS_ENSURE_TRUE(aWidth > 0 && aHeight > 0 && aFrameRate > 0,
|
NS_ENSURE_TRUE(aWidth > 0 && aHeight > 0 && aFrameRate > 0,
|
||||||
NS_ERROR_INVALID_ARG);
|
NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
OMX_VIDEO_AVCLEVELTYPE level = OMX_VIDEO_AVCLevel3;
|
||||||
|
OMX_VIDEO_CONTROLRATETYPE bitrateMode = OMX_Video_ControlRateConstant;
|
||||||
|
// Limitation of soft AVC/H.264 encoder running on emulator in stagefright.
|
||||||
|
static bool emu = IsRunningOnEmulator();
|
||||||
|
if (emu) {
|
||||||
|
if (aWidth > 352 || aHeight > 288) {
|
||||||
|
CODEC_ERROR("SoftAVCEncoder doesn't support resolution larger than CIF");
|
||||||
|
return NS_ERROR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
level = OMX_VIDEO_AVCLevel2;
|
||||||
|
bitrateMode = OMX_Video_ControlRateVariable;
|
||||||
|
}
|
||||||
|
|
||||||
// Set up configuration parameters for AVC/H.264 encoder.
|
// Set up configuration parameters for AVC/H.264 encoder.
|
||||||
sp<AMessage> format = new AMessage;
|
sp<AMessage> format = new AMessage;
|
||||||
// Fixed values
|
// Fixed values
|
||||||
|
@ -128,8 +151,8 @@ OMXVideoEncoder::Configure(int aWidth, int aHeight, int aFrameRate)
|
||||||
// height is half that of Y
|
// height is half that of Y
|
||||||
format->setInt32("color-format", OMX_COLOR_FormatYUV420SemiPlanar);
|
format->setInt32("color-format", OMX_COLOR_FormatYUV420SemiPlanar);
|
||||||
format->setInt32("profile", OMX_VIDEO_AVCProfileBaseline);
|
format->setInt32("profile", OMX_VIDEO_AVCProfileBaseline);
|
||||||
format->setInt32("level", OMX_VIDEO_AVCLevel3);
|
format->setInt32("level", level);
|
||||||
format->setInt32("bitrate-mode", OMX_Video_ControlRateConstant);
|
format->setInt32("bitrate-mode", bitrateMode);
|
||||||
format->setInt32("store-metadata-in-buffers", 0);
|
format->setInt32("store-metadata-in-buffers", 0);
|
||||||
format->setInt32("prepend-sps-pps-to-idr-frames", 0);
|
format->setInt32("prepend-sps-pps-to-idr-frames", 0);
|
||||||
// Input values.
|
// Input values.
|
||||||
|
|
|
@ -448,7 +448,7 @@ AudioChannelService::SendAudioChannelChangedNotification(uint64_t aChildID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculating the most important active channel.
|
// Calculating the most important active channel.
|
||||||
AudioChannelType higher = AUDIO_CHANNEL_LAST;
|
AudioChannelType higher = AUDIO_CHANNEL_DEFAULT;
|
||||||
|
|
||||||
// Top-Down in the hierarchy for visible elements
|
// Top-Down in the hierarchy for visible elements
|
||||||
if (!mChannelCounters[AUDIO_CHANNEL_INT_PUBLICNOTIFICATION].IsEmpty()) {
|
if (!mChannelCounters[AUDIO_CHANNEL_INT_PUBLICNOTIFICATION].IsEmpty()) {
|
||||||
|
@ -482,30 +482,19 @@ AudioChannelService::SendAudioChannelChangedNotification(uint64_t aChildID)
|
||||||
AudioChannelType visibleHigher = higher;
|
AudioChannelType visibleHigher = higher;
|
||||||
|
|
||||||
// Top-Down in the hierarchy for non-visible elements
|
// Top-Down in the hierarchy for non-visible elements
|
||||||
if (higher == AUDIO_CHANNEL_LAST) {
|
// And we can ignore normal channel because it can't play in the background.
|
||||||
if (!mChannelCounters[AUDIO_CHANNEL_INT_PUBLICNOTIFICATION_HIDDEN].IsEmpty()) {
|
for (int i = AUDIO_CHANNEL_LAST - 1;
|
||||||
higher = AUDIO_CHANNEL_PUBLICNOTIFICATION;
|
i > higher && i > AUDIO_CHANNEL_NORMAL; i--) {
|
||||||
|
if (i == AUDIO_CHANNEL_CONTENT &&
|
||||||
|
mPlayableHiddenContentChildID != CONTENT_PROCESS_ID_UNKNOWN) {
|
||||||
|
higher = static_cast<AudioChannelType>(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (!mChannelCounters[AUDIO_CHANNEL_INT_RINGER_HIDDEN].IsEmpty()) {
|
// Each channel type will be split to fg and bg for recording the state,
|
||||||
higher = AUDIO_CHANNEL_RINGER;
|
// so here need to do a translation.
|
||||||
}
|
if (!mChannelCounters[i * 2 + 1].IsEmpty()) {
|
||||||
|
higher = static_cast<AudioChannelType>(i);
|
||||||
else if (!mChannelCounters[AUDIO_CHANNEL_INT_TELEPHONY_HIDDEN].IsEmpty()) {
|
break;
|
||||||
higher = AUDIO_CHANNEL_TELEPHONY;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (!mChannelCounters[AUDIO_CHANNEL_INT_ALARM_HIDDEN].IsEmpty()) {
|
|
||||||
higher = AUDIO_CHANNEL_ALARM;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (!mChannelCounters[AUDIO_CHANNEL_INT_NOTIFICATION_HIDDEN].IsEmpty()) {
|
|
||||||
higher = AUDIO_CHANNEL_NOTIFICATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check whether there is any playable hidden content channel or not.
|
|
||||||
else if (mPlayableHiddenContentChildID != CONTENT_PROCESS_ID_UNKNOWN) {
|
|
||||||
higher = AUDIO_CHANNEL_CONTENT;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,7 +502,7 @@ AudioChannelService::SendAudioChannelChangedNotification(uint64_t aChildID)
|
||||||
mCurrentHigherChannel = higher;
|
mCurrentHigherChannel = higher;
|
||||||
|
|
||||||
nsString channelName;
|
nsString channelName;
|
||||||
if (mCurrentHigherChannel != AUDIO_CHANNEL_LAST) {
|
if (mCurrentHigherChannel != AUDIO_CHANNEL_DEFAULT) {
|
||||||
channelName.AssignASCII(ChannelName(mCurrentHigherChannel));
|
channelName.AssignASCII(ChannelName(mCurrentHigherChannel));
|
||||||
} else {
|
} else {
|
||||||
channelName.AssignLiteral("none");
|
channelName.AssignLiteral("none");
|
||||||
|
@ -528,7 +517,7 @@ AudioChannelService::SendAudioChannelChangedNotification(uint64_t aChildID)
|
||||||
mCurrentVisibleHigherChannel = visibleHigher;
|
mCurrentVisibleHigherChannel = visibleHigher;
|
||||||
|
|
||||||
nsString channelName;
|
nsString channelName;
|
||||||
if (mCurrentVisibleHigherChannel != AUDIO_CHANNEL_LAST) {
|
if (mCurrentVisibleHigherChannel != AUDIO_CHANNEL_DEFAULT) {
|
||||||
channelName.AssignASCII(ChannelName(mCurrentVisibleHigherChannel));
|
channelName.AssignASCII(ChannelName(mCurrentVisibleHigherChannel));
|
||||||
} else {
|
} else {
|
||||||
channelName.AssignLiteral("none");
|
channelName.AssignLiteral("none");
|
||||||
|
|
|
@ -134,6 +134,7 @@
|
||||||
#include "AudioChannelService.h"
|
#include "AudioChannelService.h"
|
||||||
#include "JavaScriptChild.h"
|
#include "JavaScriptChild.h"
|
||||||
#include "mozilla/dom/telephony/PTelephonyChild.h"
|
#include "mozilla/dom/telephony/PTelephonyChild.h"
|
||||||
|
#include "mozilla/dom/time/DateCacheCleaner.h"
|
||||||
#include "mozilla/net/NeckoMessageUtils.h"
|
#include "mozilla/net/NeckoMessageUtils.h"
|
||||||
|
|
||||||
using namespace base;
|
using namespace base;
|
||||||
|
@ -311,6 +312,15 @@ NS_IMPL_ISUPPORTS1(SystemMessageHandledObserver, nsIObserver)
|
||||||
|
|
||||||
ContentChild* ContentChild::sSingleton;
|
ContentChild* ContentChild::sSingleton;
|
||||||
|
|
||||||
|
// Performs initialization that is not fork-safe, i.e. that must be done after
|
||||||
|
// forking from the Nuwa process.
|
||||||
|
static void
|
||||||
|
InitOnContentProcessCreated()
|
||||||
|
{
|
||||||
|
// This will register cross-process observer.
|
||||||
|
mozilla::dom::time::InitializeDateCacheCleaner();
|
||||||
|
}
|
||||||
|
|
||||||
ContentChild::ContentChild()
|
ContentChild::ContentChild()
|
||||||
: mID(uint64_t(-1))
|
: mID(uint64_t(-1))
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
|
@ -462,6 +472,10 @@ ContentChild::InitXPCOM()
|
||||||
nsRefPtr<SystemMessageHandledObserver> sysMsgObserver =
|
nsRefPtr<SystemMessageHandledObserver> sysMsgObserver =
|
||||||
new SystemMessageHandledObserver();
|
new SystemMessageHandledObserver();
|
||||||
sysMsgObserver->Init();
|
sysMsgObserver->Init();
|
||||||
|
|
||||||
|
#ifndef MOZ_NUWA_PROCESS
|
||||||
|
InitOnContentProcessCreated();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
PMemoryReportRequestChild*
|
PMemoryReportRequestChild*
|
||||||
|
@ -1623,6 +1637,10 @@ public:
|
||||||
|
|
||||||
toplevel = toplevel->getNext();
|
toplevel = toplevel->getNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Perform other after-fork initializations.
|
||||||
|
InitOnContentProcessCreated();
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -66,7 +66,7 @@ CrashReporterParent::CrashReporterParent()
|
||||||
#ifdef MOZ_CRASHREPORTER
|
#ifdef MOZ_CRASHREPORTER
|
||||||
mNotes(4),
|
mNotes(4),
|
||||||
#endif
|
#endif
|
||||||
mStartTime(time(nullptr))
|
mStartTime(::time(nullptr))
|
||||||
, mInitialized(false)
|
, mInitialized(false)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(CrashReporterParent);
|
MOZ_COUNT_CTOR(CrashReporterParent);
|
||||||
|
|
|
@ -79,7 +79,15 @@ NetworkStatsDB.prototype = {
|
||||||
// to modify the keyPath is mandatory to delete the object store
|
// to modify the keyPath is mandatory to delete the object store
|
||||||
// and create it again. Old data is going to be deleted because the
|
// and create it again. Old data is going to be deleted because the
|
||||||
// networkId for each sample can not be set.
|
// networkId for each sample can not be set.
|
||||||
db.deleteObjectStore(DEPRECATED_STORE_NAME);
|
|
||||||
|
// In version 1.2 objectStore name was 'net_stats_v2', to avoid errors when
|
||||||
|
// upgrading from 1.2 to 1.3 objectStore name should be checked.
|
||||||
|
let stores = db.objectStoreNames;
|
||||||
|
if(stores.contains("net_stats_v2")) {
|
||||||
|
db.deleteObjectStore("net_stats_v2");
|
||||||
|
} else {
|
||||||
|
db.deleteObjectStore(DEPRECATED_STORE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
objectStore = db.createObjectStore(DEPRECATED_STORE_NAME, { keyPath: ["appId", "network", "timestamp"] });
|
objectStore = db.createObjectStore(DEPRECATED_STORE_NAME, { keyPath: ["appId", "network", "timestamp"] });
|
||||||
objectStore.createIndex("appId", "appId", { unique: false });
|
objectStore.createIndex("appId", "appId", { unique: false });
|
||||||
|
|
|
@ -22,6 +22,7 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://gre/modules/Sntp.jsm");
|
Cu.import("resource://gre/modules/Sntp.jsm");
|
||||||
Cu.import("resource://gre/modules/systemlibs.js");
|
Cu.import("resource://gre/modules/systemlibs.js");
|
||||||
Cu.import("resource://gre/modules/Promise.jsm");
|
Cu.import("resource://gre/modules/Promise.jsm");
|
||||||
|
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||||
|
|
||||||
var RIL = {};
|
var RIL = {};
|
||||||
Cu.import("resource://gre/modules/ril_consts.js", RIL);
|
Cu.import("resource://gre/modules/ril_consts.js", RIL);
|
||||||
|
@ -3299,6 +3300,16 @@ RadioInterface.prototype = {
|
||||||
// Or refresh the SNTP.
|
// Or refresh the SNTP.
|
||||||
this._sntp.request();
|
this._sntp.request();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Set a sane minimum time.
|
||||||
|
let buildTime = libcutils.property_get("ro.build.date.utc", "0") * 1000;
|
||||||
|
let file = FileUtils.File("/system/b2g/b2g");
|
||||||
|
if (file.lastModifiedTime > buildTime) {
|
||||||
|
buildTime = file.lastModifiedTime;
|
||||||
|
}
|
||||||
|
if (buildTime > Date.now()) {
|
||||||
|
gTimeService.set(buildTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case kSettingsTimezoneAutoUpdateEnabled:
|
case kSettingsTimezoneAutoUpdateEnabled:
|
||||||
|
|
|
@ -80,7 +80,7 @@ SharedSurface_Gralloc::Create(GLContext* prodGL,
|
||||||
gfxImageFormat format
|
gfxImageFormat format
|
||||||
= gfxPlatform::GetPlatform()->OptimalFormatForContent(type);
|
= gfxPlatform::GetPlatform()->OptimalFormatForContent(type);
|
||||||
|
|
||||||
GrallocTextureClientOGL* grallocTC =
|
RefPtr<GrallocTextureClientOGL> grallocTC =
|
||||||
new GrallocTextureClientOGL(
|
new GrallocTextureClientOGL(
|
||||||
allocator,
|
allocator,
|
||||||
gfx::ImageFormatToSurfaceFormat(format),
|
gfx::ImageFormatToSurfaceFormat(format),
|
||||||
|
@ -102,7 +102,6 @@ SharedSurface_Gralloc::Create(GLContext* prodGL,
|
||||||
LOCAL_EGL_NATIVE_BUFFER_ANDROID,
|
LOCAL_EGL_NATIVE_BUFFER_ANDROID,
|
||||||
clientBuffer, attrs);
|
clientBuffer, attrs);
|
||||||
if (!image) {
|
if (!image) {
|
||||||
grallocTC->DropTextureData()->DeallocateSharedData(allocator);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,9 @@ GrallocImage::SetData(const Data& aData)
|
||||||
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
|
GraphicBuffer::USAGE_SW_WRITE_OFTEN |
|
||||||
GraphicBuffer::USAGE_HW_TEXTURE,
|
GraphicBuffer::USAGE_HW_TEXTURE,
|
||||||
&desc);
|
&desc);
|
||||||
|
if (desc.type() == SurfaceDescriptor::T__None) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
mBufferAllocated = true;
|
mBufferAllocated = true;
|
||||||
mGraphicBufferLocked = new GraphicBufferLocked(desc);
|
mGraphicBufferLocked = new GraphicBufferLocked(desc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,7 +132,7 @@ CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
||||||
|
|
||||||
SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf);
|
SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf);
|
||||||
|
|
||||||
GrallocTextureClientOGL* grallocTextureClient =
|
RefPtr<GrallocTextureClientOGL> grallocTextureClient =
|
||||||
static_cast<GrallocTextureClientOGL*>(grallocSurf->GetTextureClient());
|
static_cast<GrallocTextureClientOGL*>(grallocSurf->GetTextureClient());
|
||||||
|
|
||||||
// If IPDLActor is null means this TextureClient didn't AddTextureClient yet
|
// If IPDLActor is null means this TextureClient didn't AddTextureClient yet
|
||||||
|
|
|
@ -130,7 +130,6 @@ using namespace mozilla;
|
||||||
using namespace mozilla::net;
|
using namespace mozilla::net;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
using namespace mozilla::dom::ipc;
|
using namespace mozilla::dom::ipc;
|
||||||
using namespace mozilla::dom::time;
|
|
||||||
|
|
||||||
nsrefcnt nsLayoutStatics::sLayoutStaticRefcnt = 0;
|
nsrefcnt nsLayoutStatics::sLayoutStaticRefcnt = 0;
|
||||||
|
|
||||||
|
@ -280,8 +279,6 @@ nsLayoutStatics::Initialize()
|
||||||
nsCookieService::AppClearDataObserverInit();
|
nsCookieService::AppClearDataObserverInit();
|
||||||
nsApplicationCacheService::AppClearDataObserverInit();
|
nsApplicationCacheService::AppClearDataObserverInit();
|
||||||
|
|
||||||
InitializeDateCacheCleaner();
|
|
||||||
|
|
||||||
HTMLVideoElement::Init();
|
HTMLVideoElement::Init();
|
||||||
|
|
||||||
CacheObserver::Init();
|
CacheObserver::Init();
|
||||||
|
|
|
@ -29,7 +29,7 @@ bool VolatileBuffer::Init(size_t aSize, size_t aAlignment)
|
||||||
#if defined(MOZ_MEMORY)
|
#if defined(MOZ_MEMORY)
|
||||||
posix_memalign(&mBuf, aAlignment, aSize);
|
posix_memalign(&mBuf, aAlignment, aSize);
|
||||||
#elif defined(HAVE_POSIX_MEMALIGN)
|
#elif defined(HAVE_POSIX_MEMALIGN)
|
||||||
moz_posix_memalign(&mBuf, aAlignment, aSize);
|
(void)moz_posix_memalign(&mBuf, aAlignment, aSize);
|
||||||
#else
|
#else
|
||||||
#error "No memalign implementation found"
|
#error "No memalign implementation found"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -46,7 +46,7 @@ VolatileBuffer::Init(size_t aSize, size_t aAlignment)
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_alloc:
|
heap_alloc:
|
||||||
moz_posix_memalign(&mBuf, aAlignment, aSize);
|
(void)moz_posix_memalign(&mBuf, aAlignment, aSize);
|
||||||
mHeap = true;
|
mHeap = true;
|
||||||
return !!mBuf;
|
return !!mBuf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,7 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewStub;
|
import android.view.ViewStub;
|
||||||
import android.view.ViewTreeObserver;
|
import android.view.ViewTreeObserver;
|
||||||
|
import android.view.Window;
|
||||||
import android.view.animation.Interpolator;
|
import android.view.animation.Interpolator;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
|
@ -890,6 +891,12 @@ abstract public class BrowserApp extends GeckoApp
|
||||||
|
|
||||||
// Intercept key events for gamepad shortcuts
|
// Intercept key events for gamepad shortcuts
|
||||||
mLayerView.setOnKeyListener(this);
|
mLayerView.setOnKeyListener(this);
|
||||||
|
|
||||||
|
// Initialize the actionbar menu items on startup for both large and small tablets
|
||||||
|
if (HardwareUtils.isTablet()) {
|
||||||
|
onCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, null);
|
||||||
|
invalidateOptionsMenu();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void shareCurrentUrl() {
|
private void shareCurrentUrl() {
|
||||||
|
|
|
@ -44,6 +44,13 @@ var ContextMenus = {
|
||||||
|
|
||||||
init: function() {
|
init: function() {
|
||||||
document.addEventListener("contextmenu", this, false);
|
document.addEventListener("contextmenu", this, false);
|
||||||
|
document.getElementById("contextmenu-open").addEventListener("click", this.open.bind(this), false);
|
||||||
|
document.getElementById("contextmenu-retry").addEventListener("click", this.retry.bind(this), false);
|
||||||
|
document.getElementById("contextmenu-remove").addEventListener("click", this.remove.bind(this), false);
|
||||||
|
document.getElementById("contextmenu-pause").addEventListener("click", this.pause.bind(this), false);
|
||||||
|
document.getElementById("contextmenu-resume").addEventListener("click", this.resume.bind(this), false);
|
||||||
|
document.getElementById("contextmenu-cancel").addEventListener("click", this.cancel.bind(this), false);
|
||||||
|
document.getElementById("contextmenu-removeall").addEventListener("click", this.removeAll.bind(this), false);
|
||||||
this.items = [
|
this.items = [
|
||||||
{ name: "open", states: [Downloads._dlmgr.DOWNLOAD_FINISHED] },
|
{ name: "open", states: [Downloads._dlmgr.DOWNLOAD_FINISHED] },
|
||||||
{ name: "retry", states: [Downloads._dlmgr.DOWNLOAD_FAILED, Downloads._dlmgr.DOWNLOAD_CANCELED] },
|
{ name: "retry", states: [Downloads._dlmgr.DOWNLOAD_FAILED, Downloads._dlmgr.DOWNLOAD_CANCELED] },
|
||||||
|
@ -599,3 +606,8 @@ let Downloads = {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", Downloads.init.bind(Downloads), true);
|
||||||
|
window.addEventListener("unload", Downloads.uninit.bind(Downloads), false);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,15 +24,15 @@
|
||||||
<link rel="stylesheet" href="chrome://browser/skin/aboutDownloads.css" type="text/css"/>
|
<link rel="stylesheet" href="chrome://browser/skin/aboutDownloads.css" type="text/css"/>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body dir="&locale.dir;" onload="Downloads.init();" onunload="Downloads.uninit();">
|
<body dir="&locale.dir;">
|
||||||
<menu type="context" id="downloadmenu">
|
<menu type="context" id="downloadmenu">
|
||||||
<menuitem id="contextmenu-open" label="&aboutDownloads.open;" onclick="ContextMenus.open();"></menuitem>
|
<menuitem id="contextmenu-open" label="&aboutDownloads.open;"></menuitem>
|
||||||
<menuitem id="contextmenu-retry" label="&aboutDownloads.retry;" onclick="ContextMenus.retry();"></menuitem>
|
<menuitem id="contextmenu-retry" label="&aboutDownloads.retry;"></menuitem>
|
||||||
<menuitem id="contextmenu-remove" label="&aboutDownloads.remove;" onclick="ContextMenus.remove();"></menuitem>
|
<menuitem id="contextmenu-remove" label="&aboutDownloads.remove;"></menuitem>
|
||||||
<menuitem id="contextmenu-pause" label="&aboutDownloads.pause;" onclick="ContextMenus.pause();"></menuitem>
|
<menuitem id="contextmenu-pause" label="&aboutDownloads.pause;"></menuitem>
|
||||||
<menuitem id="contextmenu-resume" label="&aboutDownloads.resume;" onclick="ContextMenus.resume();"></menuitem>
|
<menuitem id="contextmenu-resume" label="&aboutDownloads.resume;"></menuitem>
|
||||||
<menuitem id="contextmenu-cancel" label="&aboutDownloads.cancel;" onclick="ContextMenus.cancel();"></menuitem>
|
<menuitem id="contextmenu-cancel" label="&aboutDownloads.cancel;"></menuitem>
|
||||||
<menuitem id="contextmenu-removeall" label="&aboutDownloads.removeAll;" onclick="ContextMenus.removeAll();"></menuitem>
|
<menuitem id="contextmenu-removeall" label="&aboutDownloads.removeAll;"></menuitem>
|
||||||
</menu>
|
</menu>
|
||||||
|
|
||||||
<div class="header">
|
<div class="header">
|
||||||
|
|
|
@ -24,6 +24,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "jwcrypto",
|
||||||
|
|
||||||
// All properties exposed by the public FxAccounts API.
|
// All properties exposed by the public FxAccounts API.
|
||||||
let publicProperties = [
|
let publicProperties = [
|
||||||
|
"getAccountsSignInURI",
|
||||||
"getAccountsURI",
|
"getAccountsURI",
|
||||||
"getAssertion",
|
"getAssertion",
|
||||||
"getKeys",
|
"getKeys",
|
||||||
|
@ -615,6 +616,15 @@ FxAccountsInternal.prototype = {
|
||||||
return url;
|
return url;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Return the URI of the remote UI flows.
|
||||||
|
getAccountsSignInURI: function() {
|
||||||
|
let url = Services.urlFormatter.formatURLPref("identity.fxaccounts.remote.signin.uri");
|
||||||
|
if (!/^https:/.test(url)) { // Comment to un-break emacs js-mode highlighting
|
||||||
|
throw new Error("Firefox Accounts server must use HTTPS");
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
},
|
||||||
|
|
||||||
// Returns a promise that resolves with the URL to use to force a re-signin
|
// Returns a promise that resolves with the URL to use to force a re-signin
|
||||||
// of the current account.
|
// of the current account.
|
||||||
promiseAccountsForceSigninURI: function() {
|
promiseAccountsForceSigninURI: function() {
|
||||||
|
|
|
@ -64,14 +64,20 @@ this.TelemetryFile = {
|
||||||
*
|
*
|
||||||
* @param {object} ping The content of the ping to save.
|
* @param {object} ping The content of the ping to save.
|
||||||
* @param {string} file The destination file.
|
* @param {string} file The destination file.
|
||||||
* @param {bool} overwrite If |true|, the file will be overwritten
|
* @param {bool} overwrite If |true|, the file will be overwritten if it exists,
|
||||||
* if it exists.
|
* if |false| the file will not be overwritten and no error will be reported if
|
||||||
|
* the file exists.
|
||||||
* @returns {promise}
|
* @returns {promise}
|
||||||
*/
|
*/
|
||||||
savePingToFile: function(ping, file, overwrite) {
|
savePingToFile: function(ping, file, overwrite) {
|
||||||
let pingString = JSON.stringify(ping);
|
return Task.spawn(function*() {
|
||||||
return OS.File.writeAtomic(file, pingString, {tmpPath: file + ".tmp",
|
try {
|
||||||
noOverwrite: !overwrite});
|
let pingString = JSON.stringify(ping);
|
||||||
|
yield OS.File.writeAtomic(file, pingString, {tmpPath: file + ".tmp",
|
||||||
|
noOverwrite: !overwrite});
|
||||||
|
} catch(e if e.becauseExists) {
|
||||||
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,7 +92,7 @@ this.TelemetryFile = {
|
||||||
return Task.spawn(function*() {
|
return Task.spawn(function*() {
|
||||||
yield getPingDirectory();
|
yield getPingDirectory();
|
||||||
let file = pingFilePath(ping);
|
let file = pingFilePath(ping);
|
||||||
return this.savePingToFile(ping, file, overwrite);
|
yield this.savePingToFile(ping, file, overwrite);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -98,6 +104,8 @@ this.TelemetryFile = {
|
||||||
*/
|
*/
|
||||||
savePendingPings: function(sessionPing) {
|
savePendingPings: function(sessionPing) {
|
||||||
let p = pendingPings.reduce((p, ping) => {
|
let p = pendingPings.reduce((p, ping) => {
|
||||||
|
// Restore the files with the previous pings if for some reason they have
|
||||||
|
// been deleted, don't overwrite them otherwise.
|
||||||
p.push(this.savePing(ping, false));
|
p.push(this.savePing(ping, false));
|
||||||
return p;}, [this.savePing(sessionPing, true)]);
|
return p;}, [this.savePing(sessionPing, true)]);
|
||||||
|
|
||||||
|
|
|
@ -789,13 +789,13 @@ let Impl = {
|
||||||
|
|
||||||
function handler(success) {
|
function handler(success) {
|
||||||
return function(event) {
|
return function(event) {
|
||||||
this.finishPingRequest(success, startTime, ping);
|
this.finishPingRequest(success, startTime, ping).then(() => {
|
||||||
|
if (success) {
|
||||||
if (success) {
|
deferred.resolve();
|
||||||
deferred.resolve();
|
} else {
|
||||||
} else {
|
deferred.reject(event);
|
||||||
deferred.reject(event);
|
}
|
||||||
}
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
request.addEventListener("error", handler(false).bind(this), false);
|
request.addEventListener("error", handler(false).bind(this), false);
|
||||||
|
|
|
@ -18,6 +18,7 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://gre/modules/LightweightThemeManager.jsm", this);
|
Cu.import("resource://gre/modules/LightweightThemeManager.jsm", this);
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
||||||
Cu.import("resource://gre/modules/TelemetryPing.jsm", this);
|
Cu.import("resource://gre/modules/TelemetryPing.jsm", this);
|
||||||
|
Cu.import("resource://gre/modules/TelemetryFile.jsm", this);
|
||||||
Cu.import("resource://gre/modules/Task.jsm", this);
|
Cu.import("resource://gre/modules/Task.jsm", this);
|
||||||
Cu.import("resource://gre/modules/Promise.jsm", this);
|
Cu.import("resource://gre/modules/Promise.jsm", this);
|
||||||
|
|
||||||
|
@ -399,6 +400,14 @@ function actualTest() {
|
||||||
run_next_test();
|
run_next_test();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that not overwriting an existing file fails silently
|
||||||
|
add_task(function* test_overwritePing() {
|
||||||
|
let ping = {slug: "foo"}
|
||||||
|
yield TelemetryFile.savePing(ping, true);
|
||||||
|
yield TelemetryFile.savePing(ping, false);
|
||||||
|
yield TelemetryFile.cleanupPingFile(ping);
|
||||||
|
});
|
||||||
|
|
||||||
// Ensures that expired histograms are not part of the payload.
|
// Ensures that expired histograms are not part of the payload.
|
||||||
add_task(function* test_expiredHistogram() {
|
add_task(function* test_expiredHistogram() {
|
||||||
let histogram_id = "FOOBAR";
|
let histogram_id = "FOOBAR";
|
||||||
|
|
|
@ -91,6 +91,9 @@
|
||||||
testQuickFindText();
|
testQuickFindText();
|
||||||
gFindBar.close();
|
gFindBar.close();
|
||||||
ok(gFindBar.hidden, "Failed to close findbar after testQuickFindText");
|
ok(gFindBar.hidden, "Failed to close findbar after testQuickFindText");
|
||||||
|
testFindWithHighlight();
|
||||||
|
gFindBar.close();
|
||||||
|
ok(gFindBar.hidden, "Failed to close findbar after testFindWithHighlight");
|
||||||
testFindbarSelection();
|
testFindbarSelection();
|
||||||
testDrop();
|
testDrop();
|
||||||
testQuickFindLink();
|
testQuickFindLink();
|
||||||
|
@ -304,6 +307,52 @@
|
||||||
"testQuickFindLink: failed to find sample link");
|
"testQuickFindLink: failed to find sample link");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See bug 963925 for more details on this test.
|
||||||
|
function testFindWithHighlight() {
|
||||||
|
//clearFocus();
|
||||||
|
gFindBar._findField.value = "";
|
||||||
|
|
||||||
|
let findCommand = document.getElementById("cmd_find");
|
||||||
|
findCommand.doCommand();
|
||||||
|
|
||||||
|
let searchStr = "e";
|
||||||
|
enterStringIntoFindField(searchStr);
|
||||||
|
|
||||||
|
let a = gFindBar._findField.value;
|
||||||
|
let b = gFindBar._browser.finder._fastFind.searchString;
|
||||||
|
let c = gFindBar._browser.finder.searchString;
|
||||||
|
ok(a == b && b == c, "testFindWithHighlight: " + a + ", " + b + ", " + c + ".");
|
||||||
|
|
||||||
|
let oldGetInitialSelection = gFindBar._getInitialSelection;
|
||||||
|
let searchStr = "t";
|
||||||
|
gFindBar._getInitialSelection = () => searchStr;
|
||||||
|
findCommand.doCommand();
|
||||||
|
gFindBar._getInitialSelection = oldGetInitialSelection;
|
||||||
|
|
||||||
|
a = gFindBar._findField.value;
|
||||||
|
b = gFindBar._browser.finder._fastFind.searchString;
|
||||||
|
c = gFindBar._browser.finder.searchString;
|
||||||
|
ok(a == searchStr && b == c, "testFindWithHighlight: " + a + ", " + b + ", " + c + ".");
|
||||||
|
|
||||||
|
let highlightButton = gFindBar.getElement("highlight");
|
||||||
|
highlightButton.click();
|
||||||
|
ok(highlightButton.checked, "testFindWithHighlight: Highlight All should be checked.");
|
||||||
|
|
||||||
|
a = gFindBar._findField.value;
|
||||||
|
b = gFindBar._browser.finder._fastFind.searchString;
|
||||||
|
c = gFindBar._browser.finder.searchString;
|
||||||
|
ok(a == searchStr && b == c, "testFindWithHighlight: " + a + ", " + b + ", " + c + ".");
|
||||||
|
|
||||||
|
gFindBar.onFindAgainCommand();
|
||||||
|
a = gFindBar._findField.value;
|
||||||
|
b = gFindBar._browser.finder._fastFind.searchString;
|
||||||
|
c = gFindBar._browser.finder.searchString;
|
||||||
|
ok(a == b && b == c, "testFindWithHighlight: " + a + ", " + b + ", " + c + ".");
|
||||||
|
|
||||||
|
highlightButton.click();
|
||||||
|
ok(!highlightButton.checked, "testFindWithHighlight: Highlight All should be unchecked.");
|
||||||
|
}
|
||||||
|
|
||||||
function testQuickFindText() {
|
function testQuickFindText() {
|
||||||
clearFocus();
|
clearFocus();
|
||||||
|
|
||||||
|
|
|
@ -123,8 +123,7 @@
|
||||||
<handler event="compositionend"><![CDATA[
|
<handler event="compositionend"><![CDATA[
|
||||||
let findbar = this.findbar;
|
let findbar = this.findbar;
|
||||||
findbar._isIMEComposing = false;
|
findbar._isIMEComposing = false;
|
||||||
if (findbar._findMode != findbar.FIND_NORMAL &&
|
if (findbar._findMode != findbar.FIND_NORMAL)
|
||||||
!findbar.hidden)
|
|
||||||
findbar._setFindCloseTimeout();
|
findbar._setFindCloseTimeout();
|
||||||
]]></handler>
|
]]></handler>
|
||||||
|
|
||||||
|
@ -410,17 +409,18 @@
|
||||||
if (this._quickFindTimeout)
|
if (this._quickFindTimeout)
|
||||||
clearTimeout(this._quickFindTimeout);
|
clearTimeout(this._quickFindTimeout);
|
||||||
|
|
||||||
// Don't close the find toolbar while IME is composing.
|
// Don't close the find toolbar while IME is composing OR when the
|
||||||
if (this._isIMEComposing) {
|
// findbar is already hidden.
|
||||||
|
if (this._isIMEComposing || this.hidden) {
|
||||||
this._quickFindTimeout = null;
|
this._quickFindTimeout = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._quickFindTimeout =
|
this._quickFindTimeout = setTimeout(() => {
|
||||||
setTimeout(function(aSelf) {
|
if (this._findMode != this.FIND_NORMAL)
|
||||||
if (aSelf._findMode != aSelf.FIND_NORMAL)
|
this.close();
|
||||||
aSelf.close();
|
this._quickFindTimeout = null;
|
||||||
}, this._quickFindTimeoutLength, this);
|
}, this._quickFindTimeoutLength);
|
||||||
]]></body>
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
@ -1127,7 +1127,7 @@
|
||||||
else
|
else
|
||||||
this._findFailedString = null;
|
this._findFailedString = null;
|
||||||
|
|
||||||
if (this._findMode != this.FIND_NORMAL && !this.hidden)
|
if (this._findMode != this.FIND_NORMAL)
|
||||||
this._setFindCloseTimeout();
|
this._setFindCloseTimeout();
|
||||||
]]></body>
|
]]></body>
|
||||||
</method>
|
</method>
|
||||||
|
|
|
@ -11,6 +11,7 @@ Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/devtools/SourceMap.jsm");
|
Cu.import("resource://gre/modules/devtools/SourceMap.jsm");
|
||||||
|
Cu.import("resource://gre/modules/Task.jsm");
|
||||||
|
|
||||||
const promise = require("sdk/core/promise");
|
const promise = require("sdk/core/promise");
|
||||||
const events = require("sdk/event/core");
|
const events = require("sdk/event/core");
|
||||||
|
@ -94,18 +95,7 @@ let StyleSheetsActor = protocol.ActorClass({
|
||||||
let window = this.window;
|
let window = this.window;
|
||||||
var domReady = () => {
|
var domReady = () => {
|
||||||
window.removeEventListener("DOMContentLoaded", domReady, true);
|
window.removeEventListener("DOMContentLoaded", domReady, true);
|
||||||
|
this._addAllStyleSheets().then(deferred.resolve, Cu.reportError);
|
||||||
let documents = [this.document];
|
|
||||||
let actors = [];
|
|
||||||
for (let doc of documents) {
|
|
||||||
let sheets = this._addStyleSheets(doc.styleSheets);
|
|
||||||
actors = actors.concat(sheets);
|
|
||||||
// Recursively handle style sheets of the documents in iframes.
|
|
||||||
for (let iframe of doc.getElementsByTagName("iframe")) {
|
|
||||||
documents.push(iframe.contentDocument);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
deferred.resolve(actors);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (window.document.readyState === "loading") {
|
if (window.document.readyState === "loading") {
|
||||||
|
@ -120,29 +110,55 @@ let StyleSheetsActor = protocol.ActorClass({
|
||||||
response: { styleSheets: RetVal("array:stylesheet") }
|
response: { styleSheets: RetVal("array:stylesheet") }
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all the stylesheets in this document and its subframes.
|
||||||
|
* Assumes the document is loaded.
|
||||||
|
*
|
||||||
|
* @return {Promise}
|
||||||
|
* Promise that resolves with an array of StyleSheetActors
|
||||||
|
*/
|
||||||
|
_addAllStyleSheets: function() {
|
||||||
|
return Task.spawn(function() {
|
||||||
|
let documents = [this.document];
|
||||||
|
let actors = [];
|
||||||
|
|
||||||
|
for (let doc of documents) {
|
||||||
|
let sheets = yield this._addStyleSheets(doc.styleSheets);
|
||||||
|
actors = actors.concat(sheets);
|
||||||
|
|
||||||
|
// Recursively handle style sheets of the documents in iframes.
|
||||||
|
for (let iframe of doc.getElementsByTagName("iframe")) {
|
||||||
|
documents.push(iframe.contentDocument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Task.Result(actors);
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add all the stylesheets to the map and create an actor for each one
|
* Add all the stylesheets to the map and create an actor for each one
|
||||||
* if not already created. Send event that there are new stylesheets.
|
* if not already created.
|
||||||
*
|
*
|
||||||
* @param {[DOMStyleSheet]} styleSheets
|
* @param {[DOMStyleSheet]} styleSheets
|
||||||
* Stylesheets to add
|
* Stylesheets to add
|
||||||
* @return {[object]}
|
*
|
||||||
* Array of actors for each StyleSheetActor created
|
* @return {Promise}
|
||||||
|
* Promise that resolves to an array of StyleSheetActors
|
||||||
*/
|
*/
|
||||||
_addStyleSheets: function(styleSheets)
|
_addStyleSheets: function(styleSheets)
|
||||||
{
|
{
|
||||||
let sheets = [];
|
return Task.spawn(function() {
|
||||||
for (let i = 0; i < styleSheets.length; i++) {
|
let actors = [];
|
||||||
let styleSheet = styleSheets[i];
|
for (let i = 0; i < styleSheets.length; i++) {
|
||||||
sheets.push(styleSheet);
|
let actor = this._createStyleSheetActor(styleSheets[i]);
|
||||||
|
actors.push(actor);
|
||||||
|
|
||||||
// Get all sheets, including imported ones
|
// Get all sheets, including imported ones
|
||||||
let imports = this._getImported(styleSheet);
|
let imports = yield this._getImported(actor);
|
||||||
sheets = sheets.concat(imports);
|
actors = actors.concat(imports);
|
||||||
}
|
}
|
||||||
let actors = sheets.map(this._createStyleSheetActor.bind(this));
|
throw new Task.Result(actors);
|
||||||
|
}.bind(this));
|
||||||
return actors;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,31 +166,37 @@ let StyleSheetsActor = protocol.ActorClass({
|
||||||
*
|
*
|
||||||
* @param {DOMStyleSheet} styleSheet
|
* @param {DOMStyleSheet} styleSheet
|
||||||
* Style sheet to search
|
* Style sheet to search
|
||||||
* @return {array}
|
* @return {Promise}
|
||||||
* All the imported stylesheets
|
* A promise that resolves with an array of StyleSheetActors
|
||||||
*/
|
*/
|
||||||
_getImported: function(styleSheet) {
|
_getImported: function(styleSheet) {
|
||||||
let imported = [];
|
return Task.spawn(function() {
|
||||||
|
let rules = yield styleSheet.getCSSRules();
|
||||||
|
let imported = [];
|
||||||
|
|
||||||
for (let i = 0; i < styleSheet.cssRules.length; i++) {
|
for (let i = 0; i < rules.length; i++) {
|
||||||
let rule = styleSheet.cssRules[i];
|
let rule = rules[i];
|
||||||
if (rule.type == Ci.nsIDOMCSSRule.IMPORT_RULE) {
|
if (rule.type == Ci.nsIDOMCSSRule.IMPORT_RULE) {
|
||||||
// Associated styleSheet may be null if it has already been seen due to
|
// Associated styleSheet may be null if it has already been seen due
|
||||||
// duplicate @imports for the same URL.
|
// to duplicate @imports for the same URL.
|
||||||
if (!rule.styleSheet) {
|
if (!rule.styleSheet) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
let actor = this._createStyleSheetActor(rule.styleSheet);
|
||||||
|
imported.push(actor);
|
||||||
|
|
||||||
|
// recurse imports in this stylesheet as well
|
||||||
|
let children = yield this._getImported(actor);
|
||||||
|
imported = imported.concat(children);
|
||||||
}
|
}
|
||||||
imported.push(rule.styleSheet);
|
else if (rule.type != Ci.nsIDOMCSSRule.CHARSET_RULE) {
|
||||||
|
// @import rules must precede all others except @charset
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// recurse imports in this stylesheet as well
|
throw new Task.Result(imported);
|
||||||
imported = imported.concat(this._getImported(rule.styleSheet));
|
}.bind(this));
|
||||||
}
|
|
||||||
else if (rule.type != Ci.nsIDOMCSSRule.CHARSET_RULE) {
|
|
||||||
// @import rules must precede all others except @charset
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return imported;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -319,17 +341,50 @@ let StyleSheetActor = protocol.ActorClass({
|
||||||
this._styleSheetIndex = -1;
|
this._styleSheetIndex = -1;
|
||||||
|
|
||||||
this._transitionRefCount = 0;
|
this._transitionRefCount = 0;
|
||||||
|
},
|
||||||
|
|
||||||
// if this sheet has an @import, then it's rules are loaded async
|
/**
|
||||||
let ownerNode = this.rawSheet.ownerNode;
|
* Get the raw stylesheet's cssRules once the sheet has been loaded.
|
||||||
if (ownerNode) {
|
*
|
||||||
let onSheetLoaded = function(event) {
|
* @return {Promise}
|
||||||
ownerNode.removeEventListener("load", onSheetLoaded, false);
|
* Promise that resolves with a CSSRuleList
|
||||||
this._notifyPropertyChanged("ruleCount");
|
*/
|
||||||
}.bind(this);
|
getCSSRules: function() {
|
||||||
|
let rules;
|
||||||
ownerNode.addEventListener("load", onSheetLoaded, false);
|
try {
|
||||||
|
rules = this.rawSheet.cssRules;
|
||||||
}
|
}
|
||||||
|
catch (e) {
|
||||||
|
// sheet isn't loaded yet
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rules) {
|
||||||
|
return promise.resolve(rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
let ownerNode = this.rawSheet.ownerNode;
|
||||||
|
if (!ownerNode) {
|
||||||
|
return promise.resolve([]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._cssRules) {
|
||||||
|
return this._cssRules;
|
||||||
|
}
|
||||||
|
|
||||||
|
let deferred = promise.defer();
|
||||||
|
|
||||||
|
let onSheetLoaded = function(event) {
|
||||||
|
ownerNode.removeEventListener("load", onSheetLoaded, false);
|
||||||
|
|
||||||
|
deferred.resolve(this.rawSheet.cssRules);
|
||||||
|
}.bind(this);
|
||||||
|
|
||||||
|
ownerNode.addEventListener("load", onSheetLoaded, false);
|
||||||
|
|
||||||
|
// cache so we don't add many listeners if this is called multiple times.
|
||||||
|
this._cssRules = deferred.promise;
|
||||||
|
|
||||||
|
return this._cssRules;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -369,6 +424,9 @@ let StyleSheetActor = protocol.ActorClass({
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
// stylesheet had an @import rule that wasn't loaded yet
|
// stylesheet had an @import rule that wasn't loaded yet
|
||||||
|
this.getCSSRules().then(() => {
|
||||||
|
this._notifyPropertyChanged("ruleCount");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return form;
|
return form;
|
||||||
},
|
},
|
||||||
|
|
|
@ -111,11 +111,12 @@ function safeGetState(state) {
|
||||||
if (!state) {
|
if (!state) {
|
||||||
return "(none)";
|
return "(none)";
|
||||||
}
|
}
|
||||||
|
let data, string;
|
||||||
try {
|
try {
|
||||||
// Evaluate state(), normalize the result into something that we can
|
// Evaluate state(), normalize the result into something that we can
|
||||||
// safely stringify or upload.
|
// safely stringify or upload.
|
||||||
let string = JSON.stringify(state());
|
string = JSON.stringify(state());
|
||||||
let data = JSON.parse(string);
|
data = JSON.parse(string);
|
||||||
// Simplify the rest of the code by ensuring that we can simply
|
// Simplify the rest of the code by ensuring that we can simply
|
||||||
// concatenate the result to a message.
|
// concatenate the result to a message.
|
||||||
if (data && typeof data == "object") {
|
if (data && typeof data == "object") {
|
||||||
|
@ -125,6 +126,9 @@ function safeGetState(state) {
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
|
if (string) {
|
||||||
|
return string;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return "Error getting state: " + ex + " at " + ex.stack;
|
return "Error getting state: " + ex + " at " + ex.stack;
|
||||||
} catch (ex2) {
|
} catch (ex2) {
|
||||||
|
|
|
@ -36,8 +36,9 @@ Finder.prototype = {
|
||||||
this._listeners = this._listeners.filter(l => l != aListener);
|
this._listeners = this._listeners.filter(l => l != aListener);
|
||||||
},
|
},
|
||||||
|
|
||||||
_notify: function (aSearchString, aResult, aFindBackwards, aDrawOutline) {
|
_notify: function (aSearchString, aResult, aFindBackwards, aDrawOutline, aStoreResult = true) {
|
||||||
this._searchString = aSearchString;
|
if (aStoreResult)
|
||||||
|
this._searchString = aSearchString;
|
||||||
this._outlineLink(aDrawOutline);
|
this._outlineLink(aDrawOutline);
|
||||||
|
|
||||||
let foundLink = this._fastFind.foundLink;
|
let foundLink = this._fastFind.foundLink;
|
||||||
|
@ -62,6 +63,7 @@ Finder.prototype = {
|
||||||
linkURL: linkURL,
|
linkURL: linkURL,
|
||||||
rect: this._getResultRect(),
|
rect: this._getResultRect(),
|
||||||
searchString: this._searchString,
|
searchString: this._searchString,
|
||||||
|
storeResult: aStoreResult
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let l of this._listeners) {
|
for (let l of this._listeners) {
|
||||||
|
@ -110,7 +112,7 @@ Finder.prototype = {
|
||||||
if (aHighlight) {
|
if (aHighlight) {
|
||||||
let result = found ? Ci.nsITypeAheadFind.FIND_FOUND
|
let result = found ? Ci.nsITypeAheadFind.FIND_FOUND
|
||||||
: Ci.nsITypeAheadFind.FIND_NOTFOUND;
|
: Ci.nsITypeAheadFind.FIND_NOTFOUND;
|
||||||
this._notify(aWord, result, false, false);
|
this._notify(aWord, result, false, false, false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -5,213 +5,213 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "GonkMemoryPressureMonitoring.h"
|
#include "GonkMemoryPressureMonitoring.h"
|
||||||
|
#include "mozilla/ArrayUtils.h"
|
||||||
|
#include "mozilla/FileUtils.h"
|
||||||
|
#include "mozilla/Monitor.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/Services.h"
|
#include "mozilla/Services.h"
|
||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
#include "nsIObserverService.h"
|
#include "nsIObserverService.h"
|
||||||
#include "nsMemoryPressure.h"
|
#include "nsMemoryPressure.h"
|
||||||
#include "nsXULAppAPI.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "base/message_loop.h"
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <poll.h>
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
|
|
||||||
#define LOG(args...) \
|
#define LOG(args...) \
|
||||||
__android_log_print(ANDROID_LOG_INFO, "GonkMemoryPressure" , ## args)
|
__android_log_print(ANDROID_LOG_INFO, "GonkMemoryPressure" , ## args)
|
||||||
|
|
||||||
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
#include "ipc/Nuwa.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
//
|
/**
|
||||||
// MemoryPressureWatcher watches on the I/O thread for changes to the
|
* MemoryPressureWatcher watches sysfs from its own thread to notice when the
|
||||||
// lowmemkiller's sysfs interface. If the system runs low on memory,
|
* system is under memory pressure. When we observe memory pressure, we use
|
||||||
// MemoryPressureWatcher sends a MemoryPressureEvent, removes itself
|
* MemoryPressureRunnable to notify observers that they should release memory.
|
||||||
// from the I/O loop, and schedules a PollTask to re-start polling
|
*
|
||||||
// after a timeout has been reached.
|
* When the system is under memory pressure, we don't want to constantly fire
|
||||||
//
|
* memory-pressure events. So instead, we try to detect when sysfs indicates
|
||||||
// The PollTask is allocated by MemoryPressureWatcher and handed over
|
* that we're no longer under memory pressure, and only then start firing events
|
||||||
// to the I/O loop, which then owns the object and deletes it after it
|
* again.
|
||||||
// ran. We cannot allocate the object dynamically, because the system
|
*
|
||||||
// is already low on memory. Instead we overload the new and delete
|
* (This is a bit problematic because we can't poll() to detect when we're no
|
||||||
// operators for PollTask to hand-out statically allocated memory.
|
* longer under memory pressure; instead we have to periodically read the sysfs
|
||||||
// There can only be at most one instance of PollTask at a time, so
|
* node. If we remain under memory pressure for a long time, this means we'll
|
||||||
// we can re-use the same memory on each allocation.
|
* continue waking up to read from the node for a long time, potentially wasting
|
||||||
//
|
* battery life. Hopefully we don't hit this case in practice! We write to
|
||||||
// There is a separate observer for shutdown events. When the system
|
* logcat each time we go around this loop so it's at least noticable.)
|
||||||
// shuts down, it sends a task to the I/O thread for removing the
|
*
|
||||||
// watcher. If a PollTask is pending, it gets canceled. We cannot
|
* Shutting down safely is a bit of a chore. XPCOM won't shut down until all
|
||||||
// delete it at this point, because it's owned by the I/O loop.
|
* threads exit, so we need to exit the Run() method below on shutdown. But our
|
||||||
//
|
* thread might be blocked in one of two situations: We might be poll()'ing the
|
||||||
class MemoryPressureWatcher : public MessageLoopForIO::Watcher
|
* sysfs node waiting for memory pressure to occur, or we might be asleep
|
||||||
|
* waiting to read() the sysfs node to see if we're no longer under memory
|
||||||
|
* pressure.
|
||||||
|
*
|
||||||
|
* To let us wake up from the poll(), we poll() not just the sysfs node but also
|
||||||
|
* a pipe, which we write to on shutdown. To let us wake up from sleeping
|
||||||
|
* between read()s, we sleep by Wait()'ing on a monitor, which we notify on
|
||||||
|
* shutdown.
|
||||||
|
*/
|
||||||
|
class MemoryPressureWatcher
|
||||||
|
: public nsIRunnable
|
||||||
|
, public nsIObserver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
class PollTask : public CancelableTask
|
MemoryPressureWatcher()
|
||||||
|
: mMonitor("MemoryPressureWatcher")
|
||||||
|
, mShuttingDown(false)
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
PollTask(MemoryPressureWatcher* aWatcher)
|
|
||||||
: mWatcher(aWatcher)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mWatcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void* operator new(size_t aSize);
|
|
||||||
static void operator delete(void* aMem, size_t aSize);
|
|
||||||
|
|
||||||
void Run() MOZ_OVERRIDE
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(MessageLoopForIO::current());
|
|
||||||
|
|
||||||
if (mWatcher) {
|
|
||||||
MOZ_ASSERT(MessageLoopForIO::current() == mWatcher->GetIOLoop());
|
|
||||||
mWatcher->StartWatching();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Cancel() MOZ_OVERRIDE
|
|
||||||
{
|
|
||||||
mWatcher = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
MemoryPressureWatcher* mWatcher;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <size_t Size> class PollTaskAllocator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void* Alloc()
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(!sAllocated);
|
|
||||||
sAllocated = true;
|
|
||||||
return mMem;
|
|
||||||
}
|
|
||||||
void Release(void* aMem)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mMem == aMem);
|
|
||||||
MOZ_ASSERT(sAllocated);
|
|
||||||
sAllocated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static bool sAllocated;
|
|
||||||
unsigned char mMem[Size];
|
|
||||||
};
|
|
||||||
|
|
||||||
MemoryPressureWatcher(MessageLoop* aIOLoop, uint32_t aPollMS)
|
|
||||||
: mFd(-1)
|
|
||||||
, mIOLoop(aIOLoop)
|
|
||||||
, mPollTask(nullptr)
|
|
||||||
, mPollMS(aPollMS)
|
|
||||||
, mMemoryPressure(false)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mIOLoop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~MemoryPressureWatcher()
|
NS_DECL_THREADSAFE_ISUPPORTS
|
||||||
|
|
||||||
|
nsresult Init()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop);
|
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
||||||
MOZ_ASSERT(mFd == -1);
|
NS_ENSURE_STATE(os);
|
||||||
|
|
||||||
|
// The observer service holds us alive.
|
||||||
|
os->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, /* holdsWeak */ false);
|
||||||
|
|
||||||
|
// While we're under memory pressure, we periodically read()
|
||||||
|
// notify_trigger_active to try and see when we're no longer under memory
|
||||||
|
// pressure. mPollMS indicates how many milliseconds we wait between those
|
||||||
|
// read()s.
|
||||||
|
mPollMS = Preferences::GetUint("gonk.systemMemoryPressureRecoveryPollMS",
|
||||||
|
/* default */ 5000);
|
||||||
|
|
||||||
|
int pipes[2];
|
||||||
|
NS_ENSURE_STATE(!pipe(pipes));
|
||||||
|
mShutdownPipeRead = pipes[0];
|
||||||
|
mShutdownPipeWrite = pipes[1];
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageLoop* GetIOLoop () const
|
NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
|
||||||
|
const char16_t* aData)
|
||||||
{
|
{
|
||||||
return mIOLoop;
|
MOZ_ASSERT(strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0);
|
||||||
}
|
LOG("Observed XPCOM shutdown.");
|
||||||
|
|
||||||
nsresult Open()
|
MonitorAutoLock lock(mMonitor);
|
||||||
{
|
mShuttingDown = true;
|
||||||
MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop);
|
mMonitor.Notify();
|
||||||
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
|
int rv;
|
||||||
do {
|
do {
|
||||||
fd = open("/sys/kernel/mm/lowmemkiller/notify_trigger_active",
|
// Write something to the pipe; doesn't matter what.
|
||||||
O_RDONLY | O_CLOEXEC);
|
uint32_t dummy = 0;
|
||||||
} while (fd == -1 && errno == EINTR);
|
rv = write(mShutdownPipeWrite, &dummy, sizeof(dummy));
|
||||||
|
} while(rv == -1 && errno == EINTR);
|
||||||
if (NS_WARN_IF(fd == -1)) {
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
mFd = fd;
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Close()
|
NS_IMETHOD Run()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop);
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
|
||||||
if (NS_WARN_IF(mFd == -1)) {
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
return;
|
if (IsNuwaProcess()) {
|
||||||
|
NS_ASSERTION(NuwaMarkCurrentThread != nullptr,
|
||||||
|
"NuwaMarkCurrentThread is undefined!");
|
||||||
|
NuwaMarkCurrentThread(nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int res;
|
int lowMemFd = open("/sys/kernel/mm/lowmemkiller/notify_trigger_active",
|
||||||
|
O_RDONLY | O_CLOEXEC);
|
||||||
|
NS_ENSURE_STATE(lowMemFd != -1);
|
||||||
|
ScopedClose autoClose(lowMemFd);
|
||||||
|
|
||||||
do {
|
nsresult rv = CheckForMemoryPressure(lowMemFd, nullptr);
|
||||||
res = close(mFd);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
} while (res == -1 && errno == EINTR);
|
|
||||||
|
|
||||||
NS_WARN_IF(res == -1);
|
while (true) {
|
||||||
mFd = -1;
|
// Wait for a notification on lowMemFd or for data to be written to
|
||||||
}
|
// mShutdownPipeWrite. (poll(lowMemFd, POLLPRI) blocks until we're under
|
||||||
|
// memory pressure.)
|
||||||
|
struct pollfd pollfds[2];
|
||||||
|
pollfds[0].fd = lowMemFd;
|
||||||
|
pollfds[0].events = POLLPRI;
|
||||||
|
pollfds[1].fd = mShutdownPipeRead;
|
||||||
|
pollfds[1].events = POLLIN;
|
||||||
|
|
||||||
void StartWatching()
|
int pollRv;
|
||||||
{
|
do {
|
||||||
MessageLoopForIO* ioLoop = MessageLoopForIO::current();
|
pollRv = poll(pollfds, ArrayLength(pollfds), /* timeout */ -1);
|
||||||
MOZ_ASSERT(ioLoop == mIOLoop);
|
} while (pollRv == -1 && errno == EINTR);
|
||||||
ioLoop->WatchFileDescriptor(mFd, true, MessageLoopForIO::WATCH_READ,
|
|
||||||
&mReadWatcher, this);
|
|
||||||
mPollTask = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void StopWatching()
|
if (pollfds[1].revents) {
|
||||||
{
|
// Something was written to our shutdown pipe; we're outta here.
|
||||||
if (mPollTask) {
|
LOG("shutting down (1)");
|
||||||
mPollTask->Cancel();
|
return NS_OK;
|
||||||
}
|
|
||||||
mReadWatcher.StopWatchingFileDescriptor();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void OnFileCanWriteWithoutBlocking(int aFd) MOZ_OVERRIDE
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop);
|
|
||||||
NS_WARNING("Must not write to memory monitor");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void OnFileCanReadWithoutBlocking(int aFd) MOZ_OVERRIDE
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(MessageLoopForIO::current() == mIOLoop);
|
|
||||||
|
|
||||||
bool memoryPressure;
|
|
||||||
nsresult rv = CheckForMemoryPressure(memoryPressure);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memoryPressure) {
|
|
||||||
LOG("Memory pressure detected.");
|
|
||||||
StopWatching();
|
|
||||||
if (mMemoryPressure) {
|
|
||||||
rv = NS_DispatchMemoryPressure(MemPressure_Ongoing);
|
|
||||||
} else {
|
|
||||||
rv = NS_DispatchMemoryPressure(MemPressure_New);
|
|
||||||
}
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// While we're under memory pressure, we periodically read()
|
// If pollfds[1] isn't happening, pollfds[0] ought to be!
|
||||||
// notify_trigger_active to try and see when we're no longer under
|
if (!(pollfds[0].revents & POLLPRI)) {
|
||||||
// memory pressure. mPollMS indicates how many milliseconds we wait
|
LOG("Unexpected revents value after poll(): %d. "
|
||||||
// between those read()s.
|
"Shutting down GonkMemoryPressureMonitoring.", pollfds[0].revents);
|
||||||
mPollTask = new PollTask(this);
|
return NS_ERROR_FAILURE;
|
||||||
mIOLoop->PostDelayedTask(FROM_HERE, mPollTask, mPollMS);
|
}
|
||||||
} else if (mMemoryPressure) {
|
|
||||||
|
// POLLPRI on lowMemFd indicates that we're in a low-memory situation. We
|
||||||
|
// could read lowMemFd to double-check, but we've observed that the read
|
||||||
|
// sometimes completes after the memory-pressure event is over, so let's
|
||||||
|
// just believe the result of poll().
|
||||||
|
|
||||||
|
// We use low-memory-no-forward because each process has its own watcher
|
||||||
|
// and thus there is no need for the main process to forward this event.
|
||||||
|
rv = NS_DispatchMemoryPressure(MemPressure_New);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
// Manually check lowMemFd until we observe that memory pressure is over.
|
||||||
|
// We won't fire any more low-memory events until we observe that
|
||||||
|
// we're no longer under pressure. Instead, we fire low-memory-ongoing
|
||||||
|
// events, which cause processes to keep flushing caches but will not
|
||||||
|
// trigger expensive GCs and other attempts to save memory that are
|
||||||
|
// likely futile at this point.
|
||||||
|
bool memoryPressure;
|
||||||
|
do {
|
||||||
|
{
|
||||||
|
MonitorAutoLock lock(mMonitor);
|
||||||
|
|
||||||
|
// We need to check mShuttingDown before we wait here, in order to
|
||||||
|
// catch a shutdown signal sent after we poll()'ed mShutdownPipeRead
|
||||||
|
// above but before we started waiting on the monitor. But we don't
|
||||||
|
// need to check after we wait, because we'll either do another
|
||||||
|
// iteration of this inner loop, in which case we'll check
|
||||||
|
// mShuttingDown, or we'll exit this loop and do another iteration
|
||||||
|
// of the outer loop, in which case we'll check the shutdown pipe.
|
||||||
|
if (mShuttingDown) {
|
||||||
|
LOG("shutting down (2)");
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
mMonitor.Wait(PR_MillisecondsToInterval(mPollMS));
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("Checking to see if memory pressure is over.");
|
||||||
|
rv = CheckForMemoryPressure(lowMemFd, &memoryPressure);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (memoryPressure) {
|
||||||
|
rv = NS_DispatchMemoryPressure(MemPressure_Ongoing);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} while (false);
|
||||||
|
|
||||||
LOG("Memory pressure is over.");
|
LOG("Memory pressure is over.");
|
||||||
}
|
}
|
||||||
mMemoryPressure = memoryPressure;
|
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -222,138 +222,38 @@ private:
|
||||||
*
|
*
|
||||||
* We don't expect this method to block.
|
* We don't expect this method to block.
|
||||||
*/
|
*/
|
||||||
nsresult CheckForMemoryPressure(bool& aOut)
|
nsresult CheckForMemoryPressure(int aLowMemFd, bool* aOut)
|
||||||
{
|
{
|
||||||
aOut = false;
|
if (aOut) {
|
||||||
|
*aOut = false;
|
||||||
off_t off = lseek(mFd, 0, SEEK_SET);
|
|
||||||
if (NS_WARN_IF(off)) {
|
|
||||||
return NS_ERROR_UNEXPECTED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lseek(aLowMemFd, 0, SEEK_SET);
|
||||||
|
|
||||||
char buf[2];
|
char buf[2];
|
||||||
int nread;
|
int nread;
|
||||||
do {
|
do {
|
||||||
nread = read(mFd, buf, sizeof(buf));
|
nread = read(aLowMemFd, buf, sizeof(buf));
|
||||||
} while(nread == -1 && errno == EINTR);
|
} while(nread == -1 && errno == EINTR);
|
||||||
if (NS_WARN_IF(nread != 2)) {
|
NS_ENSURE_STATE(nread == 2);
|
||||||
return NS_ERROR_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The notify_trigger_active sysfs node should contain either "0\n" or
|
// The notify_trigger_active sysfs node should contain either "0\n" or
|
||||||
// "1\n". The latter indicates memory pressure.
|
// "1\n". The latter indicates memory pressure.
|
||||||
aOut = buf[0] == '1' && buf[1] == '\n';
|
if (aOut) {
|
||||||
|
*aOut = buf[0] == '1' && buf[1] == '\n';
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mFd;
|
|
||||||
MessageLoop* mIOLoop;
|
|
||||||
MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
|
|
||||||
PollTask* mPollTask;
|
|
||||||
uint32_t mPollMS;
|
|
||||||
bool mMemoryPressure;
|
|
||||||
};
|
|
||||||
|
|
||||||
static
|
|
||||||
MemoryPressureWatcher::PollTaskAllocator<sizeof(MemoryPressureWatcher::PollTask)>
|
|
||||||
sPollTaskAllocator;
|
|
||||||
|
|
||||||
template<>
|
|
||||||
bool
|
|
||||||
MemoryPressureWatcher::PollTaskAllocator<sizeof(MemoryPressureWatcher::PollTask)>::sAllocated(false);
|
|
||||||
|
|
||||||
void*
|
|
||||||
MemoryPressureWatcher::PollTask::operator new(size_t aSize)
|
|
||||||
{
|
|
||||||
return sPollTaskAllocator.Alloc();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
MemoryPressureWatcher::PollTask::operator delete(void* aMem, size_t aSize)
|
|
||||||
{
|
|
||||||
sPollTaskAllocator.Release(aMem);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initializes MemoryPressureWatcher on I/O thread
|
|
||||||
//
|
|
||||||
class InitMemoryPressureWatcherTask : public Task
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
InitMemoryPressureWatcherTask(MemoryPressureWatcher* aWatcher)
|
|
||||||
: mWatcher(aWatcher)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mWatcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Run() MOZ_OVERRIDE
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(MessageLoopForIO::current() == mWatcher->GetIOLoop());
|
|
||||||
|
|
||||||
nsresult rv = mWatcher->Open();
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
mWatcher->StartWatching();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
MemoryPressureWatcher* mWatcher;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Releases MemoryPressureWatcher on I/O thread
|
|
||||||
//
|
|
||||||
class ShutdownMemoryPressureWatcherTask : public Task
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ShutdownMemoryPressureWatcherTask(MemoryPressureWatcher* aWatcher)
|
|
||||||
: mWatcher(aWatcher)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mWatcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Run() MOZ_OVERRIDE
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(MessageLoopForIO::current() == mWatcher->GetIOLoop());
|
|
||||||
|
|
||||||
mWatcher->StopWatching();
|
|
||||||
mWatcher->Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
nsAutoPtr<MemoryPressureWatcher> mWatcher;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Closes MemoryPressureWatcher on shutdown
|
|
||||||
//
|
|
||||||
class ShutdownObserver : public nsIObserver
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ShutdownObserver(MemoryPressureWatcher* aWatcher)
|
|
||||||
: mWatcher(aWatcher)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mWatcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_DECL_THREADSAFE_ISUPPORTS
|
|
||||||
|
|
||||||
NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
|
|
||||||
const char16_t* aData)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID));
|
|
||||||
LOG("Observed XPCOM shutdown.");
|
|
||||||
|
|
||||||
Task* task = new ShutdownMemoryPressureWatcherTask(mWatcher);
|
|
||||||
mWatcher->GetIOLoop()->PostTask(FROM_HERE, task);
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
Monitor mMonitor;
|
||||||
MemoryPressureWatcher* mWatcher;
|
uint32_t mPollMS;
|
||||||
|
bool mShuttingDown;
|
||||||
|
|
||||||
|
ScopedClose mShutdownPipeRead;
|
||||||
|
ScopedClose mShutdownPipeWrite;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS1(ShutdownObserver, nsIObserver);
|
NS_IMPL_ISUPPORTS2(MemoryPressureWatcher, nsIRunnable, nsIObserver);
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
|
@ -362,22 +262,13 @@ namespace mozilla {
|
||||||
void
|
void
|
||||||
InitGonkMemoryPressureMonitoring()
|
InitGonkMemoryPressureMonitoring()
|
||||||
{
|
{
|
||||||
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
|
// memoryPressureWatcher is held alive by the observer service.
|
||||||
uint32_t pollMS =
|
nsRefPtr<MemoryPressureWatcher> memoryPressureWatcher =
|
||||||
Preferences::GetUint("gonk.systemMemoryPressureRecoveryPollMS", 5000);
|
new MemoryPressureWatcher();
|
||||||
MemoryPressureWatcher* watcher = new MemoryPressureWatcher(ioLoop, pollMS);
|
NS_ENSURE_SUCCESS_VOID(memoryPressureWatcher->Init());
|
||||||
|
|
||||||
// Start watcher on I/O thread
|
nsCOMPtr<nsIThread> thread;
|
||||||
Task* task = new InitMemoryPressureWatcherTask(watcher);
|
NS_NewThread(getter_AddRefs(thread), memoryPressureWatcher);
|
||||||
watcher->GetIOLoop()->PostTask(FROM_HERE, task);
|
|
||||||
|
|
||||||
// Install shutdown observer
|
|
||||||
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
|
||||||
if (NS_WARN_IF(!os)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nsRefPtr<ShutdownObserver> observer = new ShutdownObserver(watcher);
|
|
||||||
os->AddObserver(observer, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
Загрузка…
Ссылка в новой задаче