mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to inbound a=merge CLOSED TREE
This commit is contained in:
commit
81c5733880
@ -15,7 +15,7 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="22230c9a340a0a2c3af73320cf47e1cb544517ad"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="7512026a377271a0cade12d70846557f0bc7781c"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="22230c9a340a0a2c3af73320cf47e1cb544517ad"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7512026a377271a0cade12d70846557f0bc7781c"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="22230c9a340a0a2c3af73320cf47e1cb544517ad"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="7512026a377271a0cade12d70846557f0bc7781c"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1ddea3133e0807350326cee5dcf0d06fad00c08"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1ddea3133e0807350326cee5dcf0d06fad00c08"/>
|
||||||
@ -135,7 +135,7 @@
|
|||||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c5f8d282efe4a4e8b1e31a37300944e338e60e4f"/>
|
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c5f8d282efe4a4e8b1e31a37300944e338e60e4f"/>
|
||||||
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
|
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9f28c4faea3b2f01db227b2467b08aeba96d9bec"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9f28c4faea3b2f01db227b2467b08aeba96d9bec"/>
|
||||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d19dad5844e8803d5e88d1577a2742b4f5cbc467"/>
|
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="84395037a7a04546e8ef7cb81572eb516b85562b"/>
|
||||||
<project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
|
<project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
|
||||||
<project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
|
<project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="22230c9a340a0a2c3af73320cf47e1cb544517ad"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="7512026a377271a0cade12d70846557f0bc7781c"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
|
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="22230c9a340a0a2c3af73320cf47e1cb544517ad"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="7512026a377271a0cade12d70846557f0bc7781c"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="22230c9a340a0a2c3af73320cf47e1cb544517ad"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7512026a377271a0cade12d70846557f0bc7781c"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="22230c9a340a0a2c3af73320cf47e1cb544517ad"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="7512026a377271a0cade12d70846557f0bc7781c"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
@ -146,7 +146,7 @@
|
|||||||
<project name="platform/hardware/ril" path="hardware/ril" revision="12b1977cc704b35f2e9db2bb423fa405348bc2f3"/>
|
<project name="platform/hardware/ril" path="hardware/ril" revision="12b1977cc704b35f2e9db2bb423fa405348bc2f3"/>
|
||||||
<project name="platform/system/bluetooth" path="system/bluetooth" revision="985bf15264d865fe7b9c5b45f61c451cbaafa43d"/>
|
<project name="platform/system/bluetooth" path="system/bluetooth" revision="985bf15264d865fe7b9c5b45f61c451cbaafa43d"/>
|
||||||
<project name="platform/system/core" path="system/core" revision="42839aedcf70bf6bc92a3b7ea4a5cc9bf9aef3f9"/>
|
<project name="platform/system/core" path="system/core" revision="42839aedcf70bf6bc92a3b7ea4a5cc9bf9aef3f9"/>
|
||||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d19dad5844e8803d5e88d1577a2742b4f5cbc467"/>
|
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="84395037a7a04546e8ef7cb81572eb516b85562b"/>
|
||||||
<project name="platform/system/qcom" path="system/qcom" revision="63e3f6f176caad587d42bba4c16b66d953fb23c2"/>
|
<project name="platform/system/qcom" path="system/qcom" revision="63e3f6f176caad587d42bba4c16b66d953fb23c2"/>
|
||||||
<project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="d8952a42771045fca73ec600e2b42a4c7129d723"/>
|
<project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="d8952a42771045fca73ec600e2b42a4c7129d723"/>
|
||||||
<project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4c187c1f3a0dffd8e51a961735474ea703535b99"/>
|
<project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4c187c1f3a0dffd8e51a961735474ea703535b99"/>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
<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="22230c9a340a0a2c3af73320cf47e1cb544517ad"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="7512026a377271a0cade12d70846557f0bc7781c"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1ddea3133e0807350326cee5dcf0d06fad00c08"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1ddea3133e0807350326cee5dcf0d06fad00c08"/>
|
||||||
@ -145,7 +145,7 @@
|
|||||||
<project name="platform/hardware/ril" path="hardware/ril" revision="c4e2ac95907a5519a0e09f01a0d8e27fec101af0"/>
|
<project name="platform/hardware/ril" path="hardware/ril" revision="c4e2ac95907a5519a0e09f01a0d8e27fec101af0"/>
|
||||||
<project name="platform/system/bluetooth" path="system/bluetooth" revision="e1eb226fa3ad3874ea7b63c56a9dc7012d7ff3c2"/>
|
<project name="platform/system/bluetooth" path="system/bluetooth" revision="e1eb226fa3ad3874ea7b63c56a9dc7012d7ff3c2"/>
|
||||||
<project name="platform/system/core" path="system/core" revision="adc485d8755af6a61641d197de7cfef667722580"/>
|
<project name="platform/system/core" path="system/core" revision="adc485d8755af6a61641d197de7cfef667722580"/>
|
||||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d19dad5844e8803d5e88d1577a2742b4f5cbc467"/>
|
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="84395037a7a04546e8ef7cb81572eb516b85562b"/>
|
||||||
<project name="platform/system/qcom" path="system/qcom" revision="1cdab258b15258b7f9657da70e6f06ebd5a2fc25"/>
|
<project name="platform/system/qcom" path="system/qcom" revision="1cdab258b15258b7f9657da70e6f06ebd5a2fc25"/>
|
||||||
<project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4ae5df252123591d5b941191790e7abed1bce5a4"/>
|
<project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4ae5df252123591d5b941191790e7abed1bce5a4"/>
|
||||||
<project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="ce18b47b4a4f93a581d672bbd5cb6d12fe796ca9"/>
|
<project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="ce18b47b4a4f93a581d672bbd5cb6d12fe796ca9"/>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"git": {
|
"git": {
|
||||||
"git_revision": "22230c9a340a0a2c3af73320cf47e1cb544517ad",
|
"git_revision": "7512026a377271a0cade12d70846557f0bc7781c",
|
||||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||||
"branch": ""
|
"branch": ""
|
||||||
},
|
},
|
||||||
"revision": "298fece36f2564e042e347a48fcc104aca78e3b5",
|
"revision": "53713e514b92cccfd55404cebd2b627cb9804bc2",
|
||||||
"repo_path": "integration/gaia-central"
|
"repo_path": "integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="22230c9a340a0a2c3af73320cf47e1cb544517ad"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="7512026a377271a0cade12d70846557f0bc7781c"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1ddea3133e0807350326cee5dcf0d06fad00c08"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="a1ddea3133e0807350326cee5dcf0d06fad00c08"/>
|
||||||
@ -130,7 +130,7 @@
|
|||||||
<project name="device-mako" path="device/lge/mako" remote="b2g" revision="78d17f0c117f0c66dd55ee8d5c5dde8ccc93ecba"/>
|
<project name="device-mako" path="device/lge/mako" remote="b2g" revision="78d17f0c117f0c66dd55ee8d5c5dde8ccc93ecba"/>
|
||||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
|
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
|
||||||
<project name="device/lge/mako-kernel" path="device/lge/mako-kernel" revision="d1729e53d71d711c8fde25eab8728ff2b9b4df0e"/>
|
<project name="device/lge/mako-kernel" path="device/lge/mako-kernel" revision="d1729e53d71d711c8fde25eab8728ff2b9b4df0e"/>
|
||||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d19dad5844e8803d5e88d1577a2742b4f5cbc467"/>
|
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="84395037a7a04546e8ef7cb81572eb516b85562b"/>
|
||||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
|
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
|
||||||
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
|
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
|
||||||
<project name="platform/hardware/broadcom/wlan" path="hardware/broadcom/wlan" revision="0e1929fa3aa38bf9d40e9e953d619fab8164c82e"/>
|
<project name="platform/hardware/broadcom/wlan" path="hardware/broadcom/wlan" revision="0e1929fa3aa38bf9d40e9e953d619fab8164c82e"/>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
|
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="22230c9a340a0a2c3af73320cf47e1cb544517ad"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="7512026a377271a0cade12d70846557f0bc7781c"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3905180d9e2dbe03d7ce3b3a6debe4d4adc938d1"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
@ -141,7 +141,7 @@
|
|||||||
<default remote="caf" revision="refs/tags/android-5.0.0_r6" sync-j="4"/>
|
<default remote="caf" revision="refs/tags/android-5.0.0_r6" sync-j="4"/>
|
||||||
<!-- Nexus 5 specific things -->
|
<!-- Nexus 5 specific things -->
|
||||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="ba62cc8b78c30d36181b8060a2016cc8da166236"/>
|
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="ba62cc8b78c30d36181b8060a2016cc8da166236"/>
|
||||||
<project name="device-hammerhead" path="device/lge/hammerhead" remote="b2g" revision="b765862a60e0063fc2451f5e3e137247dd9838c3"/>
|
<project name="device-hammerhead" path="device/lge/hammerhead" remote="b2g" revision="dc525eeb67301a44f514a7ac40a59ec592b34e31"/>
|
||||||
<project name="device/qcom/common" path="device/qcom/common" remote="caf" revision="3697e5acf25629b82658334e3f8ee3b6df5becab"/>
|
<project name="device/qcom/common" path="device/qcom/common" remote="caf" revision="3697e5acf25629b82658334e3f8ee3b6df5becab"/>
|
||||||
<project name="device_lge_hammerhead-kernel" path="device/lge/hammerhead-kernel" remote="b2g" revision="1268f640184df5ef759ada669f101a613451673a"/>
|
<project name="device_lge_hammerhead-kernel" path="device/lge/hammerhead-kernel" remote="b2g" revision="1268f640184df5ef759ada669f101a613451673a"/>
|
||||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="0cb8574d338bf9f15b45ace7c08ad6deae9673ee"/>
|
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="0cb8574d338bf9f15b45ace7c08ad6deae9673ee"/>
|
||||||
@ -157,5 +157,5 @@
|
|||||||
<project name="platform/hardware/qcom/sensors" path="hardware/qcom/sensors" revision="3724fd91ef5183684d97e2bf1d7ff948faabe090"/>
|
<project name="platform/hardware/qcom/sensors" path="hardware/qcom/sensors" revision="3724fd91ef5183684d97e2bf1d7ff948faabe090"/>
|
||||||
<project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="2e54754cc0529d26ccac37ed291600048adbf6c0"/>
|
<project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="2e54754cc0529d26ccac37ed291600048adbf6c0"/>
|
||||||
<project name="platform/hardware/ril" path="hardware/ril" revision="71dfa8228ad0d6cdf6bac0426ac59404ab74b7f3"/>
|
<project name="platform/hardware/ril" path="hardware/ril" revision="71dfa8228ad0d6cdf6bac0426ac59404ab74b7f3"/>
|
||||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d19dad5844e8803d5e88d1577a2742b4f5cbc467"/>
|
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="84395037a7a04546e8ef7cb81572eb516b85562b"/>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -1577,6 +1577,9 @@ pref("devtools.browserconsole.filter.secwarn", true);
|
|||||||
// Text size in the Web Console. Use 0 for the system default size.
|
// Text size in the Web Console. Use 0 for the system default size.
|
||||||
pref("devtools.webconsole.fontSize", 0);
|
pref("devtools.webconsole.fontSize", 0);
|
||||||
|
|
||||||
|
// Max number of inputs to store in web console history.
|
||||||
|
pref("devtools.webconsole.inputHistoryCount", 50);
|
||||||
|
|
||||||
// Persistent logging: |true| if you want the Web Console to keep all of the
|
// Persistent logging: |true| if you want the Web Console to keep all of the
|
||||||
// logged messages after reloading the page, |false| if you want the output to
|
// logged messages after reloading the page, |false| if you want the output to
|
||||||
// be cleared each time page navigation happens.
|
// be cleared each time page navigation happens.
|
||||||
|
@ -11,13 +11,19 @@ XPCOMUtils.defineLazyModuleGetter(this, "CloudSync",
|
|||||||
let CloudSync = null;
|
let CloudSync = null;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "ReadingListScheduler",
|
||||||
|
"resource:///modules/readinglist/Scheduler.jsm");
|
||||||
|
|
||||||
// gSyncUI handles updating the tools menu and displaying notifications.
|
// gSyncUI handles updating the tools menu and displaying notifications.
|
||||||
let gSyncUI = {
|
let gSyncUI = {
|
||||||
_obs: ["weave:service:sync:start",
|
_obs: ["weave:service:sync:start",
|
||||||
|
"weave:service:sync:finish",
|
||||||
|
"weave:service:sync:error",
|
||||||
"weave:service:quota:remaining",
|
"weave:service:quota:remaining",
|
||||||
"weave:service:setup-complete",
|
"weave:service:setup-complete",
|
||||||
"weave:service:login:start",
|
"weave:service:login:start",
|
||||||
"weave:service:login:finish",
|
"weave:service:login:finish",
|
||||||
|
"weave:service:login:error",
|
||||||
"weave:service:logout:finish",
|
"weave:service:logout:finish",
|
||||||
"weave:service:start-over",
|
"weave:service:start-over",
|
||||||
"weave:service:start-over:finish",
|
"weave:service:start-over:finish",
|
||||||
@ -25,9 +31,15 @@ let gSyncUI = {
|
|||||||
"weave:ui:sync:error",
|
"weave:ui:sync:error",
|
||||||
"weave:ui:sync:finish",
|
"weave:ui:sync:finish",
|
||||||
"weave:ui:clear-error",
|
"weave:ui:clear-error",
|
||||||
|
|
||||||
|
"readinglist:sync:start",
|
||||||
|
"readinglist:sync:finish",
|
||||||
|
"readinglist:sync:error",
|
||||||
],
|
],
|
||||||
|
|
||||||
_unloaded: false,
|
_unloaded: false,
|
||||||
|
// The number of "active" syncs - while this is non-zero, our button will spin
|
||||||
|
_numActiveSyncTasks: 0,
|
||||||
|
|
||||||
init: function () {
|
init: function () {
|
||||||
Cu.import("resource://services-common/stringbundle.js");
|
Cu.import("resource://services-common/stringbundle.js");
|
||||||
@ -95,21 +107,25 @@ let gSyncUI = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_needsSetup: function SUI__needsSetup() {
|
_needsSetup() {
|
||||||
// We want to treat "account needs verification" as "needs setup". So
|
// We want to treat "account needs verification" as "needs setup". So
|
||||||
// "reach in" to Weave.Status._authManager to check whether we the signed-in
|
// "reach in" to Weave.Status._authManager to check whether we the signed-in
|
||||||
// user is verified.
|
// user is verified.
|
||||||
// Referencing Weave.Status spins a nested event loop to initialize the
|
// Referencing Weave.Status spins a nested event loop to initialize the
|
||||||
// authManager, so this should always return a value directly.
|
// authManager, so this should always return a value directly.
|
||||||
// This only applies to fxAccounts-based Sync.
|
// This only applies to fxAccounts-based Sync.
|
||||||
if (Weave.Status._authManager._signedInUser) {
|
if (Weave.Status._authManager._signedInUser !== undefined) {
|
||||||
// If we have a signed in user already, and that user is not verified,
|
// So we are using Firefox accounts - in this world, checking Sync isn't
|
||||||
// revert to the "needs setup" state.
|
// enough as reading list may be configured but not Sync.
|
||||||
if (!Weave.Status._authManager._signedInUser.verified) {
|
// We consider ourselves setup if we have a verified user.
|
||||||
return true;
|
// XXX - later we should consider checking preferences to ensure at least
|
||||||
}
|
// one engine is enabled?
|
||||||
|
return !Weave.Status._authManager._signedInUser ||
|
||||||
|
!Weave.Status._authManager._signedInUser.verified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// So we are using legacy sync, and reading-list isn't supported for such
|
||||||
|
// users, so check sync itself.
|
||||||
let firstSync = "";
|
let firstSync = "";
|
||||||
try {
|
try {
|
||||||
firstSync = Services.prefs.getCharPref("services.sync.firstSync");
|
firstSync = Services.prefs.getCharPref("services.sync.firstSync");
|
||||||
@ -120,7 +136,8 @@ let gSyncUI = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_loginFailed: function () {
|
_loginFailed: function () {
|
||||||
return Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED;
|
return Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED ||
|
||||||
|
ReadingListScheduler.state == ReadingListScheduler.STATE_ERROR_AUTHENTICATION;
|
||||||
},
|
},
|
||||||
|
|
||||||
updateUI: function SUI_updateUI() {
|
updateUI: function SUI_updateUI() {
|
||||||
@ -136,6 +153,7 @@ let gSyncUI = {
|
|||||||
document.getElementById("sync-syncnow-state").hidden = false;
|
document.getElementById("sync-syncnow-state").hidden = false;
|
||||||
} else if (loginFailed) {
|
} else if (loginFailed) {
|
||||||
document.getElementById("sync-reauth-state").hidden = false;
|
document.getElementById("sync-reauth-state").hidden = false;
|
||||||
|
this.showLoginError();
|
||||||
} else if (needsSetup) {
|
} else if (needsSetup) {
|
||||||
document.getElementById("sync-setup-state").hidden = false;
|
document.getElementById("sync-setup-state").hidden = false;
|
||||||
} else {
|
} else {
|
||||||
@ -146,14 +164,6 @@ let gSyncUI = {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
let syncButton = document.getElementById("sync-button");
|
let syncButton = document.getElementById("sync-button");
|
||||||
if (syncButton) {
|
|
||||||
syncButton.removeAttribute("status");
|
|
||||||
}
|
|
||||||
let panelHorizontalButton = document.getElementById("PanelUI-fxa-status");
|
|
||||||
if (panelHorizontalButton) {
|
|
||||||
panelHorizontalButton.removeAttribute("syncstatus");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (needsSetup && syncButton)
|
if (needsSetup && syncButton)
|
||||||
syncButton.removeAttribute("tooltiptext");
|
syncButton.removeAttribute("tooltiptext");
|
||||||
|
|
||||||
@ -162,17 +172,45 @@ let gSyncUI = {
|
|||||||
|
|
||||||
|
|
||||||
// Functions called by observers
|
// Functions called by observers
|
||||||
onActivityStart: function SUI_onActivityStart() {
|
onActivityStart() {
|
||||||
if (!gBrowser)
|
if (!gBrowser)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let button = document.getElementById("sync-button");
|
this.log.debug("onActivityStart with numActive", this._numActiveSyncTasks);
|
||||||
if (button) {
|
if (++this._numActiveSyncTasks == 1) {
|
||||||
button.setAttribute("status", "active");
|
let button = document.getElementById("sync-button");
|
||||||
|
if (button) {
|
||||||
|
button.setAttribute("status", "active");
|
||||||
|
}
|
||||||
|
button = document.getElementById("PanelUI-fxa-status");
|
||||||
|
if (button) {
|
||||||
|
button.setAttribute("syncstatus", "active");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
button = document.getElementById("PanelUI-fxa-status");
|
},
|
||||||
if (button) {
|
|
||||||
button.setAttribute("syncstatus", "active");
|
onActivityStop() {
|
||||||
|
if (!gBrowser)
|
||||||
|
return;
|
||||||
|
this.log.debug("onActivityStop with numActive", this._numActiveSyncTasks);
|
||||||
|
if (--this._numActiveSyncTasks) {
|
||||||
|
if (this._numActiveSyncTasks < 0) {
|
||||||
|
// This isn't particularly useful (it seems more likely we'll set a
|
||||||
|
// "start" without a "stop" meaning it forever remains > 0) but it
|
||||||
|
// might offer some value...
|
||||||
|
this.log.error("mismatched onActivityStart/Stop calls",
|
||||||
|
new Error("active=" + this._numActiveSyncTasks));
|
||||||
|
}
|
||||||
|
return; // active tasks are still ongoing...
|
||||||
|
}
|
||||||
|
|
||||||
|
let syncButton = document.getElementById("sync-button");
|
||||||
|
if (syncButton) {
|
||||||
|
syncButton.removeAttribute("status");
|
||||||
|
}
|
||||||
|
let panelHorizontalButton = document.getElementById("PanelUI-fxa-status");
|
||||||
|
if (panelHorizontalButton) {
|
||||||
|
panelHorizontalButton.removeAttribute("syncstatus");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -187,6 +225,7 @@ let gSyncUI = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onLoginError: function SUI_onLoginError() {
|
onLoginError: function SUI_onLoginError() {
|
||||||
|
// Note: This is used for *both* Sync and ReadingList login errors.
|
||||||
// if login fails, any other notifications are essentially moot
|
// if login fails, any other notifications are essentially moot
|
||||||
Weave.Notifications.removeAll();
|
Weave.Notifications.removeAll();
|
||||||
|
|
||||||
@ -200,11 +239,18 @@ let gSyncUI = {
|
|||||||
this.updateUI();
|
this.updateUI();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.showLoginError();
|
||||||
|
this.updateUI();
|
||||||
|
},
|
||||||
|
|
||||||
|
showLoginError() {
|
||||||
|
// Note: This is used for *both* Sync and ReadingList login errors.
|
||||||
let title = this._stringBundle.GetStringFromName("error.login.title");
|
let title = this._stringBundle.GetStringFromName("error.login.title");
|
||||||
|
|
||||||
let description;
|
let description;
|
||||||
if (Weave.Status.sync == Weave.PROLONGED_SYNC_FAILURE) {
|
if (Weave.Status.sync == Weave.PROLONGED_SYNC_FAILURE ||
|
||||||
|
this.isProlongedReadingListError()) {
|
||||||
|
this.log.debug("showLoginError has a prolonged login error");
|
||||||
// Convert to days
|
// Convert to days
|
||||||
let lastSync =
|
let lastSync =
|
||||||
Services.prefs.getIntPref("services.sync.errorhandler.networkFailureReportTimeout") / 86400;
|
Services.prefs.getIntPref("services.sync.errorhandler.networkFailureReportTimeout") / 86400;
|
||||||
@ -214,6 +260,7 @@ let gSyncUI = {
|
|||||||
let reason = Weave.Utils.getErrorString(Weave.Status.login);
|
let reason = Weave.Utils.getErrorString(Weave.Status.login);
|
||||||
description =
|
description =
|
||||||
this._stringBundle.formatStringFromName("error.sync.description", [reason], 1);
|
this._stringBundle.formatStringFromName("error.sync.description", [reason], 1);
|
||||||
|
this.log.debug("showLoginError has a non-prolonged error", reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
let buttons = [];
|
let buttons = [];
|
||||||
@ -226,7 +273,6 @@ let gSyncUI = {
|
|||||||
let notification = new Weave.Notification(title, description, null,
|
let notification = new Weave.Notification(title, description, null,
|
||||||
Weave.Notifications.PRIORITY_WARNING, buttons);
|
Weave.Notifications.PRIORITY_WARNING, buttons);
|
||||||
Weave.Notifications.replaceTitle(notification);
|
Weave.Notifications.replaceTitle(notification);
|
||||||
this.updateUI();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onLogout: function SUI_onLogout() {
|
onLogout: function SUI_onLogout() {
|
||||||
@ -271,6 +317,7 @@ let gSyncUI = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Services.obs.notifyObservers(null, "cloudsync:user-sync", null);
|
Services.obs.notifyObservers(null, "cloudsync:user-sync", null);
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:user-sync", null);
|
||||||
},
|
},
|
||||||
|
|
||||||
handleToolbarButton: function SUI_handleStatusbarButton() {
|
handleToolbarButton: function SUI_handleStatusbarButton() {
|
||||||
@ -367,7 +414,15 @@ let gSyncUI = {
|
|||||||
|
|
||||||
let lastSync;
|
let lastSync;
|
||||||
try {
|
try {
|
||||||
lastSync = Services.prefs.getCharPref("services.sync.lastSync");
|
lastSync = new Date(Services.prefs.getCharPref("services.sync.lastSync"));
|
||||||
|
}
|
||||||
|
catch (e) { };
|
||||||
|
// and reading-list time - we want whatever one is the most recent.
|
||||||
|
try {
|
||||||
|
let lastRLSync = new Date(Services.prefs.getCharPref("readinglist.scheduler.lastSync"));
|
||||||
|
if (!lastSync || lastRLSync > lastSync) {
|
||||||
|
lastSync = lastRLSync;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (e) { };
|
catch (e) { };
|
||||||
if (!lastSync || this._needsSetup()) {
|
if (!lastSync || this._needsSetup()) {
|
||||||
@ -376,9 +431,9 @@ let gSyncUI = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Show the day-of-week and time (HH:MM) of last sync
|
// Show the day-of-week and time (HH:MM) of last sync
|
||||||
let lastSyncDate = new Date(lastSync).toLocaleFormat("%a %H:%M");
|
let lastSyncDateString = lastSync.toLocaleFormat("%a %H:%M");
|
||||||
let lastSyncLabel =
|
let lastSyncLabel =
|
||||||
this._stringBundle.formatStringFromName("lastSync2.label", [lastSyncDate], 1);
|
this._stringBundle.formatStringFromName("lastSync2.label", [lastSyncDateString], 1);
|
||||||
|
|
||||||
syncButton.setAttribute("tooltiptext", lastSyncLabel);
|
syncButton.setAttribute("tooltiptext", lastSyncLabel);
|
||||||
},
|
},
|
||||||
@ -395,7 +450,69 @@ let gSyncUI = {
|
|||||||
this.clearError(title);
|
this.clearError(title);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Return true if the reading-list is in a "prolonged" error state. That
|
||||||
|
// engine doesn't impose what that means, so calculate it here. For
|
||||||
|
// consistency, we just use the sync prefs.
|
||||||
|
isProlongedReadingListError() {
|
||||||
|
let lastSync, threshold, prolonged;
|
||||||
|
try {
|
||||||
|
lastSync = new Date(Services.prefs.getCharPref("readinglist.scheduler.lastSync"));
|
||||||
|
threshold = new Date(Date.now() - Services.prefs.getIntPref("services.sync.errorhandler.networkFailureReportTimeout"));
|
||||||
|
prolonged = lastSync <= threshold;
|
||||||
|
} catch (ex) {
|
||||||
|
// no pref, assume not prolonged.
|
||||||
|
prolonged = false;
|
||||||
|
}
|
||||||
|
this.log.debug("isProlongedReadingListError has last successful sync at ${lastSync}, threshold is ${threshold}, prolonged=${prolonged}",
|
||||||
|
{lastSync, threshold, prolonged});
|
||||||
|
return prolonged;
|
||||||
|
},
|
||||||
|
|
||||||
|
onRLSyncError() {
|
||||||
|
// Like onSyncError, but from the reading-list engine.
|
||||||
|
// However, the current UX around Sync is that error notifications should
|
||||||
|
// generally *not* be seen as they typically aren't actionable - so only
|
||||||
|
// authentication errors (which require user action) and "prolonged" errors
|
||||||
|
// (which technically aren't actionable, but user really should know anyway)
|
||||||
|
// are shown.
|
||||||
|
this.log.debug("onRLSyncError with readingList state", ReadingListScheduler.state);
|
||||||
|
if (ReadingListScheduler.state == ReadingListScheduler.STATE_ERROR_AUTHENTICATION) {
|
||||||
|
this.onLoginError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If it's not prolonged there's nothing to do.
|
||||||
|
if (!this.isProlongedReadingListError()) {
|
||||||
|
this.log.debug("onRLSyncError has a non-authentication, non-prolonged error, so not showing any error UI");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// So it's a prolonged error.
|
||||||
|
// Unfortunate duplication from below...
|
||||||
|
this.log.debug("onRLSyncError has a prolonged error");
|
||||||
|
let title = this._stringBundle.GetStringFromName("error.sync.title");
|
||||||
|
// XXX - this is somewhat wrong - we are reporting the threshold we consider
|
||||||
|
// to be prolonged, not how long it actually has been. (ie, lastSync below
|
||||||
|
// is effectively constant) - bit it too is copied from below.
|
||||||
|
let lastSync =
|
||||||
|
Services.prefs.getIntPref("services.sync.errorhandler.networkFailureReportTimeout") / 86400;
|
||||||
|
let description =
|
||||||
|
this._stringBundle.formatStringFromName("error.sync.prolonged_failure", [lastSync], 1);
|
||||||
|
let priority = Weave.Notifications.PRIORITY_INFO;
|
||||||
|
let buttons = [
|
||||||
|
new Weave.NotificationButton(
|
||||||
|
this._stringBundle.GetStringFromName("error.sync.tryAgainButton.label"),
|
||||||
|
this._stringBundle.GetStringFromName("error.sync.tryAgainButton.accesskey"),
|
||||||
|
function() { gSyncUI.doSync(); return true; }
|
||||||
|
),
|
||||||
|
];
|
||||||
|
let notification =
|
||||||
|
new Weave.Notification(title, description, null, priority, buttons);
|
||||||
|
Weave.Notifications.replaceTitle(notification);
|
||||||
|
|
||||||
|
this.updateUI();
|
||||||
|
},
|
||||||
|
|
||||||
onSyncError: function SUI_onSyncError() {
|
onSyncError: function SUI_onSyncError() {
|
||||||
|
this.log.debug("onSyncError");
|
||||||
let title = this._stringBundle.GetStringFromName("error.sync.title");
|
let title = this._stringBundle.GetStringFromName("error.sync.title");
|
||||||
|
|
||||||
if (Weave.Status.login != Weave.LOGIN_SUCCEEDED) {
|
if (Weave.Status.login != Weave.LOGIN_SUCCEEDED) {
|
||||||
@ -418,7 +535,9 @@ let gSyncUI = {
|
|||||||
let priority = Weave.Notifications.PRIORITY_WARNING;
|
let priority = Weave.Notifications.PRIORITY_WARNING;
|
||||||
let buttons = [];
|
let buttons = [];
|
||||||
|
|
||||||
// Check if the client is outdated in some way
|
// Check if the client is outdated in some way (but note: we've never in the
|
||||||
|
// past, and probably never will, bump the relevent version numbers, so
|
||||||
|
// this is effectively dead code!)
|
||||||
let outdated = Weave.Status.sync == Weave.VERSION_OUT_OF_DATE;
|
let outdated = Weave.Status.sync == Weave.VERSION_OUT_OF_DATE;
|
||||||
for (let [engine, reason] in Iterator(Weave.Status.engines))
|
for (let [engine, reason] in Iterator(Weave.Status.engines))
|
||||||
outdated = outdated || reason == Weave.VERSION_OUT_OF_DATE;
|
outdated = outdated || reason == Weave.VERSION_OUT_OF_DATE;
|
||||||
@ -468,6 +587,7 @@ let gSyncUI = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
observe: function SUI_observe(subject, topic, data) {
|
observe: function SUI_observe(subject, topic, data) {
|
||||||
|
this.log.debug("observed", topic);
|
||||||
if (this._unloaded) {
|
if (this._unloaded) {
|
||||||
Cu.reportError("SyncUI observer called after unload: " + topic);
|
Cu.reportError("SyncUI observer called after unload: " + topic);
|
||||||
return;
|
return;
|
||||||
@ -480,10 +600,26 @@ let gSyncUI = {
|
|||||||
subject = subject.wrappedJSObject.object;
|
subject = subject.wrappedJSObject.object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// First handle "activity" only.
|
||||||
switch (topic) {
|
switch (topic) {
|
||||||
case "weave:service:sync:start":
|
case "weave:service:sync:start":
|
||||||
|
case "weave:service:login:start":
|
||||||
|
case "readinglist:sync:start":
|
||||||
this.onActivityStart();
|
this.onActivityStart();
|
||||||
break;
|
break;
|
||||||
|
case "weave:service:sync:finish":
|
||||||
|
case "weave:service:sync:error":
|
||||||
|
case "weave:service:login:finish":
|
||||||
|
case "weave:service:login:error":
|
||||||
|
case "readinglist:sync:finish":
|
||||||
|
case "readinglist:sync:error":
|
||||||
|
this.onActivityStop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Now non-activity state (eg, enabled, errors, etc)
|
||||||
|
// Note that sync uses the ":ui:" notifications for errors because sync.
|
||||||
|
// ReadingList has no such concept (yet?; hopefully the :error is enough!)
|
||||||
|
switch (topic) {
|
||||||
case "weave:ui:sync:finish":
|
case "weave:ui:sync:finish":
|
||||||
this.onSyncFinish();
|
this.onSyncFinish();
|
||||||
break;
|
break;
|
||||||
@ -496,9 +632,6 @@ let gSyncUI = {
|
|||||||
case "weave:service:setup-complete":
|
case "weave:service:setup-complete":
|
||||||
this.onSetupComplete();
|
this.onSetupComplete();
|
||||||
break;
|
break;
|
||||||
case "weave:service:login:start":
|
|
||||||
this.onActivityStart();
|
|
||||||
break;
|
|
||||||
case "weave:service:login:finish":
|
case "weave:service:login:finish":
|
||||||
this.onLoginFinish();
|
this.onLoginFinish();
|
||||||
break;
|
break;
|
||||||
@ -523,6 +656,13 @@ let gSyncUI = {
|
|||||||
case "weave:ui:clear-error":
|
case "weave:ui:clear-error":
|
||||||
this.clearError();
|
this.clearError();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "readinglist:sync:error":
|
||||||
|
this.onRLSyncError();
|
||||||
|
break;
|
||||||
|
case "readinglist:sync:finish":
|
||||||
|
this.clearError();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -540,3 +680,6 @@ XPCOMUtils.defineLazyGetter(gSyncUI, "_stringBundle", function() {
|
|||||||
createBundle("chrome://weave/locale/services/sync.properties");
|
createBundle("chrome://weave/locale/services/sync.properties");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyGetter(gSyncUI, "log", function() {
|
||||||
|
return Log.repository.getLogger("browserwindow.syncui");
|
||||||
|
});
|
||||||
|
@ -37,6 +37,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
|
|||||||
"resource:///modules/ContentSearch.jsm");
|
"resource:///modules/ContentSearch.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "AboutHome",
|
XPCOMUtils.defineLazyModuleGetter(this, "AboutHome",
|
||||||
"resource:///modules/AboutHome.jsm");
|
"resource:///modules/AboutHome.jsm");
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, "Log",
|
||||||
|
"resource://gre/modules/Log.jsm");
|
||||||
XPCOMUtils.defineLazyServiceGetter(this, "Favicons",
|
XPCOMUtils.defineLazyServiceGetter(this, "Favicons",
|
||||||
"@mozilla.org/browser/favicon-service;1",
|
"@mozilla.org/browser/favicon-service;1",
|
||||||
"mozIAsyncFavicons");
|
"mozIAsyncFavicons");
|
||||||
|
@ -403,6 +403,8 @@ support-files =
|
|||||||
[browser_ssl_error_reports.js]
|
[browser_ssl_error_reports.js]
|
||||||
[browser_star_hsts.js]
|
[browser_star_hsts.js]
|
||||||
[browser_subframe_favicons_not_used.js]
|
[browser_subframe_favicons_not_used.js]
|
||||||
|
[browser_syncui.js]
|
||||||
|
skip-if = e10s # Bug 1137087 - browser_tabopen_reflows.js fails if this was previously run with e10s
|
||||||
[browser_tabDrop.js]
|
[browser_tabDrop.js]
|
||||||
skip-if = buildapp == 'mulet' || e10s
|
skip-if = buildapp == 'mulet' || e10s
|
||||||
[browser_tabMatchesInAwesomebar.js]
|
[browser_tabMatchesInAwesomebar.js]
|
||||||
|
244
browser/base/content/test/general/browser_syncui.js
Normal file
244
browser/base/content/test/general/browser_syncui.js
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
let {Log} = Cu.import("resource://gre/modules/Log.jsm", {});
|
||||||
|
let {Weave} = Cu.import("resource://services-sync/main.js", {});
|
||||||
|
let {Notifications} = Cu.import("resource://services-sync/notifications.js", {});
|
||||||
|
// The BackStagePass allows us to get this test-only non-exported function.
|
||||||
|
let {getInternalScheduler} = Cu.import("resource:///modules/readinglist/Scheduler.jsm", {});
|
||||||
|
|
||||||
|
let stringBundle = Cc["@mozilla.org/intl/stringbundle;1"]
|
||||||
|
.getService(Ci.nsIStringBundleService)
|
||||||
|
.createBundle("chrome://weave/locale/services/sync.properties");
|
||||||
|
|
||||||
|
// ensure test output sees log messages.
|
||||||
|
Log.repository.getLogger("browserwindow.syncui").addAppender(new Log.DumpAppender());
|
||||||
|
|
||||||
|
function promiseObserver(topic) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
let obs = (subject, topic, data) => {
|
||||||
|
Services.obs.removeObserver(obs, topic);
|
||||||
|
resolve(subject);
|
||||||
|
}
|
||||||
|
Services.obs.addObserver(obs, topic, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(function* prepare() {
|
||||||
|
let xps = Components.classes["@mozilla.org/weave/service;1"]
|
||||||
|
.getService(Components.interfaces.nsISupports)
|
||||||
|
.wrappedJSObject;
|
||||||
|
yield xps.whenLoaded();
|
||||||
|
// mock out the "_needsSetup()" function so we don't short-circuit.
|
||||||
|
let oldNeedsSetup = window.gSyncUI._needsSetup;
|
||||||
|
window.gSyncUI._needsSetup = () => false;
|
||||||
|
registerCleanupFunction(() => {
|
||||||
|
window.gSyncUI._needsSetup = oldNeedsSetup;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* testProlongedSyncError() {
|
||||||
|
let promiseNotificationAdded = promiseObserver("weave:notification:added");
|
||||||
|
Assert.equal(Notifications.notifications.length, 0, "start with no notifications");
|
||||||
|
|
||||||
|
// Pretend we are in the "prolonged error" state.
|
||||||
|
Weave.Status.sync = Weave.PROLONGED_SYNC_FAILURE;
|
||||||
|
Weave.Status.login = Weave.LOGIN_SUCCEEDED;
|
||||||
|
Services.obs.notifyObservers(null, "weave:ui:sync:error", null);
|
||||||
|
|
||||||
|
let subject = yield promiseNotificationAdded;
|
||||||
|
let notification = subject.wrappedJSObject.object; // sync's observer abstraction is abstract!
|
||||||
|
Assert.equal(notification.title, stringBundle.GetStringFromName("error.sync.title"));
|
||||||
|
Assert.equal(Notifications.notifications.length, 1, "exactly 1 notification");
|
||||||
|
|
||||||
|
// Now pretend we just had a successful sync - the error notification should go away.
|
||||||
|
let promiseNotificationRemoved = promiseObserver("weave:notification:removed");
|
||||||
|
Weave.Status.sync = Weave.STATUS_OK;
|
||||||
|
Services.obs.notifyObservers(null, "weave:ui:sync:finish", null);
|
||||||
|
yield promiseNotificationRemoved;
|
||||||
|
Assert.equal(Notifications.notifications.length, 0, "no notifications left");
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* testProlongedRLError() {
|
||||||
|
let promiseNotificationAdded = promiseObserver("weave:notification:added");
|
||||||
|
Assert.equal(Notifications.notifications.length, 0, "start with no notifications");
|
||||||
|
|
||||||
|
// Pretend the reading-list is in the "prolonged error" state.
|
||||||
|
let longAgo = new Date(Date.now() - 100 * 24 * 60 * 60 * 1000); // 100 days ago.
|
||||||
|
Services.prefs.setCharPref("readinglist.scheduler.lastSync", longAgo.toString());
|
||||||
|
getInternalScheduler().state = ReadingListScheduler.STATE_ERROR_OTHER;
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:start", null);
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:error", null);
|
||||||
|
|
||||||
|
let subject = yield promiseNotificationAdded;
|
||||||
|
let notification = subject.wrappedJSObject.object; // sync's observer abstraction is abstract!
|
||||||
|
Assert.equal(notification.title, stringBundle.GetStringFromName("error.sync.title"));
|
||||||
|
Assert.equal(Notifications.notifications.length, 1, "exactly 1 notification");
|
||||||
|
|
||||||
|
// Now pretend we just had a successful sync - the error notification should go away.
|
||||||
|
let promiseNotificationRemoved = promiseObserver("weave:notification:removed");
|
||||||
|
Services.prefs.setCharPref("readinglist.scheduler.lastSync", Date.now().toString());
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:start", null);
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:finish", null);
|
||||||
|
yield promiseNotificationRemoved;
|
||||||
|
Assert.equal(Notifications.notifications.length, 0, "no notifications left");
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* testSyncLoginError() {
|
||||||
|
let promiseNotificationAdded = promiseObserver("weave:notification:added");
|
||||||
|
Assert.equal(Notifications.notifications.length, 0, "start with no notifications");
|
||||||
|
|
||||||
|
// Pretend we are in the "prolonged error" state.
|
||||||
|
Weave.Status.sync = Weave.LOGIN_FAILED;
|
||||||
|
Weave.Status.login = Weave.LOGIN_FAILED_LOGIN_REJECTED;
|
||||||
|
Services.obs.notifyObservers(null, "weave:ui:sync:error", null);
|
||||||
|
|
||||||
|
let subject = yield promiseNotificationAdded;
|
||||||
|
let notification = subject.wrappedJSObject.object; // sync's observer abstraction is abstract!
|
||||||
|
Assert.equal(notification.title, stringBundle.GetStringFromName("error.login.title"));
|
||||||
|
Assert.equal(Notifications.notifications.length, 1, "exactly 1 notification");
|
||||||
|
|
||||||
|
// Now pretend we just had a successful login - the error notification should go away.
|
||||||
|
Weave.Status.sync = Weave.STATUS_OK;
|
||||||
|
Weave.Status.login = Weave.LOGIN_SUCCEEDED;
|
||||||
|
let promiseNotificationRemoved = promiseObserver("weave:notification:removed");
|
||||||
|
Services.obs.notifyObservers(null, "weave:service:login:start", null);
|
||||||
|
Services.obs.notifyObservers(null, "weave:service:login:finish", null);
|
||||||
|
yield promiseNotificationRemoved;
|
||||||
|
Assert.equal(Notifications.notifications.length, 0, "no notifications left");
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* testRLLoginError() {
|
||||||
|
let promiseNotificationAdded = promiseObserver("weave:notification:added");
|
||||||
|
Assert.equal(Notifications.notifications.length, 0, "start with no notifications");
|
||||||
|
|
||||||
|
// Pretend RL is in an auth error state
|
||||||
|
getInternalScheduler().state = ReadingListScheduler.STATE_ERROR_AUTHENTICATION;
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:start", null);
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:error", null);
|
||||||
|
|
||||||
|
let subject = yield promiseNotificationAdded;
|
||||||
|
let notification = subject.wrappedJSObject.object; // sync's observer abstraction is abstract!
|
||||||
|
Assert.equal(notification.title, stringBundle.GetStringFromName("error.login.title"));
|
||||||
|
Assert.equal(Notifications.notifications.length, 1, "exactly 1 notification");
|
||||||
|
|
||||||
|
// Now pretend we just had a successful sync - the error notification should go away.
|
||||||
|
getInternalScheduler().state = ReadingListScheduler.STATE_OK;
|
||||||
|
let promiseNotificationRemoved = promiseObserver("weave:notification:removed");
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:start", null);
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:finish", null);
|
||||||
|
yield promiseNotificationRemoved;
|
||||||
|
Assert.equal(Notifications.notifications.length, 0, "no notifications left");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Here we put readinglist into an "authentication error" state (should see
|
||||||
|
// the error bar reflecting this), then report a prolonged error from Sync (an
|
||||||
|
// infobar to reflect the sync error should replace it), then resolve the sync
|
||||||
|
// error - the authentication error from readinglist should remain.
|
||||||
|
add_task(function* testRLLoginErrorRemains() {
|
||||||
|
let promiseNotificationAdded = promiseObserver("weave:notification:added");
|
||||||
|
Assert.equal(Notifications.notifications.length, 0, "start with no notifications");
|
||||||
|
|
||||||
|
// Pretend RL is in an auth error state
|
||||||
|
getInternalScheduler().state = ReadingListScheduler.STATE_ERROR_AUTHENTICATION;
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:start", null);
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:error", null);
|
||||||
|
|
||||||
|
let subject = yield promiseNotificationAdded;
|
||||||
|
let notification = subject.wrappedJSObject.object; // sync's observer abstraction is abstract!
|
||||||
|
Assert.equal(notification.title, stringBundle.GetStringFromName("error.login.title"));
|
||||||
|
Assert.equal(Notifications.notifications.length, 1, "exactly 1 notification");
|
||||||
|
|
||||||
|
// Now Sync into a prolonged auth error state.
|
||||||
|
promiseNotificationAdded = promiseObserver("weave:notification:added");
|
||||||
|
Weave.Status.sync = Weave.PROLONGED_SYNC_FAILURE;
|
||||||
|
Weave.Status.login = Weave.LOGIN_FAILED_LOGIN_REJECTED;
|
||||||
|
Services.obs.notifyObservers(null, "weave:ui:sync:error", null);
|
||||||
|
subject = yield promiseNotificationAdded;
|
||||||
|
// still exactly 1 notification with the "login" title.
|
||||||
|
notification = subject.wrappedJSObject.object;
|
||||||
|
Assert.equal(notification.title, stringBundle.GetStringFromName("error.login.title"));
|
||||||
|
Assert.equal(Notifications.notifications.length, 1, "exactly 1 notification");
|
||||||
|
|
||||||
|
// Resolve the sync problem.
|
||||||
|
promiseNotificationAdded = promiseObserver("weave:notification:added");
|
||||||
|
Weave.Status.sync = Weave.STATUS_OK;
|
||||||
|
Weave.Status.login = Weave.LOGIN_SUCCEEDED;
|
||||||
|
Services.obs.notifyObservers(null, "weave:ui:sync:finish", null);
|
||||||
|
|
||||||
|
// Expect one notification - the RL login problem.
|
||||||
|
subject = yield promiseNotificationAdded;
|
||||||
|
// still exactly 1 notification with the "login" title.
|
||||||
|
notification = subject.wrappedJSObject.object;
|
||||||
|
Assert.equal(notification.title, stringBundle.GetStringFromName("error.login.title"));
|
||||||
|
Assert.equal(Notifications.notifications.length, 1, "exactly 1 notification");
|
||||||
|
|
||||||
|
// and cleanup - resolve the readinglist error.
|
||||||
|
getInternalScheduler().state = ReadingListScheduler.STATE_OK;
|
||||||
|
let promiseNotificationRemoved = promiseObserver("weave:notification:removed");
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:start", null);
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:finish", null);
|
||||||
|
yield promiseNotificationRemoved;
|
||||||
|
Assert.equal(Notifications.notifications.length, 0, "no notifications left");
|
||||||
|
});
|
||||||
|
|
||||||
|
function checkButtonsStatus(shouldBeActive) {
|
||||||
|
let button = document.getElementById("sync-button");
|
||||||
|
let panelbutton = document.getElementById("PanelUI-fxa-status");
|
||||||
|
if (shouldBeActive) {
|
||||||
|
Assert.equal(button.getAttribute("status"), "active");
|
||||||
|
Assert.equal(panelbutton.getAttribute("syncstatus"), "active");
|
||||||
|
} else {
|
||||||
|
Assert.ok(!button.hasAttribute("status"));
|
||||||
|
Assert.ok(!panelbutton.hasAttribute("syncstatus"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function testButtonActions(startNotification, endNotification) {
|
||||||
|
checkButtonsStatus(false);
|
||||||
|
// pretend a sync is starting.
|
||||||
|
Services.obs.notifyObservers(null, startNotification, null);
|
||||||
|
checkButtonsStatus(true);
|
||||||
|
// and has stopped
|
||||||
|
Services.obs.notifyObservers(null, endNotification, null);
|
||||||
|
checkButtonsStatus(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(function* testButtonActivities() {
|
||||||
|
// add the Sync button to the panel so we can get it!
|
||||||
|
CustomizableUI.addWidgetToArea("sync-button", CustomizableUI.AREA_PANEL);
|
||||||
|
// check the button's functionality
|
||||||
|
yield PanelUI.show();
|
||||||
|
try {
|
||||||
|
testButtonActions("weave:service:login:start", "weave:service:login:finish");
|
||||||
|
testButtonActions("weave:service:login:start", "weave:service:login:error");
|
||||||
|
|
||||||
|
testButtonActions("weave:service:sync:start", "weave:service:sync:finish");
|
||||||
|
testButtonActions("weave:service:sync:start", "weave:service:sync:error");
|
||||||
|
|
||||||
|
testButtonActions("readinglist:sync:start", "readinglist:sync:finish");
|
||||||
|
testButtonActions("readinglist:sync:start", "readinglist:sync:error");
|
||||||
|
|
||||||
|
// and ensure the counters correctly handle multiple in-flight syncs
|
||||||
|
Services.obs.notifyObservers(null, "weave:service:sync:start", null);
|
||||||
|
checkButtonsStatus(true);
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:start", null);
|
||||||
|
checkButtonsStatus(true);
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:finish", null);
|
||||||
|
// sync is still going...
|
||||||
|
checkButtonsStatus(true);
|
||||||
|
// another reading list starts
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:start", null);
|
||||||
|
checkButtonsStatus(true);
|
||||||
|
// The initial sync stops.
|
||||||
|
Services.obs.notifyObservers(null, "weave:service:sync:finish", null);
|
||||||
|
// RL is still going...
|
||||||
|
checkButtonsStatus(true);
|
||||||
|
// RL finishes with an error, so no longer active.
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:error", null);
|
||||||
|
checkButtonsStatus(false);
|
||||||
|
} finally {
|
||||||
|
PanelUI.hide();
|
||||||
|
CustomizableUI.removeWidgetFromArea("sync-button");
|
||||||
|
}
|
||||||
|
});
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
|
XPCOMUtils.defineLazyModuleGetter(this, "DownloadUtils",
|
||||||
"resource://gre/modules/DownloadUtils.jsm");
|
"resource://gre/modules/DownloadUtils.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
|
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
|
||||||
|
@ -66,6 +66,8 @@
|
|||||||
|
|
||||||
let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
let { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
|
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon",
|
||||||
"resource:///modules/DownloadsCommon.jsm");
|
"resource:///modules/DownloadsCommon.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsViewUI",
|
XPCOMUtils.defineLazyModuleGetter(this, "DownloadsViewUI",
|
||||||
|
338
browser/components/readinglist/Scheduler.jsm
Normal file
338
browser/components/readinglist/Scheduler.jsm
Normal file
@ -0,0 +1,338 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
"use strict;"
|
||||||
|
|
||||||
|
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, 'LogManager',
|
||||||
|
'resource://services-common/logmanager.js');
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, 'Log',
|
||||||
|
'resource://gre/modules/Log.jsm');
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, 'Preferences',
|
||||||
|
'resource://gre/modules/Preferences.jsm');
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, 'setTimeout',
|
||||||
|
'resource://gre/modules/Timer.jsm');
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, 'clearTimeout',
|
||||||
|
'resource://gre/modules/Timer.jsm');
|
||||||
|
|
||||||
|
Cu.import('resource://gre/modules/Task.jsm');
|
||||||
|
|
||||||
|
this.EXPORTED_SYMBOLS = ["ReadingListScheduler"];
|
||||||
|
|
||||||
|
// A list of "external" observer topics that may cause us to change when we
|
||||||
|
// sync.
|
||||||
|
const OBSERVERS = [
|
||||||
|
// We don't sync when offline and restart when online.
|
||||||
|
"network:offline-status-changed",
|
||||||
|
// FxA notifications also cause us to check if we should sync.
|
||||||
|
"fxaccounts:onverified",
|
||||||
|
// When something notices a local change to an item.
|
||||||
|
"readinglist:item-changed",
|
||||||
|
// some notifications the engine might send if we have been requested to backoff.
|
||||||
|
"readinglist:backoff-requested",
|
||||||
|
// request to sync now
|
||||||
|
"readinglist:user-sync",
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
///////// A temp object until we get our "engine"
|
||||||
|
let engine = {
|
||||||
|
ERROR_AUTHENTICATION: "authentication error",
|
||||||
|
sync: Task.async(function* () {
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
let prefs = new Preferences("readinglist.scheduler.");
|
||||||
|
|
||||||
|
// A helper to manage our interval values.
|
||||||
|
let intervals = {
|
||||||
|
// Getters for our intervals.
|
||||||
|
_fixupIntervalPref(prefName, def) {
|
||||||
|
// All pref values are seconds, but we return ms.
|
||||||
|
return prefs.get(prefName, def) * 1000;
|
||||||
|
},
|
||||||
|
|
||||||
|
// How long after startup do we do an initial sync?
|
||||||
|
get initial() this._fixupIntervalPref("initial", 20), // 20 seconds.
|
||||||
|
// Every interval after the first.
|
||||||
|
get schedule() this._fixupIntervalPref("schedule", 2 * 60 * 60), // 2 hours
|
||||||
|
// After we've been told an item has changed
|
||||||
|
get dirty() this._fixupIntervalPref("dirty", 2 * 60), // 2 mins
|
||||||
|
// After an error
|
||||||
|
get retry() this._fixupIntervalPref("retry", 2 * 60), // 2 mins
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is the implementation, but it's not exposed directly.
|
||||||
|
function InternalScheduler() {
|
||||||
|
// oh, I don't know what logs yet - let's guess!
|
||||||
|
let logs = ["readinglist", "FirefoxAccounts", "browserwindow.syncui"];
|
||||||
|
this._logManager = new LogManager("readinglist.", logs, "readinglist");
|
||||||
|
this.log = Log.repository.getLogger("readinglist.scheduler");
|
||||||
|
this.log.info("readinglist scheduler created.")
|
||||||
|
this.state = this.STATE_OK;
|
||||||
|
|
||||||
|
// don't this.init() here, but instead at the module level - tests want to
|
||||||
|
// add hooks before it is called.
|
||||||
|
}
|
||||||
|
|
||||||
|
InternalScheduler.prototype = {
|
||||||
|
// When the next scheduled sync should happen. If we can sync, there will
|
||||||
|
// be a timer set to fire then. If we can't sync there will not be a timer,
|
||||||
|
// but it will be set to fire then as soon as we can.
|
||||||
|
_nextScheduledSync: null,
|
||||||
|
// The time when the most-recent "backoff request" expires - we will never
|
||||||
|
// schedule a new timer before this.
|
||||||
|
_backoffUntil: 0,
|
||||||
|
// Our current timer.
|
||||||
|
_timer: null,
|
||||||
|
// Our timer fires a promise - _timerRunning is true until it resolves or
|
||||||
|
// rejects.
|
||||||
|
_timerRunning: false,
|
||||||
|
// Our sync engine - XXX - maybe just a callback?
|
||||||
|
_engine: engine,
|
||||||
|
|
||||||
|
// Our state variable and constants.
|
||||||
|
state: null,
|
||||||
|
STATE_OK: "ok",
|
||||||
|
STATE_ERROR_AUTHENTICATION: "authentication error",
|
||||||
|
STATE_ERROR_OTHER: "other error",
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.log.info("scheduler initialzing");
|
||||||
|
this._observe = this.observe.bind(this);
|
||||||
|
for (let notification of OBSERVERS) {
|
||||||
|
Services.obs.addObserver(this._observe, notification, false);
|
||||||
|
}
|
||||||
|
this._nextScheduledSync = Date.now() + intervals.initial;
|
||||||
|
this._setupTimer();
|
||||||
|
},
|
||||||
|
|
||||||
|
// Note: only called by tests.
|
||||||
|
finalize() {
|
||||||
|
this.log.info("scheduler finalizing");
|
||||||
|
this._clearTimer();
|
||||||
|
for (let notification of OBSERVERS) {
|
||||||
|
Services.obs.removeObserver(this._observe, notification);
|
||||||
|
}
|
||||||
|
this._observe = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
observe(subject, topic, data) {
|
||||||
|
this.log.debug("observed ${}", topic);
|
||||||
|
switch (topic) {
|
||||||
|
case "readinglist:backoff-requested": {
|
||||||
|
// The subject comes in as a string, a number of seconds.
|
||||||
|
let interval = parseInt(data, 10);
|
||||||
|
if (isNaN(interval)) {
|
||||||
|
this.log.warn("Backoff request had non-numeric value", data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.log.info("Received a request to backoff for ${} seconds", interval);
|
||||||
|
this._backoffUntil = Date.now() + interval * 1000;
|
||||||
|
this._maybeReschedule(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "readinglist:local:dirty":
|
||||||
|
this._maybeReschedule(intervals.dirty);
|
||||||
|
break;
|
||||||
|
case "readinglist:user-sync":
|
||||||
|
this._syncNow();
|
||||||
|
break;
|
||||||
|
case "fxaccounts:onverified":
|
||||||
|
// If we were in an authentication error state, reset that now.
|
||||||
|
if (this.state == this.STATE_ERROR_AUTHENTICATION) {
|
||||||
|
this.state = this.STATE_OK;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// The rest just indicate that now is probably a good time to check if
|
||||||
|
// we can sync as normal using whatever schedule was previously set.
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// When observers fire we ignore the current sync error state as the
|
||||||
|
// notification may indicate it's been resolved.
|
||||||
|
this._setupTimer(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Is the current error state such that we shouldn't schedule a new sync.
|
||||||
|
_isBlockedOnError() {
|
||||||
|
// this needs more thought...
|
||||||
|
return this.state == this.STATE_ERROR_AUTHENTICATION;
|
||||||
|
},
|
||||||
|
|
||||||
|
// canSync indicates if we can currently sync.
|
||||||
|
_canSync(ignoreBlockingErrors = false) {
|
||||||
|
if (Services.io.offline) {
|
||||||
|
this.log.info("canSync=false - we are offline");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!ignoreBlockingErrors && this._isBlockedOnError()) {
|
||||||
|
this.log.info("canSync=false - we are in a blocked error state", this.state);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.log.info("canSync=true");
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
// _setupTimer checks the current state and the environment to see when
|
||||||
|
// we should next sync and creates the timer with the appropriate delay.
|
||||||
|
_setupTimer(ignoreBlockingErrors = false) {
|
||||||
|
if (!this._canSync(ignoreBlockingErrors)) {
|
||||||
|
this._clearTimer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this._timer) {
|
||||||
|
let when = new Date(this._nextScheduledSync);
|
||||||
|
let delay = this._nextScheduledSync - Date.now();
|
||||||
|
this.log.info("checkStatus - already have a timer - will fire in ${delay}ms at ${when}",
|
||||||
|
{delay, when});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this._timerRunning) {
|
||||||
|
this.log.info("checkStatus - currently syncing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// no timer and we can sync, so start a new one.
|
||||||
|
let now = Date.now();
|
||||||
|
let delay = Math.max(0, this._nextScheduledSync - now);
|
||||||
|
let when = new Date(now + delay);
|
||||||
|
this.log.info("next scheduled sync is in ${delay}ms (at ${when})", {delay, when})
|
||||||
|
this._timer = this._setTimeout(delay);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Something (possibly naively) thinks the next sync should happen in
|
||||||
|
// delay-ms. If there's a backoff in progress, ignore the requested delay
|
||||||
|
// and use the back-off. If there's already a timer scheduled for earlier
|
||||||
|
// than delay, let the earlier timer remain. Otherwise, use the requested
|
||||||
|
// delay.
|
||||||
|
_maybeReschedule(delay) {
|
||||||
|
// If there's no delay specified and there's nothing currently scheduled,
|
||||||
|
// it means a backoff request while the sync is actually running - there's
|
||||||
|
// no need to do anything here - the next reschedule after the sync
|
||||||
|
// completes will take the backoff into account.
|
||||||
|
if (!delay && !this._nextScheduledSync) {
|
||||||
|
this.log.debug("_maybeReschedule ignoring a backoff request while running");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let now = Date.now();
|
||||||
|
if (!this._nextScheduledSync) {
|
||||||
|
this._nextScheduledSync = now + delay;
|
||||||
|
}
|
||||||
|
// If there is something currently scheduled before the requested delay,
|
||||||
|
// keep the existing value (eg, if we have a timer firing in 1 second, and
|
||||||
|
// get a "dirty" notification that says we should sync in 2 seconds, we
|
||||||
|
// keep the 1 second value)
|
||||||
|
this._nextScheduledSync = Math.min(this._nextScheduledSync, now + delay);
|
||||||
|
// But we still need to honor a backoff.
|
||||||
|
this._nextScheduledSync = Math.max(this._nextScheduledSync, this._backoffUntil);
|
||||||
|
// And always create a new timer next time _setupTimer is called.
|
||||||
|
this._clearTimer();
|
||||||
|
},
|
||||||
|
|
||||||
|
// callback for when the timer fires.
|
||||||
|
_doSync() {
|
||||||
|
this.log.debug("starting sync");
|
||||||
|
this._timer = null;
|
||||||
|
this._timerRunning = true;
|
||||||
|
// flag that there's no new schedule yet, so a request coming in while
|
||||||
|
// we are running does the right thing.
|
||||||
|
this._nextScheduledSync = 0;
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:start", null);
|
||||||
|
this._engine.sync().then(() => {
|
||||||
|
this.log.info("Sync completed successfully");
|
||||||
|
// Write a pref in the same format used to services/sync to indicate
|
||||||
|
// the last success.
|
||||||
|
prefs.set("lastSync", new Date().toString());
|
||||||
|
this.state = this.STATE_OK;
|
||||||
|
this._logManager.resetFileLog(this._logManager.REASON_SUCCESS);
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:finish", null);
|
||||||
|
return intervals.schedule;
|
||||||
|
}).catch(err => {
|
||||||
|
this.log.error("Sync failed", err);
|
||||||
|
// XXX - how to detect an auth error?
|
||||||
|
this.state = err == this._engine.ERROR_AUTHENTICATION ?
|
||||||
|
this.STATE_ERROR_AUTHENTICATION : this.STATE_ERROR_OTHER;
|
||||||
|
this._logManager.resetFileLog(this._logManager.REASON_ERROR);
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:sync:error", null);
|
||||||
|
return intervals.retry;
|
||||||
|
}).then(nextDelay => {
|
||||||
|
this._timerRunning = false;
|
||||||
|
// ensure a new timer is setup for the appropriate next time.
|
||||||
|
this._maybeReschedule(nextDelay);
|
||||||
|
this._setupTimer();
|
||||||
|
this._onAutoReschedule(); // just for tests...
|
||||||
|
}).catch(err => {
|
||||||
|
// We should never get here, but better safe than sorry...
|
||||||
|
this.log.error("Failed to reschedule after sync completed", err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
_clearTimer() {
|
||||||
|
if (this._timer) {
|
||||||
|
clearTimeout(this._timer);
|
||||||
|
this._timer = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// A function to "sync now", but not allowing it to start if one is
|
||||||
|
// already running, and rescheduling the timer.
|
||||||
|
// To call this, just send a "readinglist:user-sync" notification.
|
||||||
|
_syncNow() {
|
||||||
|
if (this._timerRunning) {
|
||||||
|
this.log.info("syncNow() but a sync is already in progress - ignoring");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._clearTimer();
|
||||||
|
this._doSync();
|
||||||
|
},
|
||||||
|
|
||||||
|
// A couple of hook-points for testing.
|
||||||
|
// xpcshell tests hook this so (a) it can check the expected delay is set
|
||||||
|
// and (b) to ignore the delay and set a timeout of 0 so the test is fast.
|
||||||
|
_setTimeout(delay) {
|
||||||
|
return setTimeout(() => this._doSync(), delay);
|
||||||
|
},
|
||||||
|
// xpcshell tests hook this to make sure that the correct state etc exist
|
||||||
|
// after a sync has been completed and a new timer created (or not).
|
||||||
|
_onAutoReschedule() {},
|
||||||
|
};
|
||||||
|
|
||||||
|
let internalScheduler = new InternalScheduler();
|
||||||
|
internalScheduler.init();
|
||||||
|
|
||||||
|
// The public interface into this module is tiny, so a simple object that
|
||||||
|
// delegates to the implementation.
|
||||||
|
let ReadingListScheduler = {
|
||||||
|
get STATE_OK() internalScheduler.STATE_OK,
|
||||||
|
get STATE_ERROR_AUTHENTICATION() internalScheduler.STATE_ERROR_AUTHENTICATION,
|
||||||
|
get STATE_ERROR_OTHER() internalScheduler.STATE_ERROR_OTHER,
|
||||||
|
|
||||||
|
get state() internalScheduler.state,
|
||||||
|
};
|
||||||
|
|
||||||
|
// These functions are exposed purely for tests, which manage to grab them
|
||||||
|
// via a BackstagePass.
|
||||||
|
function createTestableScheduler() {
|
||||||
|
// kill the "real" scheduler as we don't want it listening to notifications etc.
|
||||||
|
if (internalScheduler) {
|
||||||
|
internalScheduler.finalize();
|
||||||
|
internalScheduler = null;
|
||||||
|
}
|
||||||
|
// No .init() call - that's up to the tests after hooking.
|
||||||
|
return new InternalScheduler();
|
||||||
|
}
|
||||||
|
|
||||||
|
// mochitests want the internal state of the real scheduler for various things.
|
||||||
|
function getInternalScheduler() {
|
||||||
|
return internalScheduler;
|
||||||
|
}
|
@ -13,3 +13,9 @@ TESTING_JS_MODULES += [
|
|||||||
]
|
]
|
||||||
|
|
||||||
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
|
BROWSER_CHROME_MANIFESTS += ['test/browser/browser.ini']
|
||||||
|
|
||||||
|
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
|
||||||
|
|
||||||
|
EXTRA_JS_MODULES.readinglist += [
|
||||||
|
'Scheduler.jsm',
|
||||||
|
]
|
||||||
|
7
browser/components/readinglist/test/xpcshell/head.js
Normal file
7
browser/components/readinglist/test/xpcshell/head.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
146
browser/components/readinglist/test/xpcshell/test_scheduler.js
Normal file
146
browser/components/readinglist/test/xpcshell/test_scheduler.js
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyModuleGetter(this, 'setTimeout',
|
||||||
|
'resource://gre/modules/Timer.jsm');
|
||||||
|
|
||||||
|
// Setup logging prefs before importing the scheduler module.
|
||||||
|
Services.prefs.setCharPref("readinglist.log.appender.dump", "Trace");
|
||||||
|
|
||||||
|
let {createTestableScheduler} = Cu.import("resource:///modules/readinglist/Scheduler.jsm", {});
|
||||||
|
Cu.import("resource://gre/modules/Preferences.jsm");
|
||||||
|
Cu.import("resource://gre/modules/Timer.jsm");
|
||||||
|
|
||||||
|
// Log rotation needs a profile dir.
|
||||||
|
do_get_profile();
|
||||||
|
|
||||||
|
let prefs = new Preferences("readinglist.scheduler.");
|
||||||
|
|
||||||
|
function promiseObserver(topic) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
let obs = (subject, topic, data) => {
|
||||||
|
Services.obs.removeObserver(obs, topic);
|
||||||
|
resolve(data);
|
||||||
|
}
|
||||||
|
Services.obs.addObserver(obs, topic, false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createScheduler(options) {
|
||||||
|
// avoid typos in the test and other footguns in the options.
|
||||||
|
let allowedOptions = ["expectedDelay", "expectNewTimer", "syncFunction"];
|
||||||
|
for (let key of Object.keys(options)) {
|
||||||
|
if (!allowedOptions.includes(key)) {
|
||||||
|
throw new Error("Invalid option " + key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let scheduler = createTestableScheduler();
|
||||||
|
// make our hooks
|
||||||
|
let syncFunction = options.syncFunction || Promise.resolve;
|
||||||
|
scheduler._engine.sync = syncFunction;
|
||||||
|
// we expect _setTimeout to be called *twice* - first is the initial sync,
|
||||||
|
// and there's no need to test the delay used for that. options.expectedDelay
|
||||||
|
// is to check the *subsequent* timer.
|
||||||
|
let numCalls = 0;
|
||||||
|
scheduler._setTimeout = function(delay) {
|
||||||
|
++numCalls;
|
||||||
|
print("Test scheduler _setTimeout call number " + numCalls + " with delay=" + delay);
|
||||||
|
switch (numCalls) {
|
||||||
|
case 1:
|
||||||
|
// this is the first and boring schedule as it initializes - do nothing
|
||||||
|
// other than return a timer that fires immediately.
|
||||||
|
return setTimeout(() => scheduler._doSync(), 0);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// This is the one we are interested in, so check things.
|
||||||
|
if (options.expectedDelay) {
|
||||||
|
// a little slop is OK as it takes a few ms to actually set the timer
|
||||||
|
ok(Math.abs(options.expectedDelay * 1000 - delay) < 500, [options.expectedDelay * 1000, delay]);
|
||||||
|
}
|
||||||
|
// and return a timeout that "never" fires
|
||||||
|
return setTimeout(() => scheduler._doSync(), 10000000);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// This is unexpected!
|
||||||
|
ok(false, numCalls);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// And a callback made once we've determined the next delay. This is always
|
||||||
|
// called even if _setTimeout isn't (due to no timer being created)
|
||||||
|
scheduler._onAutoReschedule = () => {
|
||||||
|
// Most tests expect a new timer, so this is "opt out"
|
||||||
|
let expectNewTimer = options.expectNewTimer === undefined ? true : options.expectNewTimer;
|
||||||
|
ok(expectNewTimer ? scheduler._timer : !scheduler._timer);
|
||||||
|
}
|
||||||
|
// calling .init fires things off...
|
||||||
|
scheduler.init();
|
||||||
|
return scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(function* testSuccess() {
|
||||||
|
// promises which resolve once we've got all the expected notifications.
|
||||||
|
let allNotifications = [
|
||||||
|
promiseObserver("readinglist:sync:start"),
|
||||||
|
promiseObserver("readinglist:sync:finish"),
|
||||||
|
];
|
||||||
|
// New delay should be "as regularly scheduled".
|
||||||
|
prefs.set("schedule", 100);
|
||||||
|
let scheduler = createScheduler({expectedDelay: 100});
|
||||||
|
yield Promise.all(allNotifications);
|
||||||
|
scheduler.finalize();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* testOffline() {
|
||||||
|
let scheduler = createScheduler({expectNewTimer: false});
|
||||||
|
Services.io.offline = true;
|
||||||
|
ok(!scheduler._canSync(), "_canSync is false when offline.")
|
||||||
|
ok(!scheduler._timer, "there is no current timer while offline.")
|
||||||
|
Services.io.offline = false;
|
||||||
|
ok(scheduler._canSync(), "_canSync is true when online.")
|
||||||
|
ok(scheduler._timer, "there is a new timer when back online.")
|
||||||
|
scheduler.finalize();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* testRetryableError() {
|
||||||
|
let allNotifications = [
|
||||||
|
promiseObserver("readinglist:sync:start"),
|
||||||
|
promiseObserver("readinglist:sync:error"),
|
||||||
|
];
|
||||||
|
prefs.set("retry", 10);
|
||||||
|
let scheduler = createScheduler({
|
||||||
|
expectedDelay: 10,
|
||||||
|
syncFunction: () => Promise.reject("transient"),
|
||||||
|
});
|
||||||
|
yield Promise.all(allNotifications);
|
||||||
|
scheduler.finalize();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* testAuthError() {
|
||||||
|
prefs.set("retry", 10);
|
||||||
|
// We expect an auth error to result in no new timer (as it's waiting for
|
||||||
|
// some indication it can proceed), but with the next delay being a normal
|
||||||
|
// "retry" interval (so when we can proceed it is probably already stale, so
|
||||||
|
// is effectively "immediate")
|
||||||
|
let scheduler = createScheduler({
|
||||||
|
expectedDelay: 10,
|
||||||
|
syncFunction: () => {
|
||||||
|
return Promise.reject(ReadingListScheduler._engine.ERROR_AUTHENTICATION);
|
||||||
|
},
|
||||||
|
expectNewTimer: false
|
||||||
|
});
|
||||||
|
// XXX - TODO - send an observer that "unblocks" us and ensure we actually
|
||||||
|
// do unblock.
|
||||||
|
scheduler.finalize();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* testBackoff() {
|
||||||
|
let scheduler = createScheduler({expectedDelay: 1000});
|
||||||
|
Services.obs.notifyObservers(null, "readinglist:backoff-requested", 1000);
|
||||||
|
// XXX - this needs a little love as nothing checks createScheduler actually
|
||||||
|
// made the checks we think it does.
|
||||||
|
scheduler.finalize();
|
||||||
|
});
|
||||||
|
|
||||||
|
function run_test() {
|
||||||
|
run_next_test();
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
[DEFAULT]
|
||||||
|
head = head.js
|
||||||
|
firefox-appdir = browser
|
||||||
|
|
||||||
|
[test_scheduler.js]
|
@ -48,7 +48,7 @@ function test() {
|
|||||||
statusText: "OK",
|
statusText: "OK",
|
||||||
type: "json",
|
type: "json",
|
||||||
fullMimeType: "application/json; charset=utf-8",
|
fullMimeType: "application/json; charset=utf-8",
|
||||||
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
|
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(4),
|
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(4),
|
||||||
@ -67,7 +67,7 @@ function test() {
|
|||||||
statusText: "OK",
|
statusText: "OK",
|
||||||
type: "png",
|
type: "png",
|
||||||
fullMimeType: "image/png",
|
fullMimeType: "image/png",
|
||||||
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.75),
|
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.76),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -228,8 +228,8 @@ function test() {
|
|||||||
statusText: "Meh",
|
statusText: "Meh",
|
||||||
type: "2",
|
type: "2",
|
||||||
fullMimeType: "text/2",
|
fullMimeType: "text/2",
|
||||||
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
|
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
|
||||||
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
|
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(c),
|
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(c),
|
||||||
@ -239,8 +239,8 @@ function test() {
|
|||||||
statusText: "Meh",
|
statusText: "Meh",
|
||||||
type: "3",
|
type: "3",
|
||||||
fullMimeType: "text/3",
|
fullMimeType: "text/3",
|
||||||
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
|
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
|
||||||
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
|
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(d),
|
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(d),
|
||||||
@ -250,8 +250,8 @@ function test() {
|
|||||||
statusText: "Meh",
|
statusText: "Meh",
|
||||||
type: "4",
|
type: "4",
|
||||||
fullMimeType: "text/4",
|
fullMimeType: "text/4",
|
||||||
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
|
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
|
||||||
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
|
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(e),
|
verifyRequestItemTarget(RequestsMenu.getItemAtIndex(e),
|
||||||
@ -261,8 +261,8 @@ function test() {
|
|||||||
statusText: "Meh",
|
statusText: "Meh",
|
||||||
type: "5",
|
type: "5",
|
||||||
fullMimeType: "text/5",
|
fullMimeType: "text/5",
|
||||||
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
|
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.05),
|
||||||
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
|
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.05),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -143,8 +143,8 @@ function test() {
|
|||||||
statusText: "Meh",
|
statusText: "Meh",
|
||||||
type: "2",
|
type: "2",
|
||||||
fullMimeType: "text/2",
|
fullMimeType: "text/2",
|
||||||
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
|
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
|
||||||
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.01),
|
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -156,8 +156,8 @@ function test() {
|
|||||||
statusText: "Meh",
|
statusText: "Meh",
|
||||||
type: "3",
|
type: "3",
|
||||||
fullMimeType: "text/3",
|
fullMimeType: "text/3",
|
||||||
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
|
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
|
||||||
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.02),
|
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -169,8 +169,8 @@ function test() {
|
|||||||
statusText: "Meh",
|
statusText: "Meh",
|
||||||
type: "4",
|
type: "4",
|
||||||
fullMimeType: "text/4",
|
fullMimeType: "text/4",
|
||||||
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
|
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
|
||||||
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.03),
|
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -182,8 +182,8 @@ function test() {
|
|||||||
statusText: "Meh",
|
statusText: "Meh",
|
||||||
type: "5",
|
type: "5",
|
||||||
fullMimeType: "text/5",
|
fullMimeType: "text/5",
|
||||||
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
|
transferred: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.05),
|
||||||
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.04),
|
size: L10N.getFormatStrWithNumbers("networkMenu.sizeKB", 0.05),
|
||||||
time: true
|
time: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -47,11 +47,6 @@ var Resource = Class({
|
|||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the trailing name component of this.uri.
|
|
||||||
*/
|
|
||||||
get basename() { return this.uri.path.replace(/\/+$/, '').replace(/\\/g,'/').replace( /.*\//, '' ); },
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is there more than 1 child Resource?
|
* Is there more than 1 child Resource?
|
||||||
*/
|
*/
|
||||||
@ -238,6 +233,13 @@ var FileResource = Class({
|
|||||||
return this._refreshDeferred.promise;
|
return this._refreshDeferred.promise;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the trailing name component of this Resource
|
||||||
|
*/
|
||||||
|
get basename() {
|
||||||
|
return this.path.replace(/\/+$/, '').replace(/\\/g,'/').replace( /.*\//, '' );
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A string to be used when displaying this Resource in views
|
* A string to be used when displaying this Resource in views
|
||||||
*/
|
*/
|
||||||
|
@ -13,7 +13,29 @@ add_task(function*() {
|
|||||||
let root = [...projecteditor.project.allStores()][0].root;
|
let root = [...projecteditor.project.allStores()][0].root;
|
||||||
is(root.path, TEMP_PATH, "The root store is set to the correct temp path.");
|
is(root.path, TEMP_PATH, "The root store is set to the correct temp path.");
|
||||||
for (let child of root.children) {
|
for (let child of root.children) {
|
||||||
yield renameWithContextMenu(projecteditor, projecteditor.projectTree.getViewContainer(child));
|
yield renameWithContextMenu(projecteditor,
|
||||||
|
projecteditor.projectTree.getViewContainer(child),
|
||||||
|
".renamed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function*() {
|
||||||
|
let projecteditor = yield addProjectEditorTabForTempDirectory();
|
||||||
|
ok(true, "ProjectEditor has loaded");
|
||||||
|
|
||||||
|
let root = [...projecteditor.project.allStores()][0].root;
|
||||||
|
is(root.path, TEMP_PATH, "The root store is set to the correct temp path.");
|
||||||
|
|
||||||
|
let childrenList = new Array();
|
||||||
|
for (let child of root.children) {
|
||||||
|
yield renameWithContextMenu(projecteditor,
|
||||||
|
projecteditor.projectTree.getViewContainer(child),
|
||||||
|
".ren\u0061\u0308med");
|
||||||
|
childrenList.push(child.basename + ".ren\u0061\u0308med");
|
||||||
|
}
|
||||||
|
for (let child of root.children) {
|
||||||
|
is (childrenList.indexOf(child.basename) == -1, false,
|
||||||
|
"Failed to update tree with non-ascii character");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -25,7 +47,7 @@ function openContextMenuOn(node) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function renameWithContextMenu(projecteditor, container) {
|
function renameWithContextMenu(projecteditor, container, newName) {
|
||||||
let defer = promise.defer();
|
let defer = promise.defer();
|
||||||
let popup = projecteditor.contextMenuPopup;
|
let popup = projecteditor.contextMenuPopup;
|
||||||
let resource = container.resource;
|
let resource = container.resource;
|
||||||
@ -39,7 +61,7 @@ function renameWithContextMenu(projecteditor, container) {
|
|||||||
|
|
||||||
projecteditor.project.on("refresh-complete", function refreshComplete() {
|
projecteditor.project.on("refresh-complete", function refreshComplete() {
|
||||||
projecteditor.project.off("refresh-complete", refreshComplete);
|
projecteditor.project.off("refresh-complete", refreshComplete);
|
||||||
OS.File.stat(resource.path + ".renamed").then(() => {
|
OS.File.stat(resource.path + newName).then(() => {
|
||||||
ok (true, "File is renamed");
|
ok (true, "File is renamed");
|
||||||
defer.resolve();
|
defer.resolve();
|
||||||
}, (ex) => {
|
}, (ex) => {
|
||||||
@ -50,7 +72,8 @@ function renameWithContextMenu(projecteditor, container) {
|
|||||||
|
|
||||||
renameCommand.click();
|
renameCommand.click();
|
||||||
popup.hidePopup();
|
popup.hidePopup();
|
||||||
EventUtils.sendString(resource.basename + ".renamed", projecteditor.window);
|
let input = container.elt.previousElementSibling;
|
||||||
|
input.value = resource.basename + newName;
|
||||||
EventUtils.synthesizeKey("VK_RETURN", {}, projecteditor.window);
|
EventUtils.synthesizeKey("VK_RETURN", {}, projecteditor.window);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ function* testGraph(graph) {
|
|||||||
|
|
||||||
is(graph._maxTooltip.querySelector("[text=value]").textContent, "60",
|
is(graph._maxTooltip.querySelector("[text=value]").textContent, "60",
|
||||||
"The maximum tooltip displays the correct value.");
|
"The maximum tooltip displays the correct value.");
|
||||||
is(graph._avgTooltip.querySelector("[text=value]").textContent, "41.71",
|
is(graph._avgTooltip.querySelector("[text=value]").textContent, "41.72",
|
||||||
"The average tooltip displays the correct value.");
|
"The average tooltip displays the correct value.");
|
||||||
is(graph._minTooltip.querySelector("[text=value]").textContent, "10",
|
is(graph._minTooltip.querySelector("[text=value]").textContent, "10",
|
||||||
"The minimum tooltip displays the correct value.");
|
"The minimum tooltip displays the correct value.");
|
||||||
|
@ -8,7 +8,7 @@ let {ViewHelpers} = Cu.import("resource:///modules/devtools/ViewHelpers.jsm", {}
|
|||||||
function test() {
|
function test() {
|
||||||
let l10n = new ViewHelpers.L10N();
|
let l10n = new ViewHelpers.L10N();
|
||||||
|
|
||||||
is(l10n.numberWithDecimals(1234.56789, 2), "1,234.56",
|
is(l10n.numberWithDecimals(1234.56789, 2), "1,234.57",
|
||||||
"The first number was properly localized.");
|
"The first number was properly localized.");
|
||||||
is(l10n.numberWithDecimals(0.0001, 2), "0",
|
is(l10n.numberWithDecimals(0.0001, 2), "0",
|
||||||
"The second number was properly localized.");
|
"The second number was properly localized.");
|
||||||
|
@ -369,10 +369,6 @@ ViewHelpers.L10N.prototype = {
|
|||||||
if (isNaN(aNumber) || aNumber == null) {
|
if (isNaN(aNumber) || aNumber == null) {
|
||||||
return "0";
|
return "0";
|
||||||
}
|
}
|
||||||
// Remove {n} trailing decimals. Can't use toFixed(n) because
|
|
||||||
// toLocaleString converts the number to a string. Also can't use
|
|
||||||
// toLocaleString(, { maximumFractionDigits: n }) because it's not
|
|
||||||
// implemented on OS X (bug 368838). Gross.
|
|
||||||
let localized = aNumber.toLocaleString(); // localize
|
let localized = aNumber.toLocaleString(); // localize
|
||||||
|
|
||||||
// If no grouping or decimal separators are available, bail out, because
|
// If no grouping or decimal separators are available, bail out, because
|
||||||
@ -381,9 +377,10 @@ ViewHelpers.L10N.prototype = {
|
|||||||
return localized;
|
return localized;
|
||||||
}
|
}
|
||||||
|
|
||||||
let padded = localized + new Array(aDecimals).join("0"); // pad with zeros
|
return aNumber.toLocaleString(undefined, {
|
||||||
let match = padded.match("([^]*?\\d{" + aDecimals + "})\\d*$");
|
maximumFractionDigits: aDecimals,
|
||||||
return match.pop();
|
minimumFractionDigits: aDecimals
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -447,13 +447,15 @@ StyleEditorUI.prototype = {
|
|||||||
* Editor to create UI for.
|
* Editor to create UI for.
|
||||||
*/
|
*/
|
||||||
_sourceLoaded: function(editor) {
|
_sourceLoaded: function(editor) {
|
||||||
|
let ordinal = editor.styleSheet.styleSheetIndex;
|
||||||
|
ordinal = ordinal == -1 ? Number.MAX_SAFE_INTEGER : ordinal;
|
||||||
// add new sidebar item and editor to the UI
|
// add new sidebar item and editor to the UI
|
||||||
this._view.appendTemplatedItem(STYLE_EDITOR_TEMPLATE, {
|
this._view.appendTemplatedItem(STYLE_EDITOR_TEMPLATE, {
|
||||||
data: {
|
data: {
|
||||||
editor: editor
|
editor: editor
|
||||||
},
|
},
|
||||||
disableAnimations: this._alwaysDisableAnimations,
|
disableAnimations: this._alwaysDisableAnimations,
|
||||||
ordinal: editor.styleSheet.styleSheetIndex,
|
ordinal: ordinal,
|
||||||
onCreate: function(summary, details, data) {
|
onCreate: function(summary, details, data) {
|
||||||
let editor = data.editor;
|
let editor = data.editor;
|
||||||
editor.summary = summary;
|
editor.summary = summary;
|
||||||
|
@ -15,6 +15,7 @@ const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devt
|
|||||||
const Editor = require("devtools/sourceeditor/editor");
|
const Editor = require("devtools/sourceeditor/editor");
|
||||||
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
const {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||||
const {CssLogic} = require("devtools/styleinspector/css-logic");
|
const {CssLogic} = require("devtools/styleinspector/css-logic");
|
||||||
|
const {console} = require("resource://gre/modules/devtools/Console.jsm");
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||||
@ -251,11 +252,27 @@ StyleSheetEditor.prototype = {
|
|||||||
callback(source);
|
callback(source);
|
||||||
}
|
}
|
||||||
return source;
|
return source;
|
||||||
|
}, e => {
|
||||||
|
if (this._isDestroyed) {
|
||||||
|
console.warn("Could not fetch the source for " +
|
||||||
|
this.styleSheet.href +
|
||||||
|
", the editor was destroyed");
|
||||||
|
Cu.reportError(e);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}, e => {
|
}, e => {
|
||||||
this.emit("error", { key: LOAD_ERROR, append: this.styleSheet.href });
|
if (this._isDestroyed) {
|
||||||
throw e;
|
console.warn("Could not fetch the source for " +
|
||||||
})
|
this.styleSheet.href +
|
||||||
|
", the editor was destroyed");
|
||||||
|
Cu.reportError(e);
|
||||||
|
} else {
|
||||||
|
this.emit("error", { key: LOAD_ERROR, append: this.styleSheet.href });
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -712,6 +729,7 @@ StyleSheetEditor.prototype = {
|
|||||||
this.cssSheet.off("property-change", this._onPropertyChange);
|
this.cssSheet.off("property-change", this._onPropertyChange);
|
||||||
this.cssSheet.off("media-rules-changed", this._onMediaRulesChanged);
|
this.cssSheet.off("media-rules-changed", this._onMediaRulesChanged);
|
||||||
this.styleSheet.off("error", this._onError);
|
this.styleSheet.off("error", this._onError);
|
||||||
|
this._isDestroyed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
//
|
//
|
||||||
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
|
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
|
||||||
|
|
||||||
const TESTCASE_URI = TEST_BASE + "autocomplete.html";
|
const TESTCASE_URI = TEST_BASE_HTTP + "autocomplete.html";
|
||||||
const MAX_SUGGESTIONS = 15;
|
const MAX_SUGGESTIONS = 15;
|
||||||
|
|
||||||
// Pref which decides if CSS autocompletion is enabled in Style Editor or not.
|
// Pref which decides if CSS autocompletion is enabled in Style Editor or not.
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
//
|
//
|
||||||
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
|
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
|
||||||
|
|
||||||
const TESTCASE_URI = TEST_BASE + "four.html";
|
const TESTCASE_URI = TEST_BASE_HTTP + "four.html";
|
||||||
|
|
||||||
let gUI;
|
let gUI;
|
||||||
|
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
const TESTCASE_URI_HTML = TEST_BASE + "simple.html";
|
const TESTCASE_URI_HTML = TEST_BASE_HTTP + "simple.html";
|
||||||
const TESTCASE_URI_CSS = TEST_BASE + "simple.css";
|
const TESTCASE_URI_CSS = TEST_BASE_HTTP + "simple.css";
|
||||||
|
|
||||||
const Cc = Components.classes;
|
const Cc = Components.classes;
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
//
|
//
|
||||||
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: summary is undefined");
|
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("TypeError: summary is undefined");
|
||||||
|
|
||||||
const TESTCASE_URI = TEST_BASE + "simple.html";
|
const TESTCASE_URI = TEST_BASE_HTTP + "simple.html";
|
||||||
|
|
||||||
let gUI;
|
let gUI;
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
|
|||||||
|
|
||||||
let gUI;
|
let gUI;
|
||||||
|
|
||||||
const FIRST_TEST_PAGE = TEST_BASE + "inline-1.html"
|
const FIRST_TEST_PAGE = TEST_BASE_HTTP + "inline-1.html"
|
||||||
const SECOND_TEST_PAGE = TEST_BASE + "inline-2.html"
|
const SECOND_TEST_PAGE = TEST_BASE_HTTP + "inline-2.html"
|
||||||
const SAVE_PATH = "test.css";
|
const SAVE_PATH = "test.css";
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
//
|
//
|
||||||
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
|
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
|
||||||
|
|
||||||
const TESTCASE_URI = TEST_BASE + "simple.html";
|
const TESTCASE_URI = TEST_BASE_HTTP + "simple.html";
|
||||||
|
|
||||||
let TESTCASE_CSS_SOURCE = "body{background-color:red;";
|
let TESTCASE_CSS_SOURCE = "body{background-color:red;";
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
const TESTCASE_URI = TEST_BASE + "nostyle.html";
|
const TESTCASE_URI = TEST_BASE_HTTP + "nostyle.html";
|
||||||
|
|
||||||
|
|
||||||
function test()
|
function test()
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
//
|
//
|
||||||
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
|
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
|
||||||
|
|
||||||
const TESTCASE_URI = TEST_BASE + "minified.html";
|
const TESTCASE_URI = TEST_BASE_HTTP + "minified.html";
|
||||||
|
|
||||||
let gUI;
|
let gUI;
|
||||||
|
|
||||||
|
@ -6,11 +6,11 @@ Components.utils.import("resource://gre/modules/Task.jsm");
|
|||||||
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||||
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||||
|
|
||||||
const TESTCASE_URI_HTML = TEST_BASE + "sourcemaps-watching.html";
|
const TESTCASE_URI_HTML = TEST_BASE_HTTP + "sourcemaps-watching.html";
|
||||||
const TESTCASE_URI_CSS = TEST_BASE + "sourcemap-css/sourcemaps.css";
|
const TESTCASE_URI_CSS = TEST_BASE_HTTP + "sourcemap-css/sourcemaps.css";
|
||||||
const TESTCASE_URI_REG_CSS = TEST_BASE + "simple.css";
|
const TESTCASE_URI_REG_CSS = TEST_BASE_HTTP + "simple.css";
|
||||||
const TESTCASE_URI_SCSS = TEST_BASE + "sourcemap-sass/sourcemaps.scss";
|
const TESTCASE_URI_SCSS = TEST_BASE_HTTP + "sourcemap-sass/sourcemaps.scss";
|
||||||
const TESTCASE_URI_MAP = TEST_BASE + "sourcemap-css/sourcemaps.css.map";
|
const TESTCASE_URI_MAP = TEST_BASE_HTTP + "sourcemap-css/sourcemaps.css.map";
|
||||||
const TESTCASE_SCSS_NAME = "sourcemaps.scss";
|
const TESTCASE_SCSS_NAME = "sourcemaps.scss";
|
||||||
|
|
||||||
const TRANSITIONS_PREF = "devtools.styleeditor.transitions";
|
const TRANSITIONS_PREF = "devtools.styleeditor.transitions";
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
//
|
//
|
||||||
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
|
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("Error: Unknown sheet source");
|
||||||
|
|
||||||
const TESTCASE_URI = TEST_BASE + "four.html";
|
const TESTCASE_URI = TEST_BASE_HTTP + "four.html";
|
||||||
|
|
||||||
let gUI;
|
let gUI;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
const TESTCASE_URI = TEST_BASE + "simple.html";
|
const TESTCASE_URI = TEST_BASE_HTTP + "simple.html";
|
||||||
|
|
||||||
let gOriginalWidth; // these are set by runTests()
|
let gOriginalWidth; // these are set by runTests()
|
||||||
let gOriginalHeight;
|
let gOriginalHeight;
|
||||||
|
@ -354,6 +354,7 @@ skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
|
|||||||
skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
|
skip-if = e10s # Bug 1042253 - webconsole tests disabled with e10s
|
||||||
[browser_webconsole_autocomplete-properties-with-non-alphanumeric-names.js]
|
[browser_webconsole_autocomplete-properties-with-non-alphanumeric-names.js]
|
||||||
[browser_console_hide_jsterm_when_devtools_chrome_enabled_false.js]
|
[browser_console_hide_jsterm_when_devtools_chrome_enabled_false.js]
|
||||||
|
[browser_console_history_persist.js]
|
||||||
[browser_webconsole_output_01.js]
|
[browser_webconsole_output_01.js]
|
||||||
skip-if = e10s # Bug 1042253 - webconsole e10s tests
|
skip-if = e10s # Bug 1042253 - webconsole e10s tests
|
||||||
[browser_webconsole_output_02.js]
|
[browser_webconsole_output_02.js]
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
// Test that console command input is persisted across toolbox loads.
|
||||||
|
// See Bug 943306.
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const TEST_URI = "data:text/html;charset=utf-8,Web Console test for persisting history - bug 943306";
|
||||||
|
const INPUT_HISTORY_COUNT = 10;
|
||||||
|
|
||||||
|
let test = asyncTest(function* () {
|
||||||
|
info ("Setting custom input history pref to " + INPUT_HISTORY_COUNT);
|
||||||
|
Services.prefs.setIntPref("devtools.webconsole.inputHistoryCount", INPUT_HISTORY_COUNT);
|
||||||
|
|
||||||
|
// First tab: run a bunch of commands and then make sure that you can
|
||||||
|
// navigate through their history.
|
||||||
|
yield loadTab(TEST_URI);
|
||||||
|
let hud1 = yield openConsole();
|
||||||
|
is (JSON.stringify(hud1.jsterm.history), "[]", "No history on first tab initially");
|
||||||
|
yield populateInputHistory(hud1);
|
||||||
|
is (JSON.stringify(hud1.jsterm.history), '["0","1","2","3","4","5","6","7","8","9"]',
|
||||||
|
"First tab has populated history");
|
||||||
|
|
||||||
|
// Second tab: Just make sure that you can navigate through the history
|
||||||
|
// generated by the first tab.
|
||||||
|
yield loadTab(TEST_URI);
|
||||||
|
let hud2 = yield openConsole();
|
||||||
|
is (JSON.stringify(hud2.jsterm.history), '["0","1","2","3","4","5","6","7","8","9"]',
|
||||||
|
"Second tab has populated history");
|
||||||
|
yield testNaviatingHistoryInUI(hud2);
|
||||||
|
is (JSON.stringify(hud2.jsterm.history), '["0","1","2","3","4","5","6","7","8","9",""]',
|
||||||
|
"An empty entry has been added in the second tab due to history perusal");
|
||||||
|
|
||||||
|
// Third tab: Should have the same history as first tab, but if we run a
|
||||||
|
// command, then the history of the first and second shouldn't be affected
|
||||||
|
yield loadTab(TEST_URI);
|
||||||
|
let hud3 = yield openConsole();
|
||||||
|
is (JSON.stringify(hud3.jsterm.history), '["0","1","2","3","4","5","6","7","8","9"]',
|
||||||
|
"Third tab has populated history");
|
||||||
|
|
||||||
|
// Set input value separately from execute so UP arrow accurately navigates history.
|
||||||
|
hud3.jsterm.setInputValue('"hello from third tab"');
|
||||||
|
hud3.jsterm.execute();
|
||||||
|
|
||||||
|
is (JSON.stringify(hud1.jsterm.history), '["0","1","2","3","4","5","6","7","8","9"]',
|
||||||
|
"First tab history hasn't changed due to command in third tab");
|
||||||
|
is (JSON.stringify(hud2.jsterm.history), '["0","1","2","3","4","5","6","7","8","9",""]',
|
||||||
|
"Second tab history hasn't changed due to command in third tab");
|
||||||
|
is (JSON.stringify(hud3.jsterm.history), '["1","2","3","4","5","6","7","8","9","\\"hello from third tab\\""]',
|
||||||
|
"Third tab has updated history (and purged the first result) after running a command");
|
||||||
|
|
||||||
|
// Fourth tab: Should have the latest command from the third tab, followed
|
||||||
|
// by the rest of the history from the first tab.
|
||||||
|
yield loadTab(TEST_URI);
|
||||||
|
let hud4 = yield openConsole();
|
||||||
|
is (JSON.stringify(hud4.jsterm.history), '["1","2","3","4","5","6","7","8","9","\\"hello from third tab\\""]',
|
||||||
|
"Fourth tab has most recent history");
|
||||||
|
|
||||||
|
info ("Clearing custom input history pref");
|
||||||
|
Services.prefs.clearUserPref("devtools.webconsole.inputHistoryCount");
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the history by running the following commands:
|
||||||
|
* [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||||
|
*/
|
||||||
|
function* populateInputHistory(hud) {
|
||||||
|
let jsterm = hud.jsterm;
|
||||||
|
let {inputNode} = jsterm;
|
||||||
|
|
||||||
|
for (let i = 0; i < INPUT_HISTORY_COUNT; i++) {
|
||||||
|
// Set input value separately from execute so UP arrow accurately navigates history.
|
||||||
|
jsterm.setInputValue(i);
|
||||||
|
jsterm.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check pressing up results in history traversal like:
|
||||||
|
* [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
|
||||||
|
*/
|
||||||
|
function* testNaviatingHistoryInUI(hud) {
|
||||||
|
let jsterm = hud.jsterm;
|
||||||
|
let {inputNode} = jsterm;
|
||||||
|
inputNode.focus();
|
||||||
|
|
||||||
|
// Count backwards from original input and make sure that pressing up
|
||||||
|
// restores this.
|
||||||
|
for (let i = INPUT_HISTORY_COUNT - 1; i >= 0; i--) {
|
||||||
|
EventUtils.synthesizeKey("VK_UP", {});
|
||||||
|
is(inputNode.value, i, "Pressing up restores last input");
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
|||||||
let {require, TargetFactory} = devtools;
|
let {require, TargetFactory} = devtools;
|
||||||
let {Utils: WebConsoleUtils} = require("devtools/toolkit/webconsole/utils");
|
let {Utils: WebConsoleUtils} = require("devtools/toolkit/webconsole/utils");
|
||||||
let {Messages} = require("devtools/webconsole/console-output");
|
let {Messages} = require("devtools/webconsole/console-output");
|
||||||
|
const asyncStorage = require("devtools/toolkit/shared/async-storage");
|
||||||
|
|
||||||
// promise._reportErrors = true; // please never leave me.
|
// promise._reportErrors = true; // please never leave me.
|
||||||
//Services.prefs.setBoolPref("devtools.debugger.log", true);
|
//Services.prefs.setBoolPref("devtools.debugger.log", true);
|
||||||
@ -322,6 +323,9 @@ let finishTest = Task.async(function* () {
|
|||||||
registerCleanupFunction(function*() {
|
registerCleanupFunction(function*() {
|
||||||
gDevTools.testing = false;
|
gDevTools.testing = false;
|
||||||
|
|
||||||
|
// Remove stored console commands in between tests
|
||||||
|
yield asyncStorage.removeItem("webConsoleHistory");
|
||||||
|
|
||||||
dumpConsoles();
|
dumpConsoles();
|
||||||
|
|
||||||
if (HUDService.getBrowserConsole()) {
|
if (HUDService.getBrowserConsole()) {
|
||||||
|
@ -26,6 +26,8 @@ loader.lazyGetter(this, "ConsoleOutput",
|
|||||||
() => require("devtools/webconsole/console-output").ConsoleOutput);
|
() => require("devtools/webconsole/console-output").ConsoleOutput);
|
||||||
loader.lazyGetter(this, "Messages",
|
loader.lazyGetter(this, "Messages",
|
||||||
() => require("devtools/webconsole/console-output").Messages);
|
() => require("devtools/webconsole/console-output").Messages);
|
||||||
|
loader.lazyGetter(this, "asyncStorage",
|
||||||
|
() => require("devtools/toolkit/shared/async-storage"));
|
||||||
loader.lazyImporter(this, "EnvironmentClient", "resource://gre/modules/devtools/dbg-client.jsm");
|
loader.lazyImporter(this, "EnvironmentClient", "resource://gre/modules/devtools/dbg-client.jsm");
|
||||||
loader.lazyImporter(this, "ObjectClient", "resource://gre/modules/devtools/dbg-client.jsm");
|
loader.lazyImporter(this, "ObjectClient", "resource://gre/modules/devtools/dbg-client.jsm");
|
||||||
loader.lazyImporter(this, "VariablesView", "resource:///modules/devtools/VariablesView.jsm");
|
loader.lazyImporter(this, "VariablesView", "resource:///modules/devtools/VariablesView.jsm");
|
||||||
@ -176,6 +178,7 @@ const MIN_FONT_SIZE = 10;
|
|||||||
const PREF_CONNECTION_TIMEOUT = "devtools.debugger.remote-timeout";
|
const PREF_CONNECTION_TIMEOUT = "devtools.debugger.remote-timeout";
|
||||||
const PREF_PERSISTLOG = "devtools.webconsole.persistlog";
|
const PREF_PERSISTLOG = "devtools.webconsole.persistlog";
|
||||||
const PREF_MESSAGE_TIMESTAMP = "devtools.webconsole.timestampMessages";
|
const PREF_MESSAGE_TIMESTAMP = "devtools.webconsole.timestampMessages";
|
||||||
|
const PREF_INPUT_HISTORY_COUNT = "devtools.webconsole.inputHistoryCount";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A WebConsoleFrame instance is an interactive console initialized *per target*
|
* A WebConsoleFrame instance is an interactive console initialized *per target*
|
||||||
@ -443,12 +446,29 @@ WebConsoleFrame.prototype = {
|
|||||||
/**
|
/**
|
||||||
* Initialize the WebConsoleFrame instance.
|
* Initialize the WebConsoleFrame instance.
|
||||||
* @return object
|
* @return object
|
||||||
* A promise object for the initialization.
|
* A promise object that resolves once the frame is ready to use.
|
||||||
*/
|
*/
|
||||||
init: function WCF_init()
|
init: function()
|
||||||
{
|
{
|
||||||
this._initUI();
|
this._initUI();
|
||||||
return this._initConnection();
|
let connectionInited = this._initConnection();
|
||||||
|
|
||||||
|
// Don't reject if the history fails to load for some reason.
|
||||||
|
// This would be fine, the panel will just start with empty history.
|
||||||
|
let allReady = this.jsterm.historyLoaded.catch(() => {}).then(() => {
|
||||||
|
return connectionInited;
|
||||||
|
});
|
||||||
|
|
||||||
|
// This notification is only used in tests. Don't chain it onto
|
||||||
|
// the returned promise because the console panel needs to be attached
|
||||||
|
// to the toolbox before the web-console-created event is receieved.
|
||||||
|
let notifyObservers = () => {
|
||||||
|
let id = WebConsoleUtils.supportsString(this.hudId);
|
||||||
|
Services.obs.notifyObservers(id, "web-console-created", null);
|
||||||
|
};
|
||||||
|
allReady.then(notifyObservers, notifyObservers);
|
||||||
|
|
||||||
|
return allReady;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -475,9 +495,6 @@ WebConsoleFrame.prototype = {
|
|||||||
aReason.error + ": " + aReason.message);
|
aReason.error + ": " + aReason.message);
|
||||||
this.outputMessage(CATEGORY_JS, node, [aReason]);
|
this.outputMessage(CATEGORY_JS, node, [aReason]);
|
||||||
this._initDefer.reject(aReason);
|
this._initDefer.reject(aReason);
|
||||||
}).then(() => {
|
|
||||||
let id = WebConsoleUtils.supportsString(this.hudId);
|
|
||||||
Services.obs.notifyObservers(id, "web-console-created", null);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return this._initDefer.promise;
|
return this._initDefer.promise;
|
||||||
@ -3054,17 +3071,11 @@ function JSTerm(aWebConsoleFrame)
|
|||||||
{
|
{
|
||||||
this.hud = aWebConsoleFrame;
|
this.hud = aWebConsoleFrame;
|
||||||
this.hudId = this.hud.hudId;
|
this.hudId = this.hud.hudId;
|
||||||
|
this.inputHistoryCount = Services.prefs.getIntPref(PREF_INPUT_HISTORY_COUNT);
|
||||||
|
|
||||||
this.lastCompletion = { value: null };
|
this.lastCompletion = { value: null };
|
||||||
this.history = [];
|
this._loadHistory();
|
||||||
|
|
||||||
// Holds the number of entries in history. This value is incremented in
|
|
||||||
// this.execute().
|
|
||||||
this.historyIndex = 0; // incremented on this.execute()
|
|
||||||
|
|
||||||
// Holds the index of the history entry that the user is currently viewing.
|
|
||||||
// This is reset to this.history.length when this.execute() is invoked.
|
|
||||||
this.historyPlaceHolder = 0;
|
|
||||||
this._objectActorsInVariablesViews = new Map();
|
this._objectActorsInVariablesViews = new Map();
|
||||||
|
|
||||||
this._keyPress = this._keyPress.bind(this);
|
this._keyPress = this._keyPress.bind(this);
|
||||||
@ -3079,6 +3090,38 @@ function JSTerm(aWebConsoleFrame)
|
|||||||
JSTerm.prototype = {
|
JSTerm.prototype = {
|
||||||
SELECTED_FRAME: -1,
|
SELECTED_FRAME: -1,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the console history from previous sessions.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_loadHistory: function() {
|
||||||
|
this.history = [];
|
||||||
|
this.historyIndex = this.historyPlaceHolder = 0;
|
||||||
|
|
||||||
|
this.historyLoaded = asyncStorage.getItem("webConsoleHistory").then(value => {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
// Since it was gotten asynchronously, there could be items already in
|
||||||
|
// the history. It's not likely but stick them onto the end anyway.
|
||||||
|
this.history = value.concat(this.history);
|
||||||
|
|
||||||
|
// Holds the number of entries in history. This value is incremented in
|
||||||
|
// this.execute().
|
||||||
|
this.historyIndex = this.history.length;
|
||||||
|
|
||||||
|
// Holds the index of the history entry that the user is currently viewing.
|
||||||
|
// This is reset to this.history.length when this.execute() is invoked.
|
||||||
|
this.historyPlaceHolder = this.history.length;
|
||||||
|
}
|
||||||
|
}, console.error);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the console history for future sessions.
|
||||||
|
*/
|
||||||
|
storeHistory: function() {
|
||||||
|
asyncStorage.setItem("webConsoleHistory", this.history);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the data for the last completion.
|
* Stores the data for the last completion.
|
||||||
* @type object
|
* @type object
|
||||||
@ -3388,6 +3431,12 @@ JSTerm.prototype = {
|
|||||||
// value that was not evaluated yet.
|
// value that was not evaluated yet.
|
||||||
this.history[this.historyIndex++] = aExecuteString;
|
this.history[this.historyIndex++] = aExecuteString;
|
||||||
this.historyPlaceHolder = this.history.length;
|
this.historyPlaceHolder = this.history.length;
|
||||||
|
|
||||||
|
if (this.history.length > this.inputHistoryCount) {
|
||||||
|
this.history.splice(0, this.history.length - this.inputHistoryCount);
|
||||||
|
this.historyIndex = this.historyPlaceHolder = this.history.length;
|
||||||
|
}
|
||||||
|
this.storeHistory();
|
||||||
WebConsoleUtils.usageCount++;
|
WebConsoleUtils.usageCount++;
|
||||||
this.setInputValue("");
|
this.setInputValue("");
|
||||||
this.clearCompletion();
|
this.clearCompletion();
|
||||||
|
@ -495,9 +495,14 @@ label.requests-menu-status-code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tabpanel-summary-value {
|
.tabpanel-summary-value {
|
||||||
|
color: inherit;
|
||||||
-moz-padding-start: 3px;
|
-moz-padding-start: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.theme-dark .tabpanel-summary-value {
|
||||||
|
color: var(--theme-selection-color);
|
||||||
|
}
|
||||||
|
|
||||||
/* Headers tabpanel */
|
/* Headers tabpanel */
|
||||||
|
|
||||||
#headers-summary-status,
|
#headers-summary-status,
|
||||||
|
28
dom/bluetooth/BluetoothInterfaceHelpers.cpp
Normal file
28
dom/bluetooth/BluetoothInterfaceHelpers.cpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||||
|
/* vim: set ts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "BluetoothInterfaceHelpers.h"
|
||||||
|
|
||||||
|
BEGIN_BLUETOOTH_NAMESPACE
|
||||||
|
|
||||||
|
//
|
||||||
|
// Conversion
|
||||||
|
//
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
Convert(nsresult aIn, BluetoothStatus& aOut)
|
||||||
|
{
|
||||||
|
if (NS_SUCCEEDED(aIn)) {
|
||||||
|
aOut = STATUS_SUCCESS;
|
||||||
|
} else if (aIn == NS_ERROR_OUT_OF_MEMORY) {
|
||||||
|
aOut = STATUS_NOMEM;
|
||||||
|
} else {
|
||||||
|
aOut = STATUS_FAIL;
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
END_BLUETOOTH_NAMESPACE
|
@ -12,6 +12,13 @@
|
|||||||
|
|
||||||
BEGIN_BLUETOOTH_NAMESPACE
|
BEGIN_BLUETOOTH_NAMESPACE
|
||||||
|
|
||||||
|
//
|
||||||
|
// Conversion
|
||||||
|
//
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
Convert(nsresult aIn, BluetoothStatus& aOut);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Result handling
|
// Result handling
|
||||||
//
|
//
|
||||||
@ -49,6 +56,9 @@ public:
|
|||||||
static void
|
static void
|
||||||
Dispatch(Obj* aObj, Res (Obj::*aMethod)(), const InitOp& aInitOp)
|
Dispatch(Obj* aObj, Res (Obj::*aMethod)(), const InitOp& aInitOp)
|
||||||
{
|
{
|
||||||
|
if (!aObj) {
|
||||||
|
return; // silently return if no result runnable has been given
|
||||||
|
}
|
||||||
nsRefPtr<SelfType> runnable = Create(aObj, aMethod, aInitOp);
|
nsRefPtr<SelfType> runnable = Create(aObj, aMethod, aInitOp);
|
||||||
if (!runnable) {
|
if (!runnable) {
|
||||||
BT_LOGR("BluetoothResultRunnable0::Create failed");
|
BT_LOGR("BluetoothResultRunnable0::Create failed");
|
||||||
@ -108,6 +118,9 @@ public:
|
|||||||
static void
|
static void
|
||||||
Dispatch(Obj* aObj, Res (Obj::*aMethod)(Arg1), const InitOp& aInitOp)
|
Dispatch(Obj* aObj, Res (Obj::*aMethod)(Arg1), const InitOp& aInitOp)
|
||||||
{
|
{
|
||||||
|
if (!aObj) {
|
||||||
|
return; // silently return if no result runnable has been given
|
||||||
|
}
|
||||||
nsRefPtr<SelfType> runnable = Create(aObj, aMethod, aInitOp);
|
nsRefPtr<SelfType> runnable = Create(aObj, aMethod, aInitOp);
|
||||||
if (!runnable) {
|
if (!runnable) {
|
||||||
BT_LOGR("BluetoothResultRunnable1::Create failed");
|
BT_LOGR("BluetoothResultRunnable1::Create failed");
|
||||||
@ -174,6 +187,9 @@ public:
|
|||||||
Dispatch(Obj* aObj, Res (Obj::*aMethod)(Arg1, Arg2, Arg3),
|
Dispatch(Obj* aObj, Res (Obj::*aMethod)(Arg1, Arg2, Arg3),
|
||||||
const InitOp& aInitOp)
|
const InitOp& aInitOp)
|
||||||
{
|
{
|
||||||
|
if (!aObj) {
|
||||||
|
return; // silently return if no result runnable has been given
|
||||||
|
}
|
||||||
nsRefPtr<SelfType> runnable = Create(aObj, aMethod, aInitOp);
|
nsRefPtr<SelfType> runnable = Create(aObj, aMethod, aInitOp);
|
||||||
if (!runnable) {
|
if (!runnable) {
|
||||||
BT_LOGR("BluetoothResultRunnable3::Create failed");
|
BT_LOGR("BluetoothResultRunnable3::Create failed");
|
||||||
|
@ -335,6 +335,9 @@ public:
|
|||||||
{
|
{
|
||||||
BT_WARNING("BluetoothAvrcpInterface::Cleanup failed: %d",
|
BT_WARNING("BluetoothAvrcpInterface::Cleanup failed: %d",
|
||||||
(int)aStatus);
|
(int)aStatus);
|
||||||
|
|
||||||
|
sBtAvrcpInterface = nullptr;
|
||||||
|
|
||||||
if (mRes) {
|
if (mRes) {
|
||||||
if (aStatus == STATUS_UNSUPPORTED) {
|
if (aStatus == STATUS_UNSUPPORTED) {
|
||||||
/* Not all versions of Bluedroid support AVRCP. So if the
|
/* Not all versions of Bluedroid support AVRCP. So if the
|
||||||
@ -371,6 +374,9 @@ public:
|
|||||||
{
|
{
|
||||||
BT_WARNING("BluetoothA2dpInterface::Cleanup failed: %d",
|
BT_WARNING("BluetoothA2dpInterface::Cleanup failed: %d",
|
||||||
(int)aStatus);
|
(int)aStatus);
|
||||||
|
|
||||||
|
sBtA2dpInterface = nullptr;
|
||||||
|
|
||||||
if (mRes) {
|
if (mRes) {
|
||||||
mRes->OnError(NS_ERROR_FAILURE);
|
mRes->OnError(NS_ERROR_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -395,7 +395,7 @@ BluetoothDaemonA2dpInterface::Init(
|
|||||||
nsresult rv = mModule->RegisterModule(BluetoothDaemonA2dpModule::SERVICE_ID,
|
nsresult rv = mModule->RegisterModule(BluetoothDaemonA2dpModule::SERVICE_ID,
|
||||||
0x00, BluetoothDaemonA2dpModule::MAX_NUM_CLIENTS, res);
|
0x00, BluetoothDaemonA2dpModule::MAX_NUM_CLIENTS, res);
|
||||||
if (NS_FAILED(rv) && aRes) {
|
if (NS_FAILED(rv) && aRes) {
|
||||||
DispatchError(aRes, STATUS_FAIL);
|
DispatchError(aRes, rv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,8 +443,12 @@ void
|
|||||||
BluetoothDaemonA2dpInterface::Cleanup(
|
BluetoothDaemonA2dpInterface::Cleanup(
|
||||||
BluetoothA2dpResultHandler* aRes)
|
BluetoothA2dpResultHandler* aRes)
|
||||||
{
|
{
|
||||||
mModule->UnregisterModule(BluetoothDaemonA2dpModule::SERVICE_ID,
|
nsresult rv = mModule->UnregisterModule(
|
||||||
new CleanupResultHandler(mModule, aRes));
|
BluetoothDaemonA2dpModule::SERVICE_ID,
|
||||||
|
new CleanupResultHandler(mModule, aRes));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connect / Disconnect */
|
/* Connect / Disconnect */
|
||||||
@ -455,7 +459,10 @@ BluetoothDaemonA2dpInterface::Connect(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->ConnectCmd(aBdAddr, aRes);
|
nsresult rv = mModule->ConnectCmd(aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -464,7 +471,10 @@ BluetoothDaemonA2dpInterface::Disconnect(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->DisconnectCmd(aBdAddr, aRes);
|
nsresult rv = mModule->DisconnectCmd(aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -477,4 +487,16 @@ BluetoothDaemonA2dpInterface::DispatchError(
|
|||||||
ConstantInitOp1<BluetoothStatus>(aStatus));
|
ConstantInitOp1<BluetoothStatus>(aStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothDaemonA2dpInterface::DispatchError(
|
||||||
|
BluetoothA2dpResultHandler* aRes, nsresult aRv)
|
||||||
|
{
|
||||||
|
BluetoothStatus status;
|
||||||
|
|
||||||
|
if (NS_WARN_IF(NS_FAILED(Convert(aRv, status)))) {
|
||||||
|
status = STATUS_FAIL;
|
||||||
|
}
|
||||||
|
DispatchError(aRes, status);
|
||||||
|
}
|
||||||
|
|
||||||
END_BLUETOOTH_NAMESPACE
|
END_BLUETOOTH_NAMESPACE
|
||||||
|
@ -155,6 +155,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void DispatchError(BluetoothA2dpResultHandler* aRes,
|
void DispatchError(BluetoothA2dpResultHandler* aRes,
|
||||||
BluetoothStatus aStatus);
|
BluetoothStatus aStatus);
|
||||||
|
void DispatchError(BluetoothA2dpResultHandler* aRes, nsresult aRv);
|
||||||
|
|
||||||
BluetoothDaemonA2dpModule* mModule;
|
BluetoothDaemonA2dpModule* mModule;
|
||||||
};
|
};
|
||||||
|
@ -893,7 +893,7 @@ BluetoothDaemonAvrcpInterface::Init(
|
|||||||
BluetoothDaemonAvrcpModule::MAX_NUM_CLIENTS, 0x00, res);
|
BluetoothDaemonAvrcpModule::MAX_NUM_CLIENTS, 0x00, res);
|
||||||
|
|
||||||
if (NS_FAILED(rv) && aRes) {
|
if (NS_FAILED(rv) && aRes) {
|
||||||
DispatchError(aRes, STATUS_FAIL);
|
DispatchError(aRes, rv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -943,8 +943,12 @@ BluetoothDaemonAvrcpInterface::Cleanup(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->UnregisterModule(BluetoothDaemonAvrcpModule::SERVICE_ID,
|
nsresult rv = mModule->UnregisterModule(
|
||||||
new CleanupResultHandler(mModule, aRes));
|
BluetoothDaemonAvrcpModule::SERVICE_ID,
|
||||||
|
new CleanupResultHandler(mModule, aRes));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -954,7 +958,11 @@ BluetoothDaemonAvrcpInterface::GetPlayStatusRsp(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->GetPlayStatusRspCmd(aPlayStatus, aSongLen, aSongPos, aRes);
|
nsresult rv = mModule->GetPlayStatusRspCmd(aPlayStatus, aSongLen,
|
||||||
|
aSongPos, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -964,7 +972,10 @@ BluetoothDaemonAvrcpInterface::ListPlayerAppAttrRsp(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->ListPlayerAppAttrRspCmd(aNumAttr, aPAttrs, aRes);
|
nsresult rv = mModule->ListPlayerAppAttrRspCmd(aNumAttr, aPAttrs, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -973,7 +984,10 @@ BluetoothDaemonAvrcpInterface::ListPlayerAppValueRsp(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->ListPlayerAppValueRspCmd(aNumVal, aPVals, aRes);
|
nsresult rv = mModule->ListPlayerAppValueRspCmd(aNumVal, aPVals, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -983,7 +997,11 @@ BluetoothDaemonAvrcpInterface::GetPlayerAppValueRsp(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->GetPlayerAppValueRspCmd(aNumAttrs, aIds, aValues, aRes);
|
nsresult rv = mModule->GetPlayerAppValueRspCmd(aNumAttrs, aIds,
|
||||||
|
aValues, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -993,7 +1011,11 @@ BluetoothDaemonAvrcpInterface::GetPlayerAppAttrTextRsp(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->GetPlayerAppAttrTextRspCmd(aNumAttr, aIds, aTexts, aRes);
|
nsresult rv = mModule->GetPlayerAppAttrTextRspCmd(aNumAttr, aIds,
|
||||||
|
aTexts, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1003,7 +1025,11 @@ BluetoothDaemonAvrcpInterface::GetPlayerAppValueTextRsp(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->GetPlayerAppValueTextRspCmd(aNumVal, aIds, aTexts, aRes);
|
nsresult rv = mModule->GetPlayerAppValueTextRspCmd(aNumVal, aIds,
|
||||||
|
aTexts, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1013,7 +1039,10 @@ BluetoothDaemonAvrcpInterface::GetElementAttrRsp(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->GetElementAttrRspCmd(aNumAttr, aAttr, aRes);
|
nsresult rv = mModule->GetElementAttrRspCmd(aNumAttr, aAttr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1022,7 +1051,10 @@ BluetoothDaemonAvrcpInterface::SetPlayerAppValueRsp(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->SetPlayerAppValueRspCmd(aRspStatus, aRes);
|
nsresult rv = mModule->SetPlayerAppValueRspCmd(aRspStatus, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1034,7 +1066,11 @@ BluetoothDaemonAvrcpInterface::RegisterNotificationRsp(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->RegisterNotificationRspCmd(aEvent, aType, aParam, aRes);
|
nsresult rv = mModule->RegisterNotificationRspCmd(aEvent, aType,
|
||||||
|
aParam, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1043,7 +1079,10 @@ BluetoothDaemonAvrcpInterface::SetVolume(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->SetVolumeCmd(aVolume, aRes);
|
nsresult rv = mModule->SetVolumeCmd(aVolume, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1056,4 +1095,16 @@ BluetoothDaemonAvrcpInterface::DispatchError(
|
|||||||
ConstantInitOp1<BluetoothStatus>(aStatus));
|
ConstantInitOp1<BluetoothStatus>(aStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothDaemonAvrcpInterface::DispatchError(
|
||||||
|
BluetoothAvrcpResultHandler* aRes, nsresult aRv)
|
||||||
|
{
|
||||||
|
BluetoothStatus status;
|
||||||
|
|
||||||
|
if (NS_WARN_IF(NS_FAILED(Convert(aRv, status)))) {
|
||||||
|
status = STATUS_FAIL;
|
||||||
|
}
|
||||||
|
DispatchError(aRes, status);
|
||||||
|
}
|
||||||
|
|
||||||
END_BLUETOOTH_NAMESPACE
|
END_BLUETOOTH_NAMESPACE
|
||||||
|
@ -346,6 +346,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void DispatchError(BluetoothAvrcpResultHandler* aRes,
|
void DispatchError(BluetoothAvrcpResultHandler* aRes,
|
||||||
BluetoothStatus aStatus);
|
BluetoothStatus aStatus);
|
||||||
|
void DispatchError(BluetoothAvrcpResultHandler* aRes, nsresult aRv);
|
||||||
|
|
||||||
BluetoothDaemonAvrcpModule* mModule;
|
BluetoothDaemonAvrcpModule* mModule;
|
||||||
};
|
};
|
||||||
|
@ -1512,7 +1512,7 @@ BluetoothDaemonHandsfreeInterface::Init(
|
|||||||
aMaxNumClients, res);
|
aMaxNumClients, res);
|
||||||
|
|
||||||
if (NS_FAILED(rv) && aRes) {
|
if (NS_FAILED(rv) && aRes) {
|
||||||
DispatchError(aRes, STATUS_FAIL);
|
DispatchError(aRes, rv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1532,6 +1532,7 @@ public:
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
BT_LOGR("%s:%d", __func__, __LINE__);
|
||||||
if (mRes) {
|
if (mRes) {
|
||||||
mRes->OnError(aStatus);
|
mRes->OnError(aStatus);
|
||||||
}
|
}
|
||||||
@ -1541,6 +1542,7 @@ public:
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
BT_LOGR("%s:%d", __func__, __LINE__);
|
||||||
// Clear notification handler _after_ module has been
|
// Clear notification handler _after_ module has been
|
||||||
// unregistered. While unregistering the module, we might
|
// unregistered. While unregistering the module, we might
|
||||||
// still receive notifications.
|
// still receive notifications.
|
||||||
@ -1560,8 +1562,14 @@ void
|
|||||||
BluetoothDaemonHandsfreeInterface::Cleanup(
|
BluetoothDaemonHandsfreeInterface::Cleanup(
|
||||||
BluetoothHandsfreeResultHandler* aRes)
|
BluetoothHandsfreeResultHandler* aRes)
|
||||||
{
|
{
|
||||||
mModule->UnregisterModule(BluetoothDaemonHandsfreeModule::SERVICE_ID,
|
BT_LOGR("%s:%d", __func__, __LINE__);
|
||||||
new CleanupResultHandler(mModule, aRes));
|
nsresult rv = mModule->UnregisterModule(
|
||||||
|
BluetoothDaemonHandsfreeModule::SERVICE_ID,
|
||||||
|
new CleanupResultHandler(mModule, aRes));
|
||||||
|
BT_LOGR("%s:%d", __func__, __LINE__);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connect / Disconnect */
|
/* Connect / Disconnect */
|
||||||
@ -1572,7 +1580,10 @@ BluetoothDaemonHandsfreeInterface::Connect(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->ConnectCmd(aBdAddr, aRes);
|
nsresult rv = mModule->ConnectCmd(aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1581,7 +1592,10 @@ BluetoothDaemonHandsfreeInterface::Disconnect(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->DisconnectCmd(aBdAddr, aRes);
|
nsresult rv = mModule->DisconnectCmd(aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1590,7 +1604,10 @@ BluetoothDaemonHandsfreeInterface::ConnectAudio(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->ConnectAudioCmd(aBdAddr, aRes);
|
nsresult rv = mModule->ConnectAudioCmd(aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1599,7 +1616,10 @@ BluetoothDaemonHandsfreeInterface::DisconnectAudio(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->DisconnectAudioCmd(aBdAddr, aRes);
|
nsresult rv = mModule->DisconnectAudioCmd(aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Voice Recognition */
|
/* Voice Recognition */
|
||||||
@ -1610,7 +1630,10 @@ BluetoothDaemonHandsfreeInterface::StartVoiceRecognition(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->StartVoiceRecognitionCmd(aBdAddr, aRes);
|
nsresult rv = mModule->StartVoiceRecognitionCmd(aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1619,7 +1642,10 @@ BluetoothDaemonHandsfreeInterface::StopVoiceRecognition(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->StopVoiceRecognitionCmd(aBdAddr, aRes);
|
nsresult rv = mModule->StopVoiceRecognitionCmd(aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Volume */
|
/* Volume */
|
||||||
@ -1631,7 +1657,10 @@ BluetoothDaemonHandsfreeInterface::VolumeControl(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->VolumeControlCmd(aType, aVolume, aBdAddr, aRes);
|
nsresult rv = mModule->VolumeControlCmd(aType, aVolume, aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Device status */
|
/* Device status */
|
||||||
@ -1644,8 +1673,12 @@ BluetoothDaemonHandsfreeInterface::DeviceStatusNotification(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->DeviceStatusNotificationCmd(aNtkState, aSvcType, aSignal,
|
nsresult rv = mModule->DeviceStatusNotificationCmd(aNtkState, aSvcType,
|
||||||
aBattChg, aRes);
|
aSignal, aBattChg,
|
||||||
|
aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responses */
|
/* Responses */
|
||||||
@ -1657,7 +1690,10 @@ BluetoothDaemonHandsfreeInterface::CopsResponse(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->CopsResponseCmd(aCops, aBdAddr, aRes);
|
nsresult rv = mModule->CopsResponseCmd(aCops, aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1669,8 +1705,12 @@ BluetoothDaemonHandsfreeInterface::CindResponse(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->CindResponseCmd(aSvc, aNumActive, aNumHeld, aCallSetupState,
|
nsresult rv = mModule->CindResponseCmd(aSvc, aNumActive, aNumHeld,
|
||||||
aSignal, aRoam, aBattChg, aBdAddr, aRes);
|
aCallSetupState, aSignal,
|
||||||
|
aRoam, aBattChg, aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1680,7 +1720,10 @@ BluetoothDaemonHandsfreeInterface::FormattedAtResponse(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->FormattedAtResponseCmd(aRsp, aBdAddr, aRes);
|
nsresult rv = mModule->FormattedAtResponseCmd(aRsp, aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1690,7 +1733,11 @@ BluetoothDaemonHandsfreeInterface::AtResponse(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->AtResponseCmd(aResponseCode, aErrorCode, aBdAddr, aRes);
|
nsresult rv = mModule->AtResponseCmd(aResponseCode, aErrorCode,
|
||||||
|
aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1706,8 +1753,11 @@ BluetoothDaemonHandsfreeInterface::ClccResponse(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->ClccResponseCmd(aIndex, aDir, aState, aMode, aMpty, aNumber,
|
nsresult rv = mModule->ClccResponseCmd(aIndex, aDir, aState, aMode, aMpty,
|
||||||
aType, aBdAddr, aRes);
|
aNumber, aType, aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Phone State */
|
/* Phone State */
|
||||||
@ -1722,8 +1772,12 @@ BluetoothDaemonHandsfreeInterface::PhoneStateChange(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->PhoneStateChangeCmd(aNumActive, aNumHeld, aCallSetupState, aNumber,
|
nsresult rv = mModule->PhoneStateChangeCmd(aNumActive, aNumHeld,
|
||||||
aType, aRes);
|
aCallSetupState, aNumber,
|
||||||
|
aType, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wide Band Speech */
|
/* Wide Band Speech */
|
||||||
@ -1735,7 +1789,10 @@ BluetoothDaemonHandsfreeInterface::ConfigureWbs(
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->ConfigureWbsCmd(aBdAddr, aConfig, aRes);
|
nsresult rv = mModule->ConfigureWbsCmd(aBdAddr, aConfig, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1748,4 +1805,16 @@ BluetoothDaemonHandsfreeInterface::DispatchError(
|
|||||||
ConstantInitOp1<BluetoothStatus>(aStatus));
|
ConstantInitOp1<BluetoothStatus>(aStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothDaemonHandsfreeInterface::DispatchError(
|
||||||
|
BluetoothHandsfreeResultHandler* aRes, nsresult aRv)
|
||||||
|
{
|
||||||
|
BluetoothStatus status;
|
||||||
|
|
||||||
|
if (NS_WARN_IF(NS_FAILED(Convert(aRv, status)))) {
|
||||||
|
status = STATUS_FAIL;
|
||||||
|
}
|
||||||
|
DispatchError(aRes, status);
|
||||||
|
}
|
||||||
|
|
||||||
END_BLUETOOTH_NAMESPACE
|
END_BLUETOOTH_NAMESPACE
|
||||||
|
@ -472,6 +472,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
void DispatchError(BluetoothHandsfreeResultHandler* aRes,
|
void DispatchError(BluetoothHandsfreeResultHandler* aRes,
|
||||||
BluetoothStatus aStatus);
|
BluetoothStatus aStatus);
|
||||||
|
void DispatchError(BluetoothHandsfreeResultHandler* aRes, nsresult aRv);
|
||||||
|
|
||||||
BluetoothDaemonHandsfreeModule* mModule;
|
BluetoothDaemonHandsfreeModule* mModule;
|
||||||
};
|
};
|
||||||
|
@ -1893,7 +1893,15 @@ void
|
|||||||
BluetoothDaemonInterface::OnDisconnect(enum Channel aChannel)
|
BluetoothDaemonInterface::OnDisconnect(enum Channel aChannel)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
MOZ_ASSERT(!mResultHandlerQ.IsEmpty());
|
|
||||||
|
if (mResultHandlerQ.IsEmpty()) {
|
||||||
|
if (sNotificationHandler) {
|
||||||
|
// Bluetooth daemon crashed; clear state
|
||||||
|
sNotificationHandler->AdapterStateChangedNotification(false);
|
||||||
|
sNotificationHandler = nullptr;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (aChannel) {
|
switch (aChannel) {
|
||||||
case CMD_CHANNEL:
|
case CMD_CHANNEL:
|
||||||
@ -2194,19 +2202,31 @@ BluetoothDaemonInterface::Cleanup(BluetoothResultHandler* aRes)
|
|||||||
mResultHandlerQ.AppendElement(aRes);
|
mResultHandlerQ.AppendElement(aRes);
|
||||||
|
|
||||||
// Cleanup, step 1: Unregister Socket module
|
// Cleanup, step 1: Unregister Socket module
|
||||||
mProtocol->UnregisterModuleCmd(0x02, new CleanupResultHandler(this));
|
nsresult rv = mProtocol->UnregisterModuleCmd(
|
||||||
|
0x02, new CleanupResultHandler(this));
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonInterface::Enable(BluetoothResultHandler* aRes)
|
BluetoothDaemonInterface::Enable(BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>(mProtocol)->EnableCmd(aRes);
|
nsresult rv =
|
||||||
|
static_cast<BluetoothDaemonCoreModule*>(mProtocol)->EnableCmd(aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonInterface::Disable(BluetoothResultHandler* aRes)
|
BluetoothDaemonInterface::Disable(BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>(mProtocol)->DisableCmd(aRes);
|
nsresult rv =
|
||||||
|
static_cast<BluetoothDaemonCoreModule*>(mProtocol)->DisableCmd(aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Adapter Properties */
|
/* Adapter Properties */
|
||||||
@ -2214,24 +2234,33 @@ BluetoothDaemonInterface::Disable(BluetoothResultHandler* aRes)
|
|||||||
void
|
void
|
||||||
BluetoothDaemonInterface::GetAdapterProperties(BluetoothResultHandler* aRes)
|
BluetoothDaemonInterface::GetAdapterProperties(BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
(mProtocol)->GetAdapterPropertiesCmd(aRes);
|
(mProtocol)->GetAdapterPropertiesCmd(aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonInterface::GetAdapterProperty(const nsAString& aName,
|
BluetoothDaemonInterface::GetAdapterProperty(const nsAString& aName,
|
||||||
BluetoothResultHandler* aRes)
|
BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
(mProtocol)->GetAdapterPropertyCmd(aName, aRes);
|
(mProtocol)->GetAdapterPropertyCmd(aName, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonInterface::SetAdapterProperty(
|
BluetoothDaemonInterface::SetAdapterProperty(
|
||||||
const BluetoothNamedValue& aProperty, BluetoothResultHandler* aRes)
|
const BluetoothNamedValue& aProperty, BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
(mProtocol)->SetAdapterPropertyCmd(aProperty, aRes);
|
(mProtocol)->SetAdapterPropertyCmd(aProperty, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remote Device Properties */
|
/* Remote Device Properties */
|
||||||
@ -2240,8 +2269,11 @@ void
|
|||||||
BluetoothDaemonInterface::GetRemoteDeviceProperties(
|
BluetoothDaemonInterface::GetRemoteDeviceProperties(
|
||||||
const nsAString& aRemoteAddr, BluetoothResultHandler* aRes)
|
const nsAString& aRemoteAddr, BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
(mProtocol)->GetRemoteDevicePropertiesCmd(aRemoteAddr, aRes);
|
(mProtocol)->GetRemoteDevicePropertiesCmd(aRemoteAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2249,8 +2281,11 @@ BluetoothDaemonInterface::GetRemoteDeviceProperty(
|
|||||||
const nsAString& aRemoteAddr, const nsAString& aName,
|
const nsAString& aRemoteAddr, const nsAString& aName,
|
||||||
BluetoothResultHandler* aRes)
|
BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
(mProtocol)->GetRemoteDevicePropertyCmd(aRemoteAddr, aName, aRes);
|
(mProtocol)->GetRemoteDevicePropertyCmd(aRemoteAddr, aName, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2258,8 +2293,11 @@ BluetoothDaemonInterface::SetRemoteDeviceProperty(
|
|||||||
const nsAString& aRemoteAddr, const BluetoothNamedValue& aProperty,
|
const nsAString& aRemoteAddr, const BluetoothNamedValue& aProperty,
|
||||||
BluetoothResultHandler* aRes)
|
BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
(mProtocol)->SetRemoteDevicePropertyCmd(aRemoteAddr, aProperty, aRes);
|
(mProtocol)->SetRemoteDevicePropertyCmd(aRemoteAddr, aProperty, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remote Services */
|
/* Remote Services */
|
||||||
@ -2269,16 +2307,22 @@ BluetoothDaemonInterface::GetRemoteServiceRecord(const nsAString& aRemoteAddr,
|
|||||||
const uint8_t aUuid[16],
|
const uint8_t aUuid[16],
|
||||||
BluetoothResultHandler* aRes)
|
BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>(
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
mProtocol)->GetRemoteServiceRecordCmd(aRemoteAddr, aUuid, aRes);
|
(mProtocol)->GetRemoteServiceRecordCmd(aRemoteAddr, aUuid, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonInterface::GetRemoteServices(const nsAString& aRemoteAddr,
|
BluetoothDaemonInterface::GetRemoteServices(const nsAString& aRemoteAddr,
|
||||||
BluetoothResultHandler* aRes)
|
BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>(
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
mProtocol)->GetRemoteServicesCmd(aRemoteAddr, aRes);
|
(mProtocol)->GetRemoteServicesCmd(aRemoteAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Discovery */
|
/* Discovery */
|
||||||
@ -2286,14 +2330,21 @@ BluetoothDaemonInterface::GetRemoteServices(const nsAString& aRemoteAddr,
|
|||||||
void
|
void
|
||||||
BluetoothDaemonInterface::StartDiscovery(BluetoothResultHandler* aRes)
|
BluetoothDaemonInterface::StartDiscovery(BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>(mProtocol)->StartDiscoveryCmd(aRes);
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
|
(mProtocol)->StartDiscoveryCmd(aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonInterface::CancelDiscovery(BluetoothResultHandler* aRes)
|
BluetoothDaemonInterface::CancelDiscovery(BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
(mProtocol)->CancelDiscoveryCmd(aRes);
|
(mProtocol)->CancelDiscoveryCmd(aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bonds */
|
/* Bonds */
|
||||||
@ -2303,24 +2354,33 @@ BluetoothDaemonInterface::CreateBond(const nsAString& aBdAddr,
|
|||||||
BluetoothTransport aTransport,
|
BluetoothTransport aTransport,
|
||||||
BluetoothResultHandler* aRes)
|
BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
(mProtocol)->CreateBondCmd(aBdAddr, aTransport, aRes);
|
(mProtocol)->CreateBondCmd(aBdAddr, aTransport, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonInterface::RemoveBond(const nsAString& aBdAddr,
|
BluetoothDaemonInterface::RemoveBond(const nsAString& aBdAddr,
|
||||||
BluetoothResultHandler* aRes)
|
BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
(mProtocol)->RemoveBondCmd(aBdAddr, aRes);
|
(mProtocol)->RemoveBondCmd(aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonInterface::CancelBond(const nsAString& aBdAddr,
|
BluetoothDaemonInterface::CancelBond(const nsAString& aBdAddr,
|
||||||
BluetoothResultHandler* aRes)
|
BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
(mProtocol)->CancelBondCmd(aBdAddr, aRes);
|
(mProtocol)->CancelBondCmd(aBdAddr, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connection */
|
/* Connection */
|
||||||
@ -2339,8 +2399,11 @@ BluetoothDaemonInterface::PinReply(const nsAString& aBdAddr, bool aAccept,
|
|||||||
const nsAString& aPinCode,
|
const nsAString& aPinCode,
|
||||||
BluetoothResultHandler* aRes)
|
BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
(mProtocol)->PinReplyCmd(aBdAddr, aAccept, aPinCode, aRes);
|
(mProtocol)->PinReplyCmd(aBdAddr, aAccept, aPinCode, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2349,8 +2412,11 @@ BluetoothDaemonInterface::SspReply(const nsAString& aBdAddr,
|
|||||||
bool aAccept, uint32_t aPasskey,
|
bool aAccept, uint32_t aPasskey,
|
||||||
BluetoothResultHandler* aRes)
|
BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
(mProtocol)->SspReplyCmd(aBdAddr, aVariant, aAccept, aPasskey, aRes);
|
(mProtocol)->SspReplyCmd(aBdAddr, aVariant, aAccept, aPasskey, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DUT Mode */
|
/* DUT Mode */
|
||||||
@ -2359,8 +2425,11 @@ void
|
|||||||
BluetoothDaemonInterface::DutModeConfigure(bool aEnable,
|
BluetoothDaemonInterface::DutModeConfigure(bool aEnable,
|
||||||
BluetoothResultHandler* aRes)
|
BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
(mProtocol)->DutModeConfigureCmd(aEnable, aRes);
|
(mProtocol)->DutModeConfigureCmd(aEnable, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2368,8 +2437,11 @@ BluetoothDaemonInterface::DutModeSend(uint16_t aOpcode, uint8_t* aBuf,
|
|||||||
uint8_t aLen,
|
uint8_t aLen,
|
||||||
BluetoothResultHandler* aRes)
|
BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
(mProtocol)->DutModeSendCmd(aOpcode, aBuf, aLen, aRes);
|
(mProtocol)->DutModeSendCmd(aOpcode, aBuf, aLen, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* LE Mode */
|
/* LE Mode */
|
||||||
@ -2379,8 +2451,11 @@ BluetoothDaemonInterface::LeTestMode(uint16_t aOpcode, uint8_t* aBuf,
|
|||||||
uint8_t aLen,
|
uint8_t aLen,
|
||||||
BluetoothResultHandler* aRes)
|
BluetoothResultHandler* aRes)
|
||||||
{
|
{
|
||||||
static_cast<BluetoothDaemonCoreModule*>
|
nsresult rv = static_cast<BluetoothDaemonCoreModule*>
|
||||||
(mProtocol)->LeTestModeCmd(aOpcode, aBuf, aLen, aRes);
|
(mProtocol)->LeTestModeCmd(aOpcode, aBuf, aLen, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Energy Information */
|
/* Energy Information */
|
||||||
@ -2401,6 +2476,18 @@ BluetoothDaemonInterface::DispatchError(BluetoothResultHandler* aRes,
|
|||||||
ConstantInitOp1<BluetoothStatus>(aStatus));
|
ConstantInitOp1<BluetoothStatus>(aStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothDaemonInterface::DispatchError(BluetoothResultHandler* aRes,
|
||||||
|
nsresult aRv)
|
||||||
|
{
|
||||||
|
BluetoothStatus status;
|
||||||
|
|
||||||
|
if (NS_WARN_IF(NS_FAILED(Convert(aRv, status)))) {
|
||||||
|
status = STATUS_FAIL;
|
||||||
|
}
|
||||||
|
DispatchError(aRes, status);
|
||||||
|
}
|
||||||
|
|
||||||
// Profile Interfaces
|
// Profile Interfaces
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@ -135,6 +135,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void DispatchError(BluetoothResultHandler* aRes, BluetoothStatus aStatus);
|
void DispatchError(BluetoothResultHandler* aRes, BluetoothStatus aStatus);
|
||||||
|
void DispatchError(BluetoothResultHandler* aRes, nsresult aRv);
|
||||||
|
|
||||||
nsCString mListenSocketName;
|
nsCString mListenSocketName;
|
||||||
nsRefPtr<BluetoothDaemonListenSocket> mListenSocket;
|
nsRefPtr<BluetoothDaemonListenSocket> mListenSocket;
|
||||||
|
@ -315,8 +315,11 @@ BluetoothDaemonSocketInterface::Listen(BluetoothSocketType aType,
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->ListenCmd(aType, aServiceName, aServiceUuid, aChannel,
|
nsresult rv = mModule->ListenCmd(aType, aServiceName, aServiceUuid,
|
||||||
aEncrypt, aAuth, aRes);
|
aChannel, aEncrypt, aAuth, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -329,7 +332,11 @@ BluetoothDaemonSocketInterface::Connect(const nsAString& aBdAddr,
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->ConnectCmd(aBdAddr, aType, aUuid, aChannel, aEncrypt, aAuth, aRes);
|
nsresult rv = mModule->ConnectCmd(aBdAddr, aType, aUuid, aChannel,
|
||||||
|
aEncrypt, aAuth, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -338,7 +345,10 @@ BluetoothDaemonSocketInterface::Accept(int aFd,
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->AcceptCmd(aFd, aRes);
|
nsresult rv = mModule->AcceptCmd(aFd, aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -346,7 +356,32 @@ BluetoothDaemonSocketInterface::Close(BluetoothSocketResultHandler* aRes)
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mModule);
|
MOZ_ASSERT(mModule);
|
||||||
|
|
||||||
mModule->CloseCmd(aRes);
|
nsresult rv = mModule->CloseCmd(aRes);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
DispatchError(aRes, rv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothDaemonSocketInterface::DispatchError(
|
||||||
|
BluetoothSocketResultHandler* aRes, BluetoothStatus aStatus)
|
||||||
|
{
|
||||||
|
BluetoothResultRunnable1<BluetoothSocketResultHandler, void,
|
||||||
|
BluetoothStatus, BluetoothStatus>::Dispatch(
|
||||||
|
aRes, &BluetoothSocketResultHandler::OnError,
|
||||||
|
ConstantInitOp1<BluetoothStatus>(aStatus));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothDaemonSocketInterface::DispatchError(
|
||||||
|
BluetoothSocketResultHandler* aRes, nsresult aRv)
|
||||||
|
{
|
||||||
|
BluetoothStatus status;
|
||||||
|
|
||||||
|
if (NS_WARN_IF(NS_FAILED(Convert(aRv, status)))) {
|
||||||
|
status = STATUS_FAIL;
|
||||||
|
}
|
||||||
|
DispatchError(aRes, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
END_BLUETOOTH_NAMESPACE
|
END_BLUETOOTH_NAMESPACE
|
||||||
|
@ -113,6 +113,10 @@ public:
|
|||||||
void Close(BluetoothSocketResultHandler* aRes);
|
void Close(BluetoothSocketResultHandler* aRes);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void DispatchError(BluetoothSocketResultHandler* aRes,
|
||||||
|
BluetoothStatus aStatus);
|
||||||
|
void DispatchError(BluetoothSocketResultHandler* aRes, nsresult aRv);
|
||||||
|
|
||||||
BluetoothDaemonSocketModule* mModule;
|
BluetoothDaemonSocketModule* mModule;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -310,7 +310,8 @@ public:
|
|||||||
|
|
||||||
BT_LOGR("BluetoothInterface::Disable failed: %d", aStatus);
|
BT_LOGR("BluetoothInterface::Disable failed: %d", aStatus);
|
||||||
|
|
||||||
BluetoothService::AcknowledgeToggleBt(true);
|
// Always make progress; even on failures
|
||||||
|
BluetoothService::AcknowledgeToggleBt(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -432,6 +432,9 @@ public:
|
|||||||
void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
|
void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
|
||||||
{
|
{
|
||||||
BT_WARNING("BluetoothHandsfreeInterface::Cleanup failed: %d", (int)aStatus);
|
BT_WARNING("BluetoothHandsfreeInterface::Cleanup failed: %d", (int)aStatus);
|
||||||
|
|
||||||
|
sBluetoothHfpInterface = nullptr;
|
||||||
|
|
||||||
if (mRes) {
|
if (mRes) {
|
||||||
mRes->OnError(NS_ERROR_FAILURE);
|
mRes->OnError(NS_ERROR_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ if CONFIG['MOZ_B2G_BT']:
|
|||||||
'BluetoothDevice.cpp',
|
'BluetoothDevice.cpp',
|
||||||
'BluetoothHidManager.cpp',
|
'BluetoothHidManager.cpp',
|
||||||
'BluetoothInterface.cpp',
|
'BluetoothInterface.cpp',
|
||||||
|
'BluetoothInterfaceHelpers.cpp',
|
||||||
'BluetoothManager.cpp',
|
'BluetoothManager.cpp',
|
||||||
'BluetoothProfileController.cpp',
|
'BluetoothProfileController.cpp',
|
||||||
'BluetoothPropertyContainer.cpp',
|
'BluetoothPropertyContainer.cpp',
|
||||||
|
@ -42,6 +42,8 @@ static const char *sEGLExtensionNames[] = {
|
|||||||
|
|
||||||
static PRLibrary* LoadApitraceLibrary()
|
static PRLibrary* LoadApitraceLibrary()
|
||||||
{
|
{
|
||||||
|
// Initialization of gfx prefs here is only needed during the unit tests...
|
||||||
|
gfxPrefs::GetSingleton();
|
||||||
if (!gfxPrefs::UseApitrace()) {
|
if (!gfxPrefs::UseApitrace()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -391,7 +391,7 @@ pref("devtools.errorconsole.enabled", false);
|
|||||||
// to communicate with a usb cable via adb forward.
|
// to communicate with a usb cable via adb forward.
|
||||||
pref("devtools.debugger.unix-domain-socket", "/data/data/@ANDROID_PACKAGE_NAME@/firefox-debugger-socket");
|
pref("devtools.debugger.unix-domain-socket", "/data/data/@ANDROID_PACKAGE_NAME@/firefox-debugger-socket");
|
||||||
|
|
||||||
pref("font.size.inflation.minTwips", 120);
|
pref("font.size.inflation.minTwips", 0);
|
||||||
|
|
||||||
// When true, zooming will be enabled on all sites, even ones that declare user-scalable=no.
|
// When true, zooming will be enabled on all sites, even ones that declare user-scalable=no.
|
||||||
pref("browser.ui.zoom.force-user-scalable", false);
|
pref("browser.ui.zoom.force-user-scalable", false);
|
||||||
|
@ -45,17 +45,19 @@ public class ReferrerReceiver extends BroadcastReceiver {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track the referrer object for distribution handling.
|
||||||
ReferrerDescriptor referrer = new ReferrerDescriptor(intent.getStringExtra("referrer"));
|
ReferrerDescriptor referrer = new ReferrerDescriptor(intent.getStringExtra("referrer"));
|
||||||
|
|
||||||
// Track the referrer object for distribution handling.
|
if (!TextUtils.equals(referrer.source, MOZILLA_UTM_SOURCE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (TextUtils.equals(referrer.campaign, DISTRIBUTION_UTM_CAMPAIGN)) {
|
if (TextUtils.equals(referrer.campaign, DISTRIBUTION_UTM_CAMPAIGN)) {
|
||||||
Distribution.onReceivedReferrer(context, referrer);
|
Distribution.onReceivedReferrer(context, referrer);
|
||||||
} else {
|
} else {
|
||||||
Log.d(LOGTAG, "Not downloading distribution: non-matching campaign.");
|
Log.d(LOGTAG, "Not downloading distribution: non-matching campaign.");
|
||||||
}
|
// If this is a Mozilla campaign, pass the campaign along to Gecko.
|
||||||
|
// It'll pretend to be a "playstore" distribution for BLP purposes.
|
||||||
// If this is a Mozilla campaign, pass the campaign along to Gecko.
|
|
||||||
if (TextUtils.equals(referrer.source, MOZILLA_UTM_SOURCE)) {
|
|
||||||
propagateMozillaCampaign(referrer);
|
propagateMozillaCampaign(referrer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ public class ActivityUtils {
|
|||||||
// Hide/show the system notification bar
|
// Hide/show the system notification bar
|
||||||
Window window = activity.getWindow();
|
Window window = activity.getWindow();
|
||||||
|
|
||||||
if (Versions.feature11Plus) {
|
if (Versions.feature16Plus) {
|
||||||
final int newVis;
|
final int newVis;
|
||||||
if (fullscreen) {
|
if (fullscreen) {
|
||||||
newVis = View.SYSTEM_UI_FLAG_FULLSCREEN |
|
newVis = View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||||
@ -40,12 +40,12 @@ public class ActivityUtils {
|
|||||||
public static boolean isFullScreen(final Activity activity) {
|
public static boolean isFullScreen(final Activity activity) {
|
||||||
final Window window = activity.getWindow();
|
final Window window = activity.getWindow();
|
||||||
|
|
||||||
if (Versions.feature11Plus) {
|
if (Versions.feature16Plus) {
|
||||||
final int vis = window.getDecorView().getSystemUiVisibility();
|
final int vis = window.getDecorView().getSystemUiVisibility();
|
||||||
return (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
|
return (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
|
||||||
} else {
|
|
||||||
final int flags = window.getAttributes().flags;
|
|
||||||
return ((flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final int flags = window.getAttributes().flags;
|
||||||
|
return ((flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -626,6 +626,17 @@ var BrowserApp = {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
NativeWindow.contextmenus.add(stringGetter("contextmenu.addToReadingList"),
|
||||||
|
NativeWindow.contextmenus.linkOpenableContext,
|
||||||
|
function(aTarget) {
|
||||||
|
let url = NativeWindow.contextmenus._getLinkURL(aTarget);
|
||||||
|
Messaging.sendRequestForResult({
|
||||||
|
type: "Reader:AddToList",
|
||||||
|
title: truncate(url, MAX_TITLE_LENGTH),
|
||||||
|
url: truncate(url, MAX_URI_LENGTH),
|
||||||
|
}).catch(Cu.reportError);
|
||||||
|
});
|
||||||
|
|
||||||
NativeWindow.contextmenus.add(stringGetter("contextmenu.copyLink"),
|
NativeWindow.contextmenus.add(stringGetter("contextmenu.copyLink"),
|
||||||
NativeWindow.contextmenus.linkCopyableContext,
|
NativeWindow.contextmenus.linkCopyableContext,
|
||||||
function(aTarget) {
|
function(aTarget) {
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
"use strict;"
|
||||||
|
|
||||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, 'Services',
|
XPCOMUtils.defineLazyModuleGetter(this, "Services",
|
||||||
'resource://gre/modules/Services.jsm');
|
"resource://gre/modules/Services.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, 'Preferences',
|
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
|
||||||
'resource://gre/modules/Preferences.jsm');
|
"resource://gre/modules/FileUtils.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, 'FileUtils',
|
XPCOMUtils.defineLazyModuleGetter(this, "Log",
|
||||||
'resource://gre/modules/FileUtils.jsm');
|
"resource://gre/modules/Log.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, 'Log',
|
XPCOMUtils.defineLazyModuleGetter(this, "OS",
|
||||||
'resource://gre/modules/Log.jsm');
|
"resource://gre/modules/osfile.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, 'Task',
|
XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils",
|
||||||
'resource://gre/modules/Task.jsm');
|
"resource://services-common/utils.js");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, 'OS',
|
|
||||||
'resource://gre/modules/osfile.jsm');
|
Cu.import("resource://gre/modules/Preferences.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, 'CommonUtils',
|
Cu.import("resource://gre/modules/Task.jsm");
|
||||||
'resource://services-common/utils.js');
|
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = [
|
this.EXPORTED_SYMBOLS = [
|
||||||
"LogManager",
|
"LogManager",
|
||||||
@ -28,7 +28,7 @@ const DEFAULT_MAX_ERROR_AGE = 20 * 24 * 60 * 60; // 20 days
|
|||||||
|
|
||||||
// "shared" logs (ie, where the same log name is used by multiple LogManager
|
// "shared" logs (ie, where the same log name is used by multiple LogManager
|
||||||
// instances) are a fact of life here - eg, FirefoxAccounts logs are used by
|
// instances) are a fact of life here - eg, FirefoxAccounts logs are used by
|
||||||
// both Sync and Reading-list.
|
// both Sync and Reading List.
|
||||||
// However, different instances have different pref branches, so we need to
|
// However, different instances have different pref branches, so we need to
|
||||||
// handle when one pref branch says "Debug" and the other says "Error"
|
// handle when one pref branch says "Debug" and the other says "Error"
|
||||||
// So we (a) keep singleton console and dump appenders and (b) keep track
|
// So we (a) keep singleton console and dump appenders and (b) keep track
|
||||||
@ -103,7 +103,7 @@ LogManager.prototype = {
|
|||||||
|
|
||||||
// The file appender doesn't get the special singleton behaviour.
|
// The file appender doesn't get the special singleton behaviour.
|
||||||
let fapp = this._fileAppender = new Log.StorageStreamAppender(formatter);
|
let fapp = this._fileAppender = new Log.StorageStreamAppender(formatter);
|
||||||
// the stream gets a default of Debug as the user must go out of there way
|
// the stream gets a default of Debug as the user must go out of their way
|
||||||
// to see the stuff spewed to it.
|
// to see the stuff spewed to it.
|
||||||
this._observeStreamPref = setupAppender(fapp, "log.appender.file.level", Log.Level.Debug);
|
this._observeStreamPref = setupAppender(fapp, "log.appender.file.level", Log.Level.Debug);
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ LogManager.prototype = {
|
|||||||
const BUFFER_SIZE = 8192;
|
const BUFFER_SIZE = 8192;
|
||||||
|
|
||||||
// get a binary stream
|
// get a binary stream
|
||||||
let binaryStream = Cc['@mozilla.org/binaryinputstream;1'].createInstance(Ci.nsIBinaryInputStream);
|
let binaryStream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);
|
||||||
binaryStream.setInputStream(inputStream);
|
binaryStream.setInputStream(inputStream);
|
||||||
yield OS.File.makeDir(outputFile.parent.path, { ignoreExisting: true });
|
yield OS.File.makeDir(outputFile.parent.path, { ignoreExisting: true });
|
||||||
let output = yield OS.File.open(outputFile.path, { write: true} );
|
let output = yield OS.File.open(outputFile.path, { write: true} );
|
||||||
@ -165,12 +165,14 @@ LogManager.prototype = {
|
|||||||
yield output.write(new Uint8Array(chunk));
|
yield output.write(new Uint8Array(chunk));
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
inputStream.close();
|
try {
|
||||||
binaryStream.close();
|
binaryStream.close(); // inputStream is closed by the binaryStream
|
||||||
yield output.close();
|
yield output.close();
|
||||||
|
} catch (ex) {
|
||||||
|
this._log.error("Failed to close the input stream", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this._log.trace("finished copy to", outputFile.path);
|
this._log.trace("finished copy to", outputFile.path);
|
||||||
return (yield OS.File.stat(outputFile.path)).lastModificationDate;
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -179,70 +181,65 @@ LogManager.prototype = {
|
|||||||
* Returns a promise that resolves on completion or rejects if the file could
|
* Returns a promise that resolves on completion or rejects if the file could
|
||||||
* not be written.
|
* not be written.
|
||||||
*/
|
*/
|
||||||
resetFileLog(reason) {
|
resetFileLog: Task.async(function* (reason) {
|
||||||
return new Promise((resolve, reject) => {
|
try {
|
||||||
try {
|
let flushToFile;
|
||||||
let flushToFile;
|
let reasonPrefix;
|
||||||
let reasonPrefix;
|
switch (reason) {
|
||||||
switch (reason) {
|
case this.REASON_SUCCESS:
|
||||||
case this.REASON_SUCCESS:
|
flushToFile = this._prefs.get("log.appender.file.logOnSuccess", false);
|
||||||
flushToFile = this._prefs.get("log.appender.file.logOnSuccess");
|
reasonPrefix = "success";
|
||||||
reasonPrefix = "success";
|
break;
|
||||||
break;
|
case this.REASON_ERROR:
|
||||||
case this.REASON_ERROR:
|
flushToFile = this._prefs.get("log.appender.file.logOnError", true);
|
||||||
flushToFile = this._prefs.get("log.appender.file.logOnError");
|
reasonPrefix = "error";
|
||||||
reasonPrefix = "error";
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
throw new Error("Invalid reason");
|
||||||
return reject(new Error("Invalid reason"));
|
|
||||||
}
|
|
||||||
|
|
||||||
let inStream = this._fileAppender.getInputStream();
|
|
||||||
this._fileAppender.reset();
|
|
||||||
if (flushToFile && inStream) {
|
|
||||||
this._log.debug("Flushing file log");
|
|
||||||
let filename = this.logFilePrefix + "-" + reasonPrefix + "-" + Date.now() + ".txt";
|
|
||||||
let file = this._logFileDirectory;
|
|
||||||
file.append(filename);
|
|
||||||
this._log.trace("Beginning stream copy to " + file.leafName + ": " +
|
|
||||||
Date.now());
|
|
||||||
this._copyStreamToFile(inStream, file).then(
|
|
||||||
modDate => {
|
|
||||||
this._log.trace("onCopyComplete: " + Date.now());
|
|
||||||
this._log.trace("Output file timestamp: " + modDate + " (" + modDate.getTime() + ")");
|
|
||||||
},
|
|
||||||
err => {
|
|
||||||
this._log.error("Failed to copy log stream to file", err)
|
|
||||||
reject(err)
|
|
||||||
}
|
|
||||||
).then(
|
|
||||||
() => {
|
|
||||||
// It's not completely clear to markh why we only do log cleanups
|
|
||||||
// for errors, but for now the Sync semantics have been copied...
|
|
||||||
// (one theory is that only cleaning up on error makes it less
|
|
||||||
// likely old error logs would be removed, but that's not true if
|
|
||||||
// there are occasional errors - let's address this later!)
|
|
||||||
if (reason == this.REASON_ERROR &&
|
|
||||||
!this._cleaningUpFileLogs) {
|
|
||||||
this._log.trace("Scheduling cleanup.");
|
|
||||||
// Note we don't return or wait on this promise - it continues
|
|
||||||
// in the background
|
|
||||||
this.cleanupLogs().then(null, err => {
|
|
||||||
this._log.error("Failed to cleanup logs", err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
} catch (ex) {
|
|
||||||
this._log.error("Failed to resetFileLog", ex)
|
|
||||||
reject(ex);
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
},
|
// might as well avoid creating an input stream if we aren't going to use it.
|
||||||
|
if (!flushToFile) {
|
||||||
|
this._fileAppender.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let inStream = this._fileAppender.getInputStream();
|
||||||
|
this._fileAppender.reset();
|
||||||
|
if (inStream) {
|
||||||
|
this._log.debug("Flushing file log");
|
||||||
|
// We have reasonPrefix at the start of the filename so all "error"
|
||||||
|
// logs are grouped in about:sync-log.
|
||||||
|
let filename = reasonPrefix + "-" + this.logFilePrefix + "-" + Date.now() + ".txt";
|
||||||
|
let file = this._logFileDirectory;
|
||||||
|
file.append(filename);
|
||||||
|
this._log.trace("Beginning stream copy to " + file.leafName + ": " +
|
||||||
|
Date.now());
|
||||||
|
try {
|
||||||
|
yield this._copyStreamToFile(inStream, file);
|
||||||
|
this._log.trace("onCopyComplete", Date.now());
|
||||||
|
} catch (ex) {
|
||||||
|
this._log.error("Failed to copy log stream to file", ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// It's not completely clear to markh why we only do log cleanups
|
||||||
|
// for errors, but for now the Sync semantics have been copied...
|
||||||
|
// (one theory is that only cleaning up on error makes it less
|
||||||
|
// likely old error logs would be removed, but that's not true if
|
||||||
|
// there are occasional errors - let's address this later!)
|
||||||
|
if (reason == this.REASON_ERROR && !this._cleaningUpFileLogs) {
|
||||||
|
this._log.trace("Scheduling cleanup.");
|
||||||
|
// Note we don't return/yield or otherwise wait on this promise - it
|
||||||
|
// continues in the background
|
||||||
|
this.cleanupLogs().catch(err => {
|
||||||
|
this._log.error("Failed to cleanup logs", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ex) {
|
||||||
|
this._log.error("Failed to resetFileLog", ex)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds all logs older than maxErrorAge and deletes them using async I/O.
|
* Finds all logs older than maxErrorAge and deletes them using async I/O.
|
||||||
@ -255,7 +252,8 @@ LogManager.prototype = {
|
|||||||
|
|
||||||
this._log.debug("Log cleanup threshold time: " + threshold);
|
this._log.debug("Log cleanup threshold time: " + threshold);
|
||||||
yield iterator.forEach(Task.async(function* (entry) {
|
yield iterator.forEach(Task.async(function* (entry) {
|
||||||
if (!entry.name.startsWith(this.logFilePrefix + "-")) {
|
if (!entry.name.startsWith("error-" + this.logFilePrefix + "-") &&
|
||||||
|
!entry.name.startsWith("success-" + this.logFilePrefix + "-")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -23,7 +23,7 @@ function getAppenders(log) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test that the correct thing happens when no prefs exist for the log manager.
|
// Test that the correct thing happens when no prefs exist for the log manager.
|
||||||
add_test(function test_noPrefs() {
|
add_task(function* test_noPrefs() {
|
||||||
// tell the log manager to init with a pref branch that doesn't exist.
|
// tell the log manager to init with a pref branch that doesn't exist.
|
||||||
let lm = new LogManager("no-such-branch.", ["TestLog"], "test");
|
let lm = new LogManager("no-such-branch.", ["TestLog"], "test");
|
||||||
|
|
||||||
@ -36,11 +36,10 @@ add_test(function test_noPrefs() {
|
|||||||
equal(fapps.length, 1, "only 1 file appender");
|
equal(fapps.length, 1, "only 1 file appender");
|
||||||
equal(fapps[0].level, Log.Level.Debug);
|
equal(fapps[0].level, Log.Level.Debug);
|
||||||
lm.finalize();
|
lm.finalize();
|
||||||
run_next_test();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test that changes to the prefs used by the log manager are updated dynamically.
|
// Test that changes to the prefs used by the log manager are updated dynamically.
|
||||||
add_test(function test_PrefChanges() {
|
add_task(function* test_PrefChanges() {
|
||||||
Services.prefs.setCharPref("log-manager.test.log.appender.console", "Trace");
|
Services.prefs.setCharPref("log-manager.test.log.appender.console", "Trace");
|
||||||
Services.prefs.setCharPref("log-manager.test.log.appender.dump", "Trace");
|
Services.prefs.setCharPref("log-manager.test.log.appender.dump", "Trace");
|
||||||
Services.prefs.setCharPref("log-manager.test.log.appender.file.level", "Trace");
|
Services.prefs.setCharPref("log-manager.test.log.appender.file.level", "Trace");
|
||||||
@ -66,11 +65,10 @@ add_test(function test_PrefChanges() {
|
|||||||
equal(dapp.level, Log.Level.Error);
|
equal(dapp.level, Log.Level.Error);
|
||||||
equal(fapp.level, Log.Level.Debug);
|
equal(fapp.level, Log.Level.Debug);
|
||||||
lm.finalize();
|
lm.finalize();
|
||||||
run_next_test();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test that the same log used by multiple log managers does the right thing.
|
// Test that the same log used by multiple log managers does the right thing.
|
||||||
add_test(function test_SharedLogs() {
|
add_task(function* test_SharedLogs() {
|
||||||
// create the prefs for the first instance.
|
// create the prefs for the first instance.
|
||||||
Services.prefs.setCharPref("log-manager-1.test.log.appender.console", "Trace");
|
Services.prefs.setCharPref("log-manager-1.test.log.appender.console", "Trace");
|
||||||
Services.prefs.setCharPref("log-manager-1.test.log.appender.dump", "Trace");
|
Services.prefs.setCharPref("log-manager-1.test.log.appender.dump", "Trace");
|
||||||
@ -102,6 +100,4 @@ add_test(function test_SharedLogs() {
|
|||||||
|
|
||||||
lm1.finalize();
|
lm1.finalize();
|
||||||
lm2.finalize();
|
lm2.finalize();
|
||||||
|
|
||||||
run_next_test();
|
|
||||||
});
|
});
|
||||||
|
@ -617,7 +617,7 @@ this.BrowserIDManager.prototype = {
|
|||||||
// that there is no authentication dance still under way.
|
// that there is no authentication dance still under way.
|
||||||
this._shouldHaveSyncKeyBundle = true;
|
this._shouldHaveSyncKeyBundle = true;
|
||||||
Weave.Status.login = this._authFailureReason;
|
Weave.Status.login = this._authFailureReason;
|
||||||
Services.obs.notifyObservers(null, "weave:service:login:error", null);
|
Services.obs.notifyObservers(null, "weave:ui:login:error", null);
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1770,7 +1770,7 @@ add_task(function test_sync_engine_generic_fail() {
|
|||||||
let entries = logsdir.directoryEntries;
|
let entries = logsdir.directoryEntries;
|
||||||
do_check_true(entries.hasMoreElements());
|
do_check_true(entries.hasMoreElements());
|
||||||
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
||||||
do_check_true(logfile.leafName.startsWith("sync-error-"), logfile.leafName);
|
do_check_true(logfile.leafName.startsWith("error-sync-"), logfile.leafName);
|
||||||
|
|
||||||
clean();
|
clean();
|
||||||
server.stop(deferred.resolve);
|
server.stop(deferred.resolve);
|
||||||
@ -1801,7 +1801,7 @@ add_test(function test_logs_on_sync_error_despite_shouldReportError() {
|
|||||||
let entries = logsdir.directoryEntries;
|
let entries = logsdir.directoryEntries;
|
||||||
do_check_true(entries.hasMoreElements());
|
do_check_true(entries.hasMoreElements());
|
||||||
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
||||||
do_check_true(logfile.leafName.startsWith("sync-error-"), logfile.leafName);
|
do_check_true(logfile.leafName.startsWith("error-sync-"), logfile.leafName);
|
||||||
|
|
||||||
clean();
|
clean();
|
||||||
run_next_test();
|
run_next_test();
|
||||||
@ -1828,7 +1828,7 @@ add_test(function test_logs_on_login_error_despite_shouldReportError() {
|
|||||||
let entries = logsdir.directoryEntries;
|
let entries = logsdir.directoryEntries;
|
||||||
do_check_true(entries.hasMoreElements());
|
do_check_true(entries.hasMoreElements());
|
||||||
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
||||||
do_check_true(logfile.leafName.startsWith("sync-error-"), logfile.leafName);
|
do_check_true(logfile.leafName.startsWith("error-sync-"), logfile.leafName);
|
||||||
|
|
||||||
clean();
|
clean();
|
||||||
run_next_test();
|
run_next_test();
|
||||||
@ -1862,7 +1862,7 @@ add_task(function test_engine_applyFailed() {
|
|||||||
let entries = logsdir.directoryEntries;
|
let entries = logsdir.directoryEntries;
|
||||||
do_check_true(entries.hasMoreElements());
|
do_check_true(entries.hasMoreElements());
|
||||||
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
||||||
do_check_true(logfile.leafName.startsWith("sync-error-"), logfile.leafName);
|
do_check_true(logfile.leafName.startsWith("error-sync-"), logfile.leafName);
|
||||||
|
|
||||||
clean();
|
clean();
|
||||||
server.stop(deferred.resolve);
|
server.stop(deferred.resolve);
|
||||||
|
@ -108,7 +108,7 @@ add_test(function test_logOnSuccess_true() {
|
|||||||
do_check_true(entries.hasMoreElements());
|
do_check_true(entries.hasMoreElements());
|
||||||
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
||||||
do_check_eq(logfile.leafName.slice(-4), ".txt");
|
do_check_eq(logfile.leafName.slice(-4), ".txt");
|
||||||
do_check_true(logfile.leafName.startsWith("sync-success-"), logfile.leafName);
|
do_check_true(logfile.leafName.startsWith("success-sync-"), logfile.leafName);
|
||||||
do_check_false(entries.hasMoreElements());
|
do_check_false(entries.hasMoreElements());
|
||||||
|
|
||||||
// Ensure the log message was actually written to file.
|
// Ensure the log message was actually written to file.
|
||||||
@ -175,7 +175,7 @@ add_test(function test_sync_error_logOnError_true() {
|
|||||||
do_check_true(entries.hasMoreElements());
|
do_check_true(entries.hasMoreElements());
|
||||||
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
||||||
do_check_eq(logfile.leafName.slice(-4), ".txt");
|
do_check_eq(logfile.leafName.slice(-4), ".txt");
|
||||||
do_check_true(logfile.leafName.startsWith("sync-error-"), logfile.leafName);
|
do_check_true(logfile.leafName.startsWith("error-sync-"), logfile.leafName);
|
||||||
do_check_false(entries.hasMoreElements());
|
do_check_false(entries.hasMoreElements());
|
||||||
|
|
||||||
// Ensure the log message was actually written to file.
|
// Ensure the log message was actually written to file.
|
||||||
@ -242,7 +242,7 @@ add_test(function test_login_error_logOnError_true() {
|
|||||||
do_check_true(entries.hasMoreElements());
|
do_check_true(entries.hasMoreElements());
|
||||||
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
|
||||||
do_check_eq(logfile.leafName.slice(-4), ".txt");
|
do_check_eq(logfile.leafName.slice(-4), ".txt");
|
||||||
do_check_true(logfile.leafName.startsWith("sync-error-"), logfile.leafName);
|
do_check_true(logfile.leafName.startsWith("error-sync-"), logfile.leafName);
|
||||||
do_check_false(entries.hasMoreElements());
|
do_check_false(entries.hasMoreElements());
|
||||||
|
|
||||||
// Ensure the log message was actually written to file.
|
// Ensure the log message was actually written to file.
|
||||||
@ -281,7 +281,7 @@ add_test(function test_logErrorCleanup_age() {
|
|||||||
_("Making some files.");
|
_("Making some files.");
|
||||||
for (let i = 0; i < numLogs; i++) {
|
for (let i = 0; i < numLogs; i++) {
|
||||||
let now = Date.now();
|
let now = Date.now();
|
||||||
let filename = "sync-error-" + now + "" + i + ".txt";
|
let filename = "error-sync-" + now + "" + i + ".txt";
|
||||||
let newLog = FileUtils.getFile("ProfD", ["weave", "logs", filename]);
|
let newLog = FileUtils.getFile("ProfD", ["weave", "logs", filename]);
|
||||||
let foStream = FileUtils.openFileOutputStream(newLog);
|
let foStream = FileUtils.openFileOutputStream(newLog);
|
||||||
foStream.write(errString, errString.length);
|
foStream.write(errString, errString.length);
|
||||||
|
35
testing/taskcluster/tasks/branches/b2g-inbound/job_flags.yml
Normal file
35
testing/taskcluster/tasks/branches/b2g-inbound/job_flags.yml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
# For complete sample of all build and test jobs,
|
||||||
|
# see <gecko>/testing/taskcluster/tasks/job_flags.yml
|
||||||
|
|
||||||
|
$inherits:
|
||||||
|
from: tasks/branches/base_job_flags.yml
|
||||||
|
|
||||||
|
builds:
|
||||||
|
flame-kk:
|
||||||
|
platforms:
|
||||||
|
- b2g
|
||||||
|
types:
|
||||||
|
opt:
|
||||||
|
task: tasks/builds/b2g_flame_kk_opt.yml
|
||||||
|
flame-kk-eng:
|
||||||
|
platforms:
|
||||||
|
- b2g
|
||||||
|
types:
|
||||||
|
opt:
|
||||||
|
task: tasks/builds/b2g_flame_kk_eng.yml
|
||||||
|
|
||||||
|
tests:
|
||||||
|
gaia-build:
|
||||||
|
allowed_build_tasks:
|
||||||
|
tasks/builds/b2g_flame_kk_opt.yml:
|
||||||
|
task: tasks/tests/b2g_build_test.yml
|
||||||
|
tasks/builds/b2g_flame_kk_eng.yml:
|
||||||
|
task: tasks/tests/b2g_build_test.yml
|
||||||
|
gaia-linter:
|
||||||
|
allowed_build_tasks:
|
||||||
|
tasks/builds/b2g_flame_kk_opt.yml:
|
||||||
|
task: tasks/tests/b2g_linter.yml
|
||||||
|
tasks/builds/b2g_flame_kk_eng.yml:
|
||||||
|
task: tasks/tests/b2g_linter.yml
|
||||||
|
|
35
testing/taskcluster/tasks/branches/cypress/job_flags.yml
Normal file
35
testing/taskcluster/tasks/branches/cypress/job_flags.yml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
---
|
||||||
|
# For complete sample of all build and test jobs,
|
||||||
|
# see <gecko>/testing/taskcluster/tasks/job_flags.yml
|
||||||
|
|
||||||
|
$inherits:
|
||||||
|
from: tasks/branches/base_job_flags.yml
|
||||||
|
|
||||||
|
builds:
|
||||||
|
flame-kk:
|
||||||
|
platforms:
|
||||||
|
- b2g
|
||||||
|
types:
|
||||||
|
opt:
|
||||||
|
task: tasks/builds/b2g_flame_kk_opt.yml
|
||||||
|
flame-kk-eng:
|
||||||
|
platforms:
|
||||||
|
- b2g
|
||||||
|
types:
|
||||||
|
opt:
|
||||||
|
task: tasks/builds/b2g_flame_kk_eng.yml
|
||||||
|
|
||||||
|
tests:
|
||||||
|
gaia-build:
|
||||||
|
allowed_build_tasks:
|
||||||
|
tasks/builds/b2g_flame_kk_opt.yml:
|
||||||
|
task: tasks/tests/b2g_build_test.yml
|
||||||
|
tasks/builds/b2g_flame_kk_eng.yml:
|
||||||
|
task: tasks/tests/b2g_build_test.yml
|
||||||
|
gaia-linter:
|
||||||
|
allowed_build_tasks:
|
||||||
|
tasks/builds/b2g_flame_kk_opt.yml:
|
||||||
|
task: tasks/tests/b2g_linter.yml
|
||||||
|
tasks/builds/b2g_flame_kk_eng.yml:
|
||||||
|
task: tasks/tests/b2g_linter.yml
|
||||||
|
|
@ -104,11 +104,11 @@ let StyleSheetsActor = exports.StyleSheetsActor = protocol.ActorClass({
|
|||||||
let actors = [];
|
let actors = [];
|
||||||
|
|
||||||
for (let doc of documents) {
|
for (let doc of documents) {
|
||||||
let sheets = yield this._addStyleSheets(doc.styleSheets);
|
let sheets = yield this._addStyleSheets(doc);
|
||||||
actors = actors.concat(sheets);
|
actors = actors.concat(sheets);
|
||||||
|
|
||||||
// Recursively handle style sheets of the documents in iframes.
|
// Recursively handle style sheets of the documents in iframes.
|
||||||
for (let iframe of doc.getElementsByTagName("iframe")) {
|
for (let iframe of doc.querySelectorAll("iframe, browser, frame")) {
|
||||||
if (iframe.contentDocument) {
|
if (iframe.contentDocument) {
|
||||||
// Sometimes, iframes don't have any document, like the
|
// Sometimes, iframes don't have any document, like the
|
||||||
// one that are over deeply nested (bug 285395)
|
// one that are over deeply nested (bug 285395)
|
||||||
@ -121,25 +121,54 @@ let StyleSheetsActor = exports.StyleSheetsActor = protocol.ActorClass({
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add all the stylesheets to the map and create an actor for each one
|
* Check if we should be showing this stylesheet.
|
||||||
* if not already created.
|
|
||||||
*
|
*
|
||||||
* @param {[DOMStyleSheet]} styleSheets
|
* @param {Document} doc
|
||||||
* Stylesheets to add
|
* Document for which we're checking
|
||||||
|
* @param {DOMCSSStyleSheet} sheet
|
||||||
|
* Stylesheet we're interested in
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
* Whether the stylesheet should be listed.
|
||||||
|
*/
|
||||||
|
_shouldListSheet: function(doc, sheet) {
|
||||||
|
// Special case about:PreferenceStyleSheet, as it is generated on the
|
||||||
|
// fly and the URI is not registered with the about: handler.
|
||||||
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=935803#c37
|
||||||
|
if (sheet.href && sheet.href.toLowerCase() == "about:preferencestylesheet") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all the stylesheets for this document to the map and create an actor
|
||||||
|
* for each one if not already created.
|
||||||
|
*
|
||||||
|
* @param {Document} doc
|
||||||
|
* Document for which to add stylesheets
|
||||||
*
|
*
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
* Promise that resolves to an array of StyleSheetActors
|
* Promise that resolves to an array of StyleSheetActors
|
||||||
*/
|
*/
|
||||||
_addStyleSheets: function(styleSheets)
|
_addStyleSheets: function(doc)
|
||||||
{
|
{
|
||||||
return Task.spawn(function*() {
|
return Task.spawn(function*() {
|
||||||
|
let isChrome = Services.scriptSecurityManager.isSystemPrincipal(doc.nodePrincipal);
|
||||||
|
let styleSheets = isChrome ? DOMUtils.getAllStyleSheets(doc) : doc.styleSheets;
|
||||||
let actors = [];
|
let actors = [];
|
||||||
for (let i = 0; i < styleSheets.length; i++) {
|
for (let i = 0; i < styleSheets.length; i++) {
|
||||||
let actor = this.parentActor.createStyleSheetActor(styleSheets[i]);
|
let sheet = styleSheets[i];
|
||||||
|
if (!this._shouldListSheet(doc, sheet)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let actor = this.parentActor.createStyleSheetActor(sheet);
|
||||||
actors.push(actor);
|
actors.push(actor);
|
||||||
|
|
||||||
// Get all sheets, including imported ones
|
// Get all sheets, including imported ones
|
||||||
let imports = yield this._getImported(actor);
|
let imports = yield this._getImported(doc, actor);
|
||||||
actors = actors.concat(imports);
|
actors = actors.concat(imports);
|
||||||
}
|
}
|
||||||
return actors;
|
return actors;
|
||||||
@ -149,12 +178,14 @@ let StyleSheetsActor = exports.StyleSheetsActor = protocol.ActorClass({
|
|||||||
/**
|
/**
|
||||||
* Get all the stylesheets @imported from a stylesheet.
|
* Get all the stylesheets @imported from a stylesheet.
|
||||||
*
|
*
|
||||||
|
* @param {Document} doc
|
||||||
|
* The document including the stylesheet
|
||||||
* @param {DOMStyleSheet} styleSheet
|
* @param {DOMStyleSheet} styleSheet
|
||||||
* Style sheet to search
|
* Style sheet to search
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
* A promise that resolves with an array of StyleSheetActors
|
* A promise that resolves with an array of StyleSheetActors
|
||||||
*/
|
*/
|
||||||
_getImported: function(styleSheet) {
|
_getImported: function(doc, styleSheet) {
|
||||||
return Task.spawn(function*() {
|
return Task.spawn(function*() {
|
||||||
let rules = yield styleSheet.getCSSRules();
|
let rules = yield styleSheet.getCSSRules();
|
||||||
let imported = [];
|
let imported = [];
|
||||||
@ -164,14 +195,14 @@ let StyleSheetsActor = exports.StyleSheetsActor = protocol.ActorClass({
|
|||||||
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
|
// Associated styleSheet may be null if it has already been seen due
|
||||||
// to duplicate @imports for the same URL.
|
// to duplicate @imports for the same URL.
|
||||||
if (!rule.styleSheet) {
|
if (!rule.styleSheet || !this._shouldListSheet(doc, rule.styleSheet)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let actor = this.parentActor.createStyleSheetActor(rule.styleSheet);
|
let actor = this.parentActor.createStyleSheetActor(rule.styleSheet);
|
||||||
imported.push(actor);
|
imported.push(actor);
|
||||||
|
|
||||||
// recurse imports in this stylesheet as well
|
// recurse imports in this stylesheet as well
|
||||||
let children = yield this._getImported(actor);
|
let children = yield this._getImported(doc, actor);
|
||||||
imported = imported.concat(children);
|
imported = imported.concat(children);
|
||||||
}
|
}
|
||||||
else if (rule.type != Ci.nsIDOMCSSRule.CHARSET_RULE) {
|
else if (rule.type != Ci.nsIDOMCSSRule.CHARSET_RULE) {
|
||||||
|
@ -154,7 +154,11 @@ WebConsoleClient.prototype = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this._client.request(packet, response => {
|
this._client.request(packet, response => {
|
||||||
this.pendingEvaluationResults.set(response.resultID, aOnResponse);
|
// Null check this in case the client has been detached while waiting
|
||||||
|
// for a response.
|
||||||
|
if (this.pendingEvaluationResults) {
|
||||||
|
this.pendingEvaluationResults.set(response.resultID, aOnResponse);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -82,3 +82,17 @@ xul|*.inline-link:-moz-focusring {
|
|||||||
color: #ff9500;
|
color: #ff9500;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xul|button:-moz-focusring,
|
||||||
|
xul|menulist:-moz-focusring,
|
||||||
|
xul|checkbox:-moz-focusring > .checkbox-check,
|
||||||
|
xul|radio[focused="true"] > .radio-check,
|
||||||
|
xul|tab:-moz-focusring > .tab-middle > .tab-text {
|
||||||
|
outline: 2px solid rgba(0,149,221,0.5);
|
||||||
|
outline-offset: 1px;
|
||||||
|
-moz-outline-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
xul|radio[focused="true"] > .radio-check {
|
||||||
|
-moz-outline-radius: 100%;
|
||||||
|
}
|
@ -94,9 +94,7 @@ XXX: apply styles to all themes until bug 509642 is fixed
|
|||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
%ifndef WINDOWS_AERO
|
background-color: rgba(250,250,250,.3)
|
||||||
background-color: rgba(250,250,250,.3);
|
|
||||||
%endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup-notification-menubutton:hover:active {
|
.popup-notification-menubutton:hover:active {
|
||||||
@ -109,17 +107,25 @@ XXX: apply styles to all themes until bug 509642 is fixed
|
|||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border: 1px solid rgba(0,0,0,.35);
|
border: 1px solid rgba(0,0,0,.35);
|
||||||
%ifdef WINDOWS_AERO
|
|
||||||
background-image: linear-gradient(rgba(250,250,250,.6), rgba(175,175,175,.25) 49%, rgba(0,0,0,.12) 51%, rgba(0,0,0,.09) 60%, rgba(0,0,0,.05));
|
|
||||||
box-shadow: 0 0 1px 1px rgba(255,255,255,.75) inset;
|
|
||||||
%else
|
|
||||||
box-shadow: 0 1px 0 rgba(255,255,255,.5) inset,
|
box-shadow: 0 1px 0 rgba(255,255,255,.5) inset,
|
||||||
0 2px 2px rgba(255,255,255,.35) inset,
|
0 2px 2px rgba(255,255,255,.35) inset,
|
||||||
0 -1px 2px rgba(0,0,0,.1) inset,
|
0 -1px 2px rgba(0,0,0,.1) inset,
|
||||||
0 1px 0 rgba(255,255,255,.35);
|
0 1px 0 rgba(255,255,255,.35);
|
||||||
%endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
%ifdef WINDOWS_AERO
|
||||||
|
@media (-moz-windows-glass) {
|
||||||
|
.popup-notification-menubutton:not([type="menu-button"]),
|
||||||
|
.popup-notification-menubutton > .button-menubutton-button,
|
||||||
|
.popup-notification-menubutton > .button-menubutton-dropmarker {
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: linear-gradient(rgba(250,250,250,.6), rgba(175,175,175,.25) 49%, rgba(0,0,0,.12) 51%, rgba(0,0,0,.09) 60%, rgba(0,0,0,.05));
|
||||||
|
box-shadow: 0 0 1px 1px rgba(255,255,255,.75) inset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%endif
|
||||||
.popup-notification-menubutton > .button-menubutton-button {
|
.popup-notification-menubutton > .button-menubutton-button {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
padding: 1px;
|
padding: 1px;
|
||||||
@ -145,40 +151,51 @@ XXX: apply styles to all themes until bug 509642 is fixed
|
|||||||
}
|
}
|
||||||
|
|
||||||
%ifdef WINDOWS_AERO
|
%ifdef WINDOWS_AERO
|
||||||
.popup-notification-menubutton > .button-menubutton-button:-moz-locale-dir(ltr),
|
@media (-moz-windows-glass) {
|
||||||
.popup-notification-menubutton > .button-menubutton-dropmarker:-moz-locale-dir(rtl) {
|
.popup-notification-menubutton > .button-menubutton-button:-moz-locale-dir(ltr),
|
||||||
border-radius: 2px 0 0 2px;
|
.popup-notification-menubutton > .button-menubutton-dropmarker:-moz-locale-dir(rtl) {
|
||||||
}
|
border-radius: 2px 0 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
.popup-notification-menubutton > .button-menubutton-button:-moz-locale-dir(rtl),
|
.popup-notification-menubutton > .button-menubutton-button:-moz-locale-dir(rtl),
|
||||||
.popup-notification-menubutton > .button-menubutton-dropmarker:-moz-locale-dir(ltr) {
|
.popup-notification-menubutton > .button-menubutton-dropmarker:-moz-locale-dir(ltr) {
|
||||||
border-radius: 0 2px 2px 0;
|
border-radius: 0 2px 2px 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
.popup-notification-menubutton:not([type="menu-button"]):hover,
|
.popup-notification-menubutton:not([type="menu-button"]):hover,
|
||||||
.popup-notification-menubutton > .button-menubutton-button:hover,
|
.popup-notification-menubutton > .button-menubutton-button:hover,
|
||||||
.popup-notification-menubutton > .button-menubutton-dropmarker:hover {
|
.popup-notification-menubutton > .button-menubutton-dropmarker:hover {
|
||||||
%ifdef WINDOWS_AERO
|
|
||||||
background-image: linear-gradient(rgba(250,250,250,.9), rgba(200,200,200,.6) 49%, rgba(0,0,0,.23) 51%, rgba(0,0,0,.17) 60%, rgba(0,0,0,.05));
|
|
||||||
box-shadow: 0 0 0 1px white inset,
|
|
||||||
0 0 2px 1px rgba(255,255,255,.75) inset;
|
|
||||||
%else
|
|
||||||
background-color: rgba(250,250,250,.6);
|
background-color: rgba(250,250,250,.6);
|
||||||
%endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup-notification-menubutton:not([type="menu-button"]):hover:active,
|
.popup-notification-menubutton:not([type="menu-button"]):hover:active,
|
||||||
.popup-notification-menubutton > .button-menubutton-button:hover:active,
|
.popup-notification-menubutton > .button-menubutton-button:hover:active,
|
||||||
.popup-notification-menubutton > .button-menubutton-dropmarker:hover:active,
|
.popup-notification-menubutton > .button-menubutton-dropmarker:hover:active,
|
||||||
.popup-notification-menubutton[open="true"] > .button-menubutton-dropmarker {
|
.popup-notification-menubutton[open="true"] > .button-menubutton-dropmarker {
|
||||||
%ifdef WINDOWS_AERO
|
|
||||||
background-image: linear-gradient(rgba(250,250,250,.9), rgba(200,200,200,.6) 49%, rgba(0,0,0,.23) 51%, rgba(0,0,0,.17) 60%, rgba(0,0,0,.05));
|
|
||||||
%else
|
|
||||||
background-color: rgba(0,0,0,.05);
|
background-color: rgba(0,0,0,.05);
|
||||||
%endif
|
|
||||||
box-shadow: 0 0 2px rgba(0,0,0,.65) inset;
|
box-shadow: 0 0 2px rgba(0,0,0,.65) inset;
|
||||||
}
|
}
|
||||||
|
%ifdef WINDOWS_AERO
|
||||||
|
@media (-moz-windows-glass) {
|
||||||
|
.popup-notification-menubutton:not([type="menu-button"]):hover,
|
||||||
|
.popup-notification-menubutton > .button-menubutton-button:hover,
|
||||||
|
.popup-notification-menubutton > .button-menubutton-dropmarker:hover {
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: linear-gradient(rgba(250,250,250,.9), rgba(200,200,200,.6) 49%, rgba(0,0,0,.23) 51%, rgba(0,0,0,.17) 60%, rgba(0,0,0,.05));
|
||||||
|
box-shadow: 0 0 0 1px white inset,
|
||||||
|
0 0 2px 1px rgba(255,255,255,.75) inset;
|
||||||
|
}
|
||||||
|
.popup-notification-menubutton:not([type="menu-button"]):hover:active,
|
||||||
|
.popup-notification-menubutton > .button-menubutton-button:hover:active,
|
||||||
|
.popup-notification-menubutton > .button-menubutton-dropmarker:hover:active,
|
||||||
|
.popup-notification-menubutton[open="true"] > .button-menubutton-dropmarker {
|
||||||
|
background-color: transparent;
|
||||||
|
background-image: linear-gradient(rgba(250,250,250,.9), rgba(200,200,200,.6) 49%, rgba(0,0,0,.23) 51%, rgba(0,0,0,.17) 60%, rgba(0,0,0,.05));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%endif
|
||||||
/*}*/
|
/*}*/
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ using namespace mozilla::gfx;
|
|||||||
using namespace mozilla::jni;
|
using namespace mozilla::jni;
|
||||||
using namespace mozilla::widget;
|
using namespace mozilla::widget;
|
||||||
|
|
||||||
AndroidBridge* AndroidBridge::sBridge;
|
AndroidBridge* AndroidBridge::sBridge = nullptr;
|
||||||
pthread_t AndroidBridge::sJavaUiThread = -1;
|
pthread_t AndroidBridge::sJavaUiThread = -1;
|
||||||
static unsigned sJavaEnvThreadIndex = 0;
|
static unsigned sJavaEnvThreadIndex = 0;
|
||||||
static jobject sGlobalContext = nullptr;
|
static jobject sGlobalContext = nullptr;
|
||||||
@ -161,14 +161,12 @@ AndroidBridge::ConstructBridge(JNIEnv *jEnv, Object::Param clsLoader)
|
|||||||
|
|
||||||
PR_NewThreadPrivateIndex(&sJavaEnvThreadIndex, JavaThreadDetachFunc);
|
PR_NewThreadPrivateIndex(&sJavaEnvThreadIndex, JavaThreadDetachFunc);
|
||||||
|
|
||||||
AndroidBridge *bridge = new AndroidBridge();
|
MOZ_ASSERT(!sBridge);
|
||||||
if (!bridge->Init(jEnv, clsLoader)) {
|
sBridge = new AndroidBridge;
|
||||||
delete bridge;
|
sBridge->Init(jEnv, clsLoader); // Success or crash
|
||||||
}
|
|
||||||
sBridge = bridge;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
AndroidBridge::Init(JNIEnv *jEnv, Object::Param clsLoader)
|
AndroidBridge::Init(JNIEnv *jEnv, Object::Param clsLoader)
|
||||||
{
|
{
|
||||||
ALOG_BRIDGE("AndroidBridge::Init");
|
ALOG_BRIDGE("AndroidBridge::Init");
|
||||||
@ -244,8 +242,6 @@ AndroidBridge::Init(JNIEnv *jEnv, Object::Param clsLoader)
|
|||||||
// jEnv should NOT be cached here by anything -- the jEnv here
|
// jEnv should NOT be cached here by anything -- the jEnv here
|
||||||
// is not valid for the real gecko main thread, which is set
|
// is not valid for the real gecko main thread, which is set
|
||||||
// at SetMainThread time.
|
// at SetMainThread time.
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -364,7 +364,7 @@ protected:
|
|||||||
~AndroidBridge();
|
~AndroidBridge();
|
||||||
|
|
||||||
void InitStubs(JNIEnv *jEnv);
|
void InitStubs(JNIEnv *jEnv);
|
||||||
bool Init(JNIEnv *jEnv, jni::Object::Param clsLoader);
|
void Init(JNIEnv *jEnv, jni::Object::Param clsLoader);
|
||||||
|
|
||||||
bool mOpenedGraphicsLibraries;
|
bool mOpenedGraphicsLibraries;
|
||||||
void OpenGraphicsLibraries();
|
void OpenGraphicsLibraries();
|
||||||
|
@ -41,8 +41,9 @@ public:
|
|||||||
return mVendor;
|
return mVendor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This spoofed value wins, even if the environment variable
|
||||||
|
// MOZ_GFX_SPOOF_GL_VENDOR was set.
|
||||||
void SpoofVendor(const nsCString& s) {
|
void SpoofVendor(const nsCString& s) {
|
||||||
EnsureInitialized();
|
|
||||||
mVendor = s;
|
mVendor = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,8 +52,9 @@ public:
|
|||||||
return mRenderer;
|
return mRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This spoofed value wins, even if the environment variable
|
||||||
|
// MOZ_GFX_SPOOF_GL_RENDERER was set.
|
||||||
void SpoofRenderer(const nsCString& s) {
|
void SpoofRenderer(const nsCString& s) {
|
||||||
EnsureInitialized();
|
|
||||||
mRenderer = s;
|
mRenderer = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,8 +63,9 @@ public:
|
|||||||
return mVersion;
|
return mVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This spoofed value wins, even if the environment variable
|
||||||
|
// MOZ_GFX_SPOOF_GL_VERSION was set.
|
||||||
void SpoofVersion(const nsCString& s) {
|
void SpoofVersion(const nsCString& s) {
|
||||||
EnsureInitialized();
|
|
||||||
mVersion = s;
|
mVersion = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,21 +88,32 @@ public:
|
|||||||
|
|
||||||
gl->MakeCurrent();
|
gl->MakeCurrent();
|
||||||
|
|
||||||
const char *spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_GL_VENDOR");
|
if (mVendor.IsEmpty()) {
|
||||||
if (spoofedVendor)
|
const char *spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_GL_VENDOR");
|
||||||
|
if (spoofedVendor) {
|
||||||
mVendor.Assign(spoofedVendor);
|
mVendor.Assign(spoofedVendor);
|
||||||
else
|
} else {
|
||||||
mVendor.Assign((const char*)gl->fGetString(LOCAL_GL_VENDOR));
|
mVendor.Assign((const char*)gl->fGetString(LOCAL_GL_VENDOR));
|
||||||
const char *spoofedRenderer = PR_GetEnv("MOZ_GFX_SPOOF_GL_RENDERER");
|
}
|
||||||
if (spoofedRenderer)
|
}
|
||||||
|
|
||||||
|
if (mRenderer.IsEmpty()) {
|
||||||
|
const char *spoofedRenderer = PR_GetEnv("MOZ_GFX_SPOOF_GL_RENDERER");
|
||||||
|
if (spoofedRenderer) {
|
||||||
mRenderer.Assign(spoofedRenderer);
|
mRenderer.Assign(spoofedRenderer);
|
||||||
else
|
} else {
|
||||||
mRenderer.Assign((const char*)gl->fGetString(LOCAL_GL_RENDERER));
|
mRenderer.Assign((const char*)gl->fGetString(LOCAL_GL_RENDERER));
|
||||||
const char *spoofedVersion = PR_GetEnv("MOZ_GFX_SPOOF_GL_VERSION");
|
}
|
||||||
if (spoofedVersion)
|
}
|
||||||
|
|
||||||
|
if (mVersion.IsEmpty()) {
|
||||||
|
const char *spoofedVersion = PR_GetEnv("MOZ_GFX_SPOOF_GL_VERSION");
|
||||||
|
if (spoofedVersion) {
|
||||||
mVersion.Assign(spoofedVersion);
|
mVersion.Assign(spoofedVersion);
|
||||||
else
|
} else {
|
||||||
mVersion.Assign((const char*)gl->fGetString(LOCAL_GL_VERSION));
|
mVersion.Assign((const char*)gl->fGetString(LOCAL_GL_VERSION));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mReady = true;
|
mReady = true;
|
||||||
}
|
}
|
||||||
@ -153,9 +167,10 @@ GfxInfo::EnsureInitialized()
|
|||||||
if (mInitialized)
|
if (mInitialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mGLStrings->EnsureInitialized();
|
if (!mozilla::AndroidBridge::Bridge()) {
|
||||||
|
gfxWarning() << "AndroidBridge missing during initialization";
|
||||||
MOZ_ASSERT(mozilla::AndroidBridge::Bridge());
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "MODEL", mModel)) {
|
if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "MODEL", mModel)) {
|
||||||
mAdapterDescription.AppendPrintf("Model: %s", NS_LossyConvertUTF16toASCII(mModel).get());
|
mAdapterDescription.AppendPrintf("Model: %s", NS_LossyConvertUTF16toASCII(mModel).get());
|
||||||
@ -601,7 +616,6 @@ GfxInfo::GetFeatureStatusImpl(int32_t aFeature,
|
|||||||
/* void spoofVendorID (in DOMString aVendorID); */
|
/* void spoofVendorID (in DOMString aVendorID); */
|
||||||
NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID)
|
NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID)
|
||||||
{
|
{
|
||||||
EnsureInitialized();
|
|
||||||
mGLStrings->SpoofVendor(NS_LossyConvertUTF16toASCII(aVendorID));
|
mGLStrings->SpoofVendor(NS_LossyConvertUTF16toASCII(aVendorID));
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -609,7 +623,6 @@ NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID)
|
|||||||
/* void spoofDeviceID (in unsigned long aDeviceID); */
|
/* void spoofDeviceID (in unsigned long aDeviceID); */
|
||||||
NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID)
|
NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID)
|
||||||
{
|
{
|
||||||
EnsureInitialized();
|
|
||||||
mGLStrings->SpoofRenderer(NS_LossyConvertUTF16toASCII(aDeviceID));
|
mGLStrings->SpoofRenderer(NS_LossyConvertUTF16toASCII(aDeviceID));
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -617,7 +630,6 @@ NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID)
|
|||||||
/* void spoofDriverVersion (in DOMString aDriverVersion); */
|
/* void spoofDriverVersion (in DOMString aDriverVersion); */
|
||||||
NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion)
|
NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion)
|
||||||
{
|
{
|
||||||
EnsureInitialized();
|
|
||||||
mGLStrings->SpoofVersion(NS_LossyConvertUTF16toASCII(aDriverVersion));
|
mGLStrings->SpoofVersion(NS_LossyConvertUTF16toASCII(aDriverVersion));
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user