зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound, a=merge
This commit is contained in:
Коммит
9deac25dd2
|
@ -385,7 +385,7 @@ pref("urlclassifier.gethash.timeout_ms", 5000);
|
||||||
pref("urlclassifier.max-complete-age", 2700);
|
pref("urlclassifier.max-complete-age", 2700);
|
||||||
|
|
||||||
// Tracking protection
|
// Tracking protection
|
||||||
pref("privacy.trackingprotection.enabled", true);
|
pref("privacy.trackingprotection.enabled", false);
|
||||||
pref("privacy.trackingprotection.pbmode.enabled", false);
|
pref("privacy.trackingprotection.pbmode.enabled", false);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -671,6 +671,7 @@ var settingsToObserve = {
|
||||||
'mms.debugging.enabled': false,
|
'mms.debugging.enabled': false,
|
||||||
'network.debugging.enabled': false,
|
'network.debugging.enabled': false,
|
||||||
'privacy.donottrackheader.enabled': false,
|
'privacy.donottrackheader.enabled': false,
|
||||||
|
'privacy.trackingprotection.enabled': false,
|
||||||
'ril.debugging.enabled': false,
|
'ril.debugging.enabled': false,
|
||||||
'ril.radio.disabled': false,
|
'ril.radio.disabled': false,
|
||||||
'ril.mms.requestReadReport.enabled': {
|
'ril.mms.requestReadReport.enabled': {
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="60cdaa3d3424db3432dc903e7f9c6c8fa099c06d"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="0019347fbaedc9d54f2f3436fff17aeb22968174"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="60cdaa3d3424db3432dc903e7f9c6c8fa099c06d"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="0019347fbaedc9d54f2f3436fff17aeb22968174"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||||
|
|
|
@ -19,11 +19,11 @@
|
||||||
<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="60cdaa3d3424db3432dc903e7f9c6c8fa099c06d"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0019347fbaedc9d54f2f3436fff17aeb22968174"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||||
<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="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
|
||||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="12ff7481566587aa4198cf1287598acb3a999973"/>
|
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="065f6361461030d32c6dc08d716b013bfadab1d9"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
|
|
|
@ -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="60cdaa3d3424db3432dc903e7f9c6c8fa099c06d"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="0019347fbaedc9d54f2f3436fff17aeb22968174"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="60cdaa3d3424db3432dc903e7f9c6c8fa099c06d"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="0019347fbaedc9d54f2f3436fff17aeb22968174"/>
|
||||||
<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="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -128,10 +128,10 @@
|
||||||
<!-- Emulator specific things -->
|
<!-- Emulator specific things -->
|
||||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
|
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
|
||||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="8d4018ebd33ac3f1a043b2d54bc578028656a659"/>
|
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="8d4018ebd33ac3f1a043b2d54bc578028656a659"/>
|
||||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="b2773dbc3cb24e70cff2b05522e9c959250400ac"/>
|
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="6bbed5a99dd0f347bcee7fdde0463467fe3002f3"/>
|
||||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/>
|
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/>
|
||||||
<project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="0c6a6547cd1fd302fa2b0f6e375654df36bf0ec4"/>
|
<project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="0c6a6547cd1fd302fa2b0f6e375654df36bf0ec4"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="7132bc11fbc68acfebcd509095562ca04fad5584"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="575799df119771fcfbe9c99c8eee43f8100cd9a2"/>
|
||||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="5f4b68c799927b6e078f987b12722c3a6ccd4a45"/>
|
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="5f4b68c799927b6e078f987b12722c3a6ccd4a45"/>
|
||||||
<project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
|
<project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
|
||||||
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="6a1bb59af65b6485b1090522f66fac95c3f9e22c"/>
|
<project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="6a1bb59af65b6485b1090522f66fac95c3f9e22c"/>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="60cdaa3d3424db3432dc903e7f9c6c8fa099c06d"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="0019347fbaedc9d54f2f3436fff17aeb22968174"/>
|
||||||
<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="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
|
|
@ -19,11 +19,11 @@
|
||||||
<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="60cdaa3d3424db3432dc903e7f9c6c8fa099c06d"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="0019347fbaedc9d54f2f3436fff17aeb22968174"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||||
<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="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
|
||||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="12ff7481566587aa4198cf1287598acb3a999973"/>
|
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="065f6361461030d32c6dc08d716b013bfadab1d9"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="60cdaa3d3424db3432dc903e7f9c6c8fa099c06d"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="0019347fbaedc9d54f2f3436fff17aeb22968174"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"git": {
|
"git": {
|
||||||
"git_revision": "60cdaa3d3424db3432dc903e7f9c6c8fa099c06d",
|
"git_revision": "0019347fbaedc9d54f2f3436fff17aeb22968174",
|
||||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||||
"branch": ""
|
"branch": ""
|
||||||
},
|
},
|
||||||
"revision": "1de2dfa13b0b91c293111198011353c7bb86242d",
|
"revision": "32ae3240869f21601d31c7f71c4fd09c02239353",
|
||||||
"repo_path": "integration/gaia-central"
|
"repo_path": "integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="60cdaa3d3424db3432dc903e7f9c6c8fa099c06d"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="0019347fbaedc9d54f2f3436fff17aeb22968174"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<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="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="60cdaa3d3424db3432dc903e7f9c6c8fa099c06d"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="0019347fbaedc9d54f2f3436fff17aeb22968174"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="60cdaa3d3424db3432dc903e7f9c6c8fa099c06d"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="0019347fbaedc9d54f2f3436fff17aeb22968174"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
|
||||||
|
@ -141,7 +141,7 @@
|
||||||
<default remote="caf" revision="refs/tags/android-5.1.0_r1" sync-j="4"/>
|
<default remote="caf" revision="refs/tags/android-5.1.0_r1" 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="fe7df1bc8dd0fd71571505d7be1c31a4ad1e40fb"/>
|
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="fe7df1bc8dd0fd71571505d7be1c31a4ad1e40fb"/>
|
||||||
<project name="device-hammerhead" path="device/lge/hammerhead" remote="b2g" revision="31b5bafd0d234984f1133a3b3d08839521f2b718"/>
|
<project name="device-hammerhead" path="device/lge/hammerhead" remote="b2g" revision="844d9fe1c7114c6d586fbea611cbb7038413d762"/>
|
||||||
<project name="device_lge_hammerhead-kernel" path="device/lge/hammerhead-kernel" remote="b2g" revision="8b3ffcfdd3d3852eca5488628f8bb2a08acbffa7"/>
|
<project name="device_lge_hammerhead-kernel" path="device/lge/hammerhead-kernel" remote="b2g" revision="8b3ffcfdd3d3852eca5488628f8bb2a08acbffa7"/>
|
||||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="5d0ae53d9588c3d70c005aec9be94af9a534de16"/>
|
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="5d0ae53d9588c3d70c005aec9be94af9a534de16"/>
|
||||||
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="c15b6e266136cd0cdd9b94d0bbed1962d9dd6672"/>
|
<project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="c15b6e266136cd0cdd9b94d0bbed1962d9dd6672"/>
|
||||||
|
|
|
@ -1882,6 +1882,12 @@ pref("browser.tabs.remote.autostart.1", false);
|
||||||
pref("browser.tabs.remote.autostart.2", true);
|
pref("browser.tabs.remote.autostart.2", true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// For the about:tabcrashed page
|
||||||
|
pref("browser.tabs.crashReporting.sendReport", true);
|
||||||
|
pref("browser.tabs.crashReporting.includeURL", false);
|
||||||
|
pref("browser.tabs.crashReporting.emailMe", false);
|
||||||
|
pref("browser.tabs.crashReporting.email", "");
|
||||||
|
|
||||||
#ifdef NIGHTLY_BUILD
|
#ifdef NIGHTLY_BUILD
|
||||||
#ifndef MOZ_MULET
|
#ifndef MOZ_MULET
|
||||||
pref("layers.async-pan-zoom.enabled", true);
|
pref("layers.async-pan-zoom.enabled", true);
|
||||||
|
|
|
@ -3,27 +3,66 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
function parseQueryString() {
|
function parseQueryString() {
|
||||||
let url = document.documentURI;
|
let URL = document.documentURI;
|
||||||
let queryString = url.replace(/^about:tabcrashed?e=tabcrashed/, "");
|
let queryString = URL.replace(/^about:tabcrashed?e=tabcrashed/, "");
|
||||||
|
|
||||||
let titleMatch = queryString.match(/d=([^&]*)/);
|
let titleMatch = queryString.match(/d=([^&]*)/);
|
||||||
return titleMatch && titleMatch[1] ? decodeURIComponent(titleMatch[1]) : "";
|
let URLMatch = queryString.match(/u=([^&]*)/);
|
||||||
|
return {
|
||||||
|
title: titleMatch && titleMatch[1] ? decodeURIComponent(titleMatch[1]) : "",
|
||||||
|
URL: URLMatch && URLMatch[1] ? decodeURIComponent(URLMatch[1]) : "",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
document.title = parseQueryString();
|
function displayUI() {
|
||||||
|
if (!hasReport()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
function shouldSendReport() {
|
let sendCrashReport = document.getElementById("sendReport").checked;
|
||||||
if (!document.documentElement.classList.contains("crashDumpAvailable"))
|
let container = document.getElementById("crash-reporter-container");
|
||||||
return false;
|
container.hidden = !sendCrashReport;
|
||||||
return document.getElementById("sendReport").checked;
|
}
|
||||||
|
|
||||||
|
function hasReport() {
|
||||||
|
return document.documentElement.classList.contains("crashDumpAvailable");
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendEvent(message) {
|
function sendEvent(message) {
|
||||||
|
let comments = "";
|
||||||
|
let email = "";
|
||||||
|
let URL = "";
|
||||||
|
let sendCrashReport = false;
|
||||||
|
let emailMe = false;
|
||||||
|
let includeURL = false;
|
||||||
|
|
||||||
|
if (hasReport()) {
|
||||||
|
sendCrashReport = document.getElementById("sendReport").checked;
|
||||||
|
if (sendCrashReport) {
|
||||||
|
comments = document.getElementById("comments").value.trim();
|
||||||
|
|
||||||
|
includeURL = document.getElementById("includeURL").checked;
|
||||||
|
if (includeURL) {
|
||||||
|
URL = parseQueryString().URL.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
emailMe = document.getElementById("emailMe").checked;
|
||||||
|
if (emailMe) {
|
||||||
|
email = document.getElementById("email").value.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let event = new CustomEvent("AboutTabCrashedMessage", {
|
let event = new CustomEvent("AboutTabCrashedMessage", {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
detail: {
|
detail: {
|
||||||
message,
|
message,
|
||||||
sendCrashReport: shouldSendReport(),
|
sendCrashReport,
|
||||||
|
comments,
|
||||||
|
email,
|
||||||
|
emailMe,
|
||||||
|
includeURL,
|
||||||
|
URL,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -42,6 +81,17 @@ function restoreAll() {
|
||||||
sendEvent("restoreAll");
|
sendEvent("restoreAll");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.title = parseQueryString().title;
|
||||||
|
|
||||||
// Error pages are loaded as LOAD_BACKGROUND, so they don't get load events.
|
// Error pages are loaded as LOAD_BACKGROUND, so they don't get load events.
|
||||||
var event = new CustomEvent("AboutTabCrashedLoad", {bubbles:true});
|
var event = new CustomEvent("AboutTabCrashedLoad", {bubbles:true});
|
||||||
document.dispatchEvent(event);
|
document.dispatchEvent(event);
|
||||||
|
|
||||||
|
addEventListener("DOMContentLoaded", function() {
|
||||||
|
let sendReport = document.getElementById("sendReport");
|
||||||
|
sendReport.addEventListener("click", function() {
|
||||||
|
displayUI();
|
||||||
|
});
|
||||||
|
|
||||||
|
displayUI();
|
||||||
|
});
|
||||||
|
|
|
@ -37,8 +37,22 @@
|
||||||
<p>&tabCrashed.message;</p>
|
<p>&tabCrashed.message;</p>
|
||||||
|
|
||||||
<div id="report-box">
|
<div id="report-box">
|
||||||
<input type="checkbox" id="sendReport" checked="checked"/>
|
<input type="checkbox" id="sendReport"/>
|
||||||
<label for="sendReport">&tabCrashed.sendReport;</label>
|
<label for="sendReport">&tabCrashed.sendReport;</label>
|
||||||
|
<div id="crash-reporter-container" hidden="true">
|
||||||
|
<p id="crash-reporter-title">&tabCrashed.crashReporter;</p>
|
||||||
|
<textarea id="comments" placeholder="&tabCrashed.commentPlaceholder;" rows="4"></textarea>
|
||||||
|
|
||||||
|
<ul id="options">
|
||||||
|
<li><input type="checkbox" id="includeURL"/>
|
||||||
|
<label for="includeURL">&tabCrashed.includeURL;</label></li>
|
||||||
|
|
||||||
|
<li><input type="checkbox" id="emailMe"/>
|
||||||
|
<label for="emailMe">&tabCrashed.emailMe;</label></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<input type="text" id="email" placeholder="&tabCrashed.emailPlaceholder;"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p id="reportSent">&tabCrashed.reportSent;</p>
|
<p id="reportSent">&tabCrashed.reportSent;</p>
|
||||||
|
|
|
@ -1166,7 +1166,15 @@ var gBrowserInit = {
|
||||||
let browser = gBrowser.getBrowserForDocument(ownerDoc);
|
let browser = gBrowser.getBrowserForDocument(ownerDoc);
|
||||||
#ifdef MOZ_CRASHREPORTER
|
#ifdef MOZ_CRASHREPORTER
|
||||||
if (event.detail.sendCrashReport) {
|
if (event.detail.sendCrashReport) {
|
||||||
TabCrashReporter.submitCrashReport(browser);
|
TabCrashReporter.submitCrashReport(browser, {
|
||||||
|
comments: event.detail.comments,
|
||||||
|
email: event.detail.email,
|
||||||
|
emailMe: event.detail.emailMe,
|
||||||
|
includeURL: event.detail.includeURL,
|
||||||
|
URL: event.detail.URL,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
TabCrashReporter.dontSubmitCrashReport();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -5355,13 +5355,11 @@
|
||||||
]]></handler>
|
]]></handler>
|
||||||
|
|
||||||
<handler event="dblclick"><![CDATA[
|
<handler event="dblclick"><![CDATA[
|
||||||
if (gBrowser.AppConstants.platform != "macosx") {
|
// When the tabbar has an unified appearance with the titlebar
|
||||||
// When the tabbar has an unified appearance with the titlebar
|
// and menubar, a double-click in it should have the same behavior
|
||||||
// and menubar, a double-click in it should have the same behavior
|
// as double-clicking the titlebar
|
||||||
// as double-clicking the titlebar
|
if (TabsInTitlebar.enabled || this.parentNode._dragBindingAlive)
|
||||||
if (TabsInTitlebar.enabled || this.parentNode._dragBindingAlive)
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.button != 0 ||
|
if (event.button != 0 ||
|
||||||
event.originalTarget.localName != "box")
|
event.originalTarget.localName != "box")
|
||||||
|
|
|
@ -525,3 +525,5 @@ support-files =
|
||||||
readerModeArticle.html
|
readerModeArticle.html
|
||||||
[browser_domFullscreen_fullscreenMode.js]
|
[browser_domFullscreen_fullscreenMode.js]
|
||||||
[browser_menuButtonBadgeManager.js]
|
[browser_menuButtonBadgeManager.js]
|
||||||
|
[browser_aboutTabCrashed.js]
|
||||||
|
skip-if = !e10s || !crashreporter
|
||||||
|
|
|
@ -0,0 +1,335 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
let { TabCrashReporter } =
|
||||||
|
Cu.import("resource:///modules/ContentCrashReporters.jsm");
|
||||||
|
|
||||||
|
const SERVER_URL = "http://example.com/browser/toolkit/crashreporter/test/browser/crashreport.sjs";
|
||||||
|
const PAGE = "data:text/html,<html><body>A%20regular,%20everyday,%20normal%20page.";
|
||||||
|
const COMMENTS = "Here's my test comment!";
|
||||||
|
const EMAIL = "foo@privacy.com";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For an nsIPropertyBag, returns the value for a given
|
||||||
|
* key.
|
||||||
|
*
|
||||||
|
* @param bag
|
||||||
|
* The nsIPropertyBag to retrieve the value from
|
||||||
|
* @param key
|
||||||
|
* The key that we want to get the value for from the
|
||||||
|
* bag
|
||||||
|
* @returns The value corresponding to the key from the bag,
|
||||||
|
* or null if the value could not be retrieved (for
|
||||||
|
* example, if no value is set at that key).
|
||||||
|
*/
|
||||||
|
function getPropertyBagValue(bag, key) {
|
||||||
|
try {
|
||||||
|
let val = bag.getProperty(key);
|
||||||
|
return val;
|
||||||
|
} catch(e if e.result == Cr.NS_ERROR_FAILURE) {}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Promise that resolves once a crash report has
|
||||||
|
* been submitted. This function will also test the crash
|
||||||
|
* reports extra data to see if it matches expectedExtra.
|
||||||
|
*
|
||||||
|
* @param expectedExtra
|
||||||
|
* An Object whose key-value pairs will be compared
|
||||||
|
* against the key-value pairs in the extra data of the
|
||||||
|
* crash report. A test failure will occur if there is
|
||||||
|
* a mismatch.
|
||||||
|
*
|
||||||
|
* Note that this will only check the values that exist
|
||||||
|
* in expectedExtra. It's possible that the crash report
|
||||||
|
* will contain other extra information that is not
|
||||||
|
* compared against.
|
||||||
|
* @returns Promise
|
||||||
|
*/
|
||||||
|
function promiseCrashReport(expectedExtra) {
|
||||||
|
return Task.spawn(function*() {
|
||||||
|
info("Starting wait on crash-report-status");
|
||||||
|
let [subject, data] =
|
||||||
|
yield TestUtils.topicObserved("crash-report-status", (subject, data) => {
|
||||||
|
return data == "success";
|
||||||
|
});
|
||||||
|
info("Topic observed!");
|
||||||
|
|
||||||
|
if (!(subject instanceof Ci.nsIPropertyBag2)) {
|
||||||
|
throw new Error("Subject was not a Ci.nsIPropertyBag2");
|
||||||
|
}
|
||||||
|
|
||||||
|
let remoteID = getPropertyBagValue(subject, "serverCrashID");
|
||||||
|
if (!remoteID) {
|
||||||
|
throw new Error("Report should have a server ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
let file = Cc["@mozilla.org/file/local;1"]
|
||||||
|
.createInstance(Ci.nsILocalFile);
|
||||||
|
file.initWithPath(Services.crashmanager._submittedDumpsDir);
|
||||||
|
file.append(remoteID + ".txt");
|
||||||
|
if (!file.exists()) {
|
||||||
|
throw new Error("Report should have been received by the server");
|
||||||
|
}
|
||||||
|
|
||||||
|
file.remove(false);
|
||||||
|
|
||||||
|
let extra = getPropertyBagValue(subject, "extra");
|
||||||
|
if (!(extra instanceof Ci.nsIPropertyBag2)) {
|
||||||
|
throw new Error("extra was not a Ci.nsIPropertyBag2");
|
||||||
|
}
|
||||||
|
|
||||||
|
info("Iterating crash report extra keys");
|
||||||
|
let enumerator = extra.enumerator;
|
||||||
|
while (enumerator.hasMoreElements()) {
|
||||||
|
let key = enumerator.getNext().QueryInterface(Ci.nsIProperty).name;
|
||||||
|
let value = extra.getPropertyAsAString(key);
|
||||||
|
if (key in expectedExtra) {
|
||||||
|
is(value, expectedExtra[key],
|
||||||
|
`Crash report had the right extra value for ${key}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the browser to send crash reports to the local crash report
|
||||||
|
* testing server.
|
||||||
|
*/
|
||||||
|
add_task(function* setup() {
|
||||||
|
// The test harness sets MOZ_CRASHREPORTER_NO_REPORT, which disables crash
|
||||||
|
// reports. This test needs them enabled. The test also needs a mock
|
||||||
|
// report server, and fortunately one is already set up by toolkit/
|
||||||
|
// crashreporter/test/Makefile.in. Assign its URL to MOZ_CRASHREPORTER_URL,
|
||||||
|
// which CrashSubmit.jsm uses as a server override.
|
||||||
|
let env = Cc["@mozilla.org/process/environment;1"]
|
||||||
|
.getService(Components.interfaces.nsIEnvironment);
|
||||||
|
let noReport = env.get("MOZ_CRASHREPORTER_NO_REPORT");
|
||||||
|
let serverUrl = env.get("MOZ_CRASHREPORTER_URL");
|
||||||
|
env.set("MOZ_CRASHREPORTER_NO_REPORT", "");
|
||||||
|
env.set("MOZ_CRASHREPORTER_URL", SERVER_URL);
|
||||||
|
|
||||||
|
registerCleanupFunction(function() {
|
||||||
|
env.set("MOZ_CRASHREPORTER_NO_REPORT", noReport);
|
||||||
|
env.set("MOZ_CRASHREPORTER_URL", serverUrl);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns a Promise that resolves once the following
|
||||||
|
* actions have taken place:
|
||||||
|
*
|
||||||
|
* 1) A new tab is opened up at PAGE
|
||||||
|
* 2) The tab is crashed
|
||||||
|
* 3) The about:tabcrashed page's fields are set in accordance with
|
||||||
|
* fieldValues
|
||||||
|
* 4) The tab is restored
|
||||||
|
* 5) A crash report is received from the testing server
|
||||||
|
* 6) Any tab crash prefs that were overwritten are reset
|
||||||
|
*
|
||||||
|
* @param fieldValues
|
||||||
|
* An Object describing how to set the about:tabcrashed
|
||||||
|
* fields. The following properties are accepted:
|
||||||
|
*
|
||||||
|
* comments (String)
|
||||||
|
* The comments to put in the comment textarea
|
||||||
|
* email (String)
|
||||||
|
* The email address to put in the email address input
|
||||||
|
* emailMe (bool)
|
||||||
|
* The checked value of the "Email me" checkbox
|
||||||
|
* includeURL (bool)
|
||||||
|
* The checked value of the "Include URL" checkbox
|
||||||
|
*
|
||||||
|
* If any of these fields are missing, the defaults from
|
||||||
|
* the user preferences are used.
|
||||||
|
* @param expectedExtra
|
||||||
|
* An Object describing the expected values that the submitted
|
||||||
|
* crash report's extra data should contain.
|
||||||
|
* @returns Promise
|
||||||
|
*/
|
||||||
|
function crashTabTestHelper(fieldValues, expectedExtra) {
|
||||||
|
return BrowserTestUtils.withNewTab({
|
||||||
|
gBrowser,
|
||||||
|
url: PAGE,
|
||||||
|
}, function*(browser) {
|
||||||
|
let prefs = TabCrashReporter.prefs;
|
||||||
|
let originalSendReport = prefs.getBoolPref("sendReport");
|
||||||
|
let originalEmailMe = prefs.getBoolPref("emailMe");
|
||||||
|
let originalIncludeURL = prefs.getBoolPref("includeURL");
|
||||||
|
let originalEmail = prefs.getCharPref("email");
|
||||||
|
|
||||||
|
let tab = gBrowser.getTabForBrowser(browser);
|
||||||
|
yield BrowserTestUtils.crashBrowser(browser);
|
||||||
|
let doc = browser.contentDocument;
|
||||||
|
|
||||||
|
// Since about:tabcrashed will run in the parent process, we can safely
|
||||||
|
// manipulate its DOM nodes directly
|
||||||
|
let comments = doc.getElementById("comments");
|
||||||
|
let email = doc.getElementById("email");
|
||||||
|
let emailMe = doc.getElementById("emailMe");
|
||||||
|
let includeURL = doc.getElementById("includeURL");
|
||||||
|
|
||||||
|
if (fieldValues.hasOwnProperty("comments")) {
|
||||||
|
comments.value = fieldValues.comments;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fieldValues.hasOwnProperty("email")) {
|
||||||
|
email.value = fieldValues.email;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fieldValues.hasOwnProperty("emailMe")) {
|
||||||
|
emailMe.checked = fieldValues.emailMe;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fieldValues.hasOwnProperty("includeURL")) {
|
||||||
|
includeURL.checked = fieldValues.includeURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
let crashReport = promiseCrashReport(expectedExtra);
|
||||||
|
let restoreTab = browser.contentDocument.getElementById("restoreTab");
|
||||||
|
restoreTab.click();
|
||||||
|
yield BrowserTestUtils.waitForEvent(tab, "SSTabRestored");
|
||||||
|
yield crashReport;
|
||||||
|
|
||||||
|
// Submitting the crash report may have set some prefs regarding how to
|
||||||
|
// send tab crash reports. Let's reset them for the next test.
|
||||||
|
prefs.setBoolPref("sendReport", originalSendReport);
|
||||||
|
prefs.setBoolPref("emailMe", originalEmailMe);
|
||||||
|
prefs.setBoolPref("includeURL", originalIncludeURL);
|
||||||
|
prefs.setCharPref("email", originalEmail);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests what we send with the crash report by default. By default, we do not
|
||||||
|
* send any comments, the URL of the crashing page, or the email address of
|
||||||
|
* the user.
|
||||||
|
*/
|
||||||
|
add_task(function* test_default() {
|
||||||
|
yield crashTabTestHelper({}, {
|
||||||
|
"Comments": "",
|
||||||
|
"URL": "",
|
||||||
|
"Email": "",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test just sending a comment.
|
||||||
|
*/
|
||||||
|
add_task(function* test_just_a_comment() {
|
||||||
|
yield crashTabTestHelper({
|
||||||
|
comments: COMMENTS,
|
||||||
|
}, {
|
||||||
|
"Comments": COMMENTS,
|
||||||
|
"URL": "",
|
||||||
|
"Email": "",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that we don't send email if emailMe is unchecked
|
||||||
|
*/
|
||||||
|
add_task(function* test_no_email() {
|
||||||
|
yield crashTabTestHelper({
|
||||||
|
email: EMAIL,
|
||||||
|
emailMe: false,
|
||||||
|
}, {
|
||||||
|
"Comments": "",
|
||||||
|
"URL": "",
|
||||||
|
"Email": "",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that we can send an email address if emailMe is checked
|
||||||
|
*/
|
||||||
|
add_task(function* test_yes_email() {
|
||||||
|
yield crashTabTestHelper({
|
||||||
|
email: EMAIL,
|
||||||
|
emailMe: true,
|
||||||
|
}, {
|
||||||
|
"Comments": "",
|
||||||
|
"URL": "",
|
||||||
|
"Email": EMAIL,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that we will send the URL of the page if includeURL is checked.
|
||||||
|
*/
|
||||||
|
add_task(function* test_send_URL() {
|
||||||
|
yield crashTabTestHelper({
|
||||||
|
includeURL: true,
|
||||||
|
}, {
|
||||||
|
"Comments": "",
|
||||||
|
"URL": PAGE,
|
||||||
|
"Email": "",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that we can send comments, the email address, and the URL
|
||||||
|
*/
|
||||||
|
add_task(function* test_send_all() {
|
||||||
|
yield crashTabTestHelper({
|
||||||
|
includeURL: true,
|
||||||
|
emailMe: true,
|
||||||
|
email: EMAIL,
|
||||||
|
comments: COMMENTS,
|
||||||
|
}, {
|
||||||
|
"Comments": COMMENTS,
|
||||||
|
"URL": PAGE,
|
||||||
|
"Email": EMAIL,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that if we have an email address stored in prefs, and we decide
|
||||||
|
* not to submit the email address in the next crash report, that we
|
||||||
|
* clear the email address.
|
||||||
|
*/
|
||||||
|
add_task(function* test_clear_email() {
|
||||||
|
return BrowserTestUtils.withNewTab({
|
||||||
|
gBrowser,
|
||||||
|
url: PAGE,
|
||||||
|
}, function*(browser) {
|
||||||
|
let prefs = TabCrashReporter.prefs;
|
||||||
|
let originalSendReport = prefs.getBoolPref("sendReport");
|
||||||
|
let originalEmailMe = prefs.getBoolPref("emailMe");
|
||||||
|
let originalIncludeURL = prefs.getBoolPref("includeURL");
|
||||||
|
let originalEmail = prefs.getCharPref("email");
|
||||||
|
|
||||||
|
// Pretend that we stored an email address from the previous
|
||||||
|
// crash
|
||||||
|
prefs.setCharPref("email", EMAIL);
|
||||||
|
prefs.setBoolPref("emailMe", true);
|
||||||
|
|
||||||
|
let tab = gBrowser.getTabForBrowser(browser);
|
||||||
|
yield BrowserTestUtils.crashBrowser(browser);
|
||||||
|
let doc = browser.contentDocument;
|
||||||
|
|
||||||
|
// Since about:tabcrashed will run in the parent process, we can safely
|
||||||
|
// manipulate its DOM nodes directly
|
||||||
|
let emailMe = doc.getElementById("emailMe");
|
||||||
|
emailMe.checked = false;
|
||||||
|
|
||||||
|
let crashReport = promiseCrashReport({
|
||||||
|
Email: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
let restoreTab = browser.contentDocument.getElementById("restoreTab");
|
||||||
|
restoreTab.click();
|
||||||
|
yield BrowserTestUtils.waitForEvent(tab, "SSTabRestored");
|
||||||
|
yield crashReport;
|
||||||
|
|
||||||
|
is(prefs.getCharPref("email"), "", "No email address should be stored");
|
||||||
|
|
||||||
|
// Submitting the crash report may have set some prefs regarding how to
|
||||||
|
// send tab crash reports. Let's reset them for the next test.
|
||||||
|
prefs.setBoolPref("sendReport", originalSendReport);
|
||||||
|
prefs.setBoolPref("emailMe", originalEmailMe);
|
||||||
|
prefs.setBoolPref("includeURL", originalIncludeURL);
|
||||||
|
prefs.setCharPref("email", originalEmail);
|
||||||
|
});
|
||||||
|
});
|
|
@ -120,10 +120,12 @@ loop.shared.views = (function(_, mozL10n) {
|
||||||
|
|
||||||
_handleShareTabs: function() {
|
_handleShareTabs: function() {
|
||||||
this._startScreenShare("browser");
|
this._startScreenShare("browser");
|
||||||
|
this.hideDropdownMenu();
|
||||||
},
|
},
|
||||||
|
|
||||||
_handleShareWindows: function() {
|
_handleShareWindows: function() {
|
||||||
this._startScreenShare("window");
|
this._startScreenShare("window");
|
||||||
|
this.hideDropdownMenu();
|
||||||
},
|
},
|
||||||
|
|
||||||
_getTitle: function() {
|
_getTitle: function() {
|
||||||
|
|
|
@ -120,10 +120,12 @@ loop.shared.views = (function(_, mozL10n) {
|
||||||
|
|
||||||
_handleShareTabs: function() {
|
_handleShareTabs: function() {
|
||||||
this._startScreenShare("browser");
|
this._startScreenShare("browser");
|
||||||
|
this.hideDropdownMenu();
|
||||||
},
|
},
|
||||||
|
|
||||||
_handleShareWindows: function() {
|
_handleShareWindows: function() {
|
||||||
this._startScreenShare("window");
|
this._startScreenShare("window");
|
||||||
|
this.hideDropdownMenu();
|
||||||
},
|
},
|
||||||
|
|
||||||
_getTitle: function() {
|
_getTitle: function() {
|
||||||
|
|
|
@ -176,6 +176,22 @@ describe("loop.shared.views", function() {
|
||||||
new sharedActions.StartScreenShare({ type: "browser" }));
|
new sharedActions.StartScreenShare({ type: "browser" }));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should close the dropdown on 'browser' option click", function() {
|
||||||
|
var comp = TestUtils.renderIntoDocument(
|
||||||
|
React.createElement(sharedViews.ScreenShareControlButton, {
|
||||||
|
dispatcher: dispatcher,
|
||||||
|
visible: true,
|
||||||
|
state: SCREEN_SHARE_STATES.INACTIVE
|
||||||
|
}));
|
||||||
|
|
||||||
|
sandbox.stub(comp, "hideDropdownMenu");
|
||||||
|
|
||||||
|
TestUtils.Simulate.click(comp.getDOMNode().querySelector(
|
||||||
|
".screen-share-menu > li"));
|
||||||
|
|
||||||
|
sinon.assert.calledOnce(comp.hideDropdownMenu);
|
||||||
|
});
|
||||||
|
|
||||||
it("should dispatch a 'window' StartScreenShare action on option click",
|
it("should dispatch a 'window' StartScreenShare action on option click",
|
||||||
function() {
|
function() {
|
||||||
var comp = TestUtils.renderIntoDocument(
|
var comp = TestUtils.renderIntoDocument(
|
||||||
|
@ -193,6 +209,22 @@ describe("loop.shared.views", function() {
|
||||||
new sharedActions.StartScreenShare({ type: "window" }));
|
new sharedActions.StartScreenShare({ type: "window" }));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should close the dropdown on 'window' option click", function() {
|
||||||
|
var comp = TestUtils.renderIntoDocument(
|
||||||
|
React.createElement(sharedViews.ScreenShareControlButton, {
|
||||||
|
dispatcher: dispatcher,
|
||||||
|
visible: true,
|
||||||
|
state: SCREEN_SHARE_STATES.INACTIVE
|
||||||
|
}));
|
||||||
|
|
||||||
|
sandbox.stub(comp, "hideDropdownMenu");
|
||||||
|
|
||||||
|
TestUtils.Simulate.click(comp.getDOMNode().querySelector(
|
||||||
|
".screen-share-menu > li:last-child"));
|
||||||
|
|
||||||
|
sinon.assert.calledOnce(comp.hideDropdownMenu);
|
||||||
|
});
|
||||||
|
|
||||||
it("should have the 'window' option enabled", function() {
|
it("should have the 'window' option enabled", function() {
|
||||||
var comp = TestUtils.renderIntoDocument(
|
var comp = TestUtils.renderIntoDocument(
|
||||||
React.createElement(sharedViews.ScreenShareControlButton, {
|
React.createElement(sharedViews.ScreenShareControlButton, {
|
||||||
|
|
|
@ -69,7 +69,7 @@ add_task(function* test_crash() {
|
||||||
// the content process. The "crash" message makes it first so that we don't
|
// the content process. The "crash" message makes it first so that we don't
|
||||||
// get a chance to process the flush. The TabStateFlusher however should be
|
// get a chance to process the flush. The TabStateFlusher however should be
|
||||||
// notified so that the flush still completes.
|
// notified so that the flush still completes.
|
||||||
let promise1 = crashBrowser(browser);
|
let promise1 = BrowserTestUtils.crashBrowser(browser);
|
||||||
let promise2 = TabStateFlusher.flush(browser);
|
let promise2 = TabStateFlusher.flush(browser);
|
||||||
yield Promise.all([promise1, promise2]);
|
yield Promise.all([promise1, promise2]);
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ add_task(function test_crash_page_not_in_history() {
|
||||||
yield TabStateFlusher.flush(browser);
|
yield TabStateFlusher.flush(browser);
|
||||||
|
|
||||||
// Crash the tab
|
// Crash the tab
|
||||||
yield crashBrowser(browser);
|
yield BrowserTestUtils.crashBrowser(browser);
|
||||||
|
|
||||||
// Check the tab state and make sure the tab crashed page isn't
|
// Check the tab state and make sure the tab crashed page isn't
|
||||||
// mentioned.
|
// mentioned.
|
||||||
|
@ -146,7 +146,7 @@ add_task(function test_revived_history_from_remote() {
|
||||||
yield TabStateFlusher.flush(browser);
|
yield TabStateFlusher.flush(browser);
|
||||||
|
|
||||||
// Crash the tab
|
// Crash the tab
|
||||||
yield crashBrowser(browser);
|
yield BrowserTestUtils.crashBrowser(browser);
|
||||||
|
|
||||||
// Browse to a new site that will cause the browser to
|
// Browse to a new site that will cause the browser to
|
||||||
// become remote again.
|
// become remote again.
|
||||||
|
@ -185,7 +185,7 @@ add_task(function test_revived_history_from_non_remote() {
|
||||||
yield TabStateFlusher.flush(browser);
|
yield TabStateFlusher.flush(browser);
|
||||||
|
|
||||||
// Crash the tab
|
// Crash the tab
|
||||||
yield crashBrowser(browser);
|
yield BrowserTestUtils.crashBrowser(browser);
|
||||||
|
|
||||||
// Browse to a new site that will not cause the browser to
|
// Browse to a new site that will not cause the browser to
|
||||||
// become remote again.
|
// become remote again.
|
||||||
|
@ -235,7 +235,7 @@ add_task(function test_revive_tab_from_session_store() {
|
||||||
yield TabStateFlusher.flush(browser);
|
yield TabStateFlusher.flush(browser);
|
||||||
|
|
||||||
// Crash the tab
|
// Crash the tab
|
||||||
yield crashBrowser(browser);
|
yield BrowserTestUtils.crashBrowser(browser);
|
||||||
is(newTab2.getAttribute("crashed"), "true", "Second tab should be crashed too.");
|
is(newTab2.getAttribute("crashed"), "true", "Second tab should be crashed too.");
|
||||||
|
|
||||||
// Use SessionStore to revive the tab
|
// Use SessionStore to revive the tab
|
||||||
|
@ -286,7 +286,7 @@ add_task(function test_revive_all_tabs_from_session_store() {
|
||||||
yield TabStateFlusher.flush(browser2);
|
yield TabStateFlusher.flush(browser2);
|
||||||
|
|
||||||
// Crash the tab
|
// Crash the tab
|
||||||
yield crashBrowser(browser);
|
yield BrowserTestUtils.crashBrowser(browser);
|
||||||
is(newTab2.getAttribute("crashed"), "true", "Second tab should be crashed too.");
|
is(newTab2.getAttribute("crashed"), "true", "Second tab should be crashed too.");
|
||||||
|
|
||||||
// Use SessionStore to revive all the tabs
|
// Use SessionStore to revive all the tabs
|
||||||
|
@ -331,7 +331,7 @@ add_task(function test_close_tab_after_crash() {
|
||||||
yield TabStateFlusher.flush(browser);
|
yield TabStateFlusher.flush(browser);
|
||||||
|
|
||||||
// Crash the tab
|
// Crash the tab
|
||||||
yield crashBrowser(browser);
|
yield BrowserTestUtils.crashBrowser(browser);
|
||||||
|
|
||||||
let promise = promiseEvent(gBrowser.tabContainer, "TabClose");
|
let promise = promiseEvent(gBrowser.tabContainer, "TabClose");
|
||||||
|
|
||||||
|
@ -359,7 +359,7 @@ add_task(function* test_hide_restore_all_button() {
|
||||||
yield TabStateFlusher.flush(browser);
|
yield TabStateFlusher.flush(browser);
|
||||||
|
|
||||||
// Crash the tab
|
// Crash the tab
|
||||||
yield crashBrowser(browser);
|
yield BrowserTestUtils.crashBrowser(browser);
|
||||||
|
|
||||||
let doc = browser.contentDocument;
|
let doc = browser.contentDocument;
|
||||||
let restoreAllButton = doc.getElementById("restoreAll");
|
let restoreAllButton = doc.getElementById("restoreAll");
|
||||||
|
@ -375,7 +375,7 @@ add_task(function* test_hide_restore_all_button() {
|
||||||
yield promiseBrowserLoaded(browser);
|
yield promiseBrowserLoaded(browser);
|
||||||
|
|
||||||
// Crash the tab
|
// Crash the tab
|
||||||
yield crashBrowser(browser);
|
yield BrowserTestUtils.crashBrowser(browser);
|
||||||
|
|
||||||
doc = browser.contentDocument;
|
doc = browser.contentDocument;
|
||||||
restoreAllButton = doc.getElementById("restoreAll");
|
restoreAllButton = doc.getElementById("restoreAll");
|
||||||
|
@ -405,7 +405,7 @@ add_task(function* test_aboutcrashedtabzoom() {
|
||||||
yield TabStateFlusher.flush(browser);
|
yield TabStateFlusher.flush(browser);
|
||||||
|
|
||||||
// Crash the tab
|
// Crash the tab
|
||||||
yield crashBrowser(browser);
|
yield BrowserTestUtils.crashBrowser(browser);
|
||||||
|
|
||||||
ok(ZoomManager.getZoomForBrowser(browser) === 1, "zoom should have reset on crash");
|
ok(ZoomManager.getZoomForBrowser(browser) === 1, "zoom should have reset on crash");
|
||||||
|
|
||||||
|
|
|
@ -538,112 +538,6 @@ function promiseRemoveTab(tab) {
|
||||||
return BrowserTestUtils.removeTab(tab);
|
return BrowserTestUtils.removeTab(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a Promise that resolves once a remote <xul:browser> has experienced
|
|
||||||
* a crash. Also does the job of cleaning up the minidump of the crash.
|
|
||||||
*
|
|
||||||
* @param browser
|
|
||||||
* The <xul:browser> that will crash
|
|
||||||
* @return Promise
|
|
||||||
*/
|
|
||||||
function crashBrowser(browser) {
|
|
||||||
/**
|
|
||||||
* Returns the directory where crash dumps are stored.
|
|
||||||
*
|
|
||||||
* @return nsIFile
|
|
||||||
*/
|
|
||||||
function getMinidumpDirectory() {
|
|
||||||
let dir = Services.dirsvc.get('ProfD', Ci.nsIFile);
|
|
||||||
dir.append("minidumps");
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes a file from a directory. This is a no-op if the file does not
|
|
||||||
* exist.
|
|
||||||
*
|
|
||||||
* @param directory
|
|
||||||
* The nsIFile representing the directory to remove from.
|
|
||||||
* @param filename
|
|
||||||
* A string for the file to remove from the directory.
|
|
||||||
*/
|
|
||||||
function removeFile(directory, filename) {
|
|
||||||
let file = directory.clone();
|
|
||||||
file.append(filename);
|
|
||||||
if (file.exists()) {
|
|
||||||
file.remove(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This frame script is injected into the remote browser, and used to
|
|
||||||
// intentionally crash the tab. We crash by using js-ctypes and dereferencing
|
|
||||||
// a bad pointer. The crash should happen immediately upon loading this
|
|
||||||
// frame script.
|
|
||||||
let frame_script = () => {
|
|
||||||
const Cu = Components.utils;
|
|
||||||
Cu.import("resource://gre/modules/ctypes.jsm");
|
|
||||||
|
|
||||||
let dies = function() {
|
|
||||||
privateNoteIntentionalCrash();
|
|
||||||
let zero = new ctypes.intptr_t(8);
|
|
||||||
let badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
|
|
||||||
badptr.contents
|
|
||||||
};
|
|
||||||
|
|
||||||
dump("Et tu, Brute?");
|
|
||||||
dies();
|
|
||||||
}
|
|
||||||
|
|
||||||
let crashCleanupPromise = new Promise((resolve, reject) => {
|
|
||||||
let observer = (subject, topic, data) => {
|
|
||||||
is(topic, 'ipc:content-shutdown', 'Received correct observer topic.');
|
|
||||||
ok(subject instanceof Ci.nsIPropertyBag2,
|
|
||||||
'Subject implements nsIPropertyBag2.');
|
|
||||||
// we might see this called as the process terminates due to previous tests.
|
|
||||||
// We are only looking for "abnormal" exits...
|
|
||||||
if (!subject.hasKey("abnormal")) {
|
|
||||||
info("This is a normal termination and isn't the one we are looking for...");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let dumpID;
|
|
||||||
if ('nsICrashReporter' in Ci) {
|
|
||||||
dumpID = subject.getPropertyAsAString('dumpID');
|
|
||||||
ok(dumpID, "dumpID is present and not an empty string");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dumpID) {
|
|
||||||
let minidumpDirectory = getMinidumpDirectory();
|
|
||||||
removeFile(minidumpDirectory, dumpID + '.dmp');
|
|
||||||
removeFile(minidumpDirectory, dumpID + '.extra');
|
|
||||||
}
|
|
||||||
|
|
||||||
Services.obs.removeObserver(observer, 'ipc:content-shutdown');
|
|
||||||
info("Crash cleaned up");
|
|
||||||
resolve();
|
|
||||||
};
|
|
||||||
|
|
||||||
Services.obs.addObserver(observer, 'ipc:content-shutdown');
|
|
||||||
});
|
|
||||||
|
|
||||||
let aboutTabCrashedLoadPromise = new Promise((resolve, reject) => {
|
|
||||||
browser.addEventListener("AboutTabCrashedLoad", function onCrash() {
|
|
||||||
browser.removeEventListener("AboutTabCrashedLoad", onCrash, false);
|
|
||||||
info("about:tabcrashed loaded");
|
|
||||||
resolve();
|
|
||||||
}, false, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
// This frame script will crash the remote browser as soon as it is
|
|
||||||
// evaluated.
|
|
||||||
let mm = browser.messageManager;
|
|
||||||
mm.loadFrameScript("data:,(" + frame_script.toString() + ")();", false);
|
|
||||||
return Promise.all([crashCleanupPromise, aboutTabCrashedLoadPromise]).then(() => {
|
|
||||||
let tab = gBrowser.getTabForBrowser(browser);
|
|
||||||
is(tab.getAttribute("crashed"), "true", "Tab should be marked as crashed");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write DOMSessionStorage data to the given browser.
|
// Write DOMSessionStorage data to the given browser.
|
||||||
function modifySessionStorage(browser, data, options = {}) {
|
function modifySessionStorage(browser, data, options = {}) {
|
||||||
return ContentTask.spawn(browser, [data, options], function* ([data, options]) {
|
return ContentTask.spawn(browser, [data, options], function* ([data, options]) {
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
<!ENTITY tabCrashed.header "Bad news first: This tab has crashed">
|
<!ENTITY tabCrashed.header "Bad news first: This tab has crashed">
|
||||||
<!ENTITY tabCrashed.message "Now for the good news: You can just close this tab, restore it or restore all your crashed tabs.">
|
<!ENTITY tabCrashed.message "Now for the good news: You can just close this tab, restore it or restore all your crashed tabs.">
|
||||||
<!ENTITY tabCrashed.sendReport "Submit a crash report to help prevent more bad news">
|
<!ENTITY tabCrashed.sendReport "Submit a crash report to help prevent more bad news">
|
||||||
|
<!ENTITY tabCrashed.includeURL "Include the address of the page I was on">
|
||||||
|
<!ENTITY tabCrashed.commentPlaceholder "Add a comment (comments are publicly visible)">
|
||||||
|
<!ENTITY tabCrashed.emailPlaceholder "Enter your email address here">
|
||||||
|
<!ENTITY tabCrashed.emailMe "Email me when more information is available">
|
||||||
|
<!ENTITY tabCrashed.crashReporter "Mozilla Crash Reporter">
|
||||||
<!ENTITY tabCrashed.reportSent "Crash report already submitted; thank you for helping make &brandShortName; better!">
|
<!ENTITY tabCrashed.reportSent "Crash report already submitted; thank you for helping make &brandShortName; better!">
|
||||||
<!ENTITY tabCrashed.closeTab "Close This Tab">
|
<!ENTITY tabCrashed.closeTab "Close This Tab">
|
||||||
<!ENTITY tabCrashed.restoreTab "Restore This Tab">
|
<!ENTITY tabCrashed.restoreTab "Restore This Tab">
|
||||||
|
|
|
@ -17,6 +17,11 @@ XPCOMUtils.defineLazyModuleGetter(this, "CrashSubmit",
|
||||||
"resource://gre/modules/CrashSubmit.jsm");
|
"resource://gre/modules/CrashSubmit.jsm");
|
||||||
|
|
||||||
this.TabCrashReporter = {
|
this.TabCrashReporter = {
|
||||||
|
get prefs() {
|
||||||
|
delete this.prefs;
|
||||||
|
return this.prefs = Services.prefs.getBranch("browser.tabs.crashReporting.");
|
||||||
|
},
|
||||||
|
|
||||||
init: function () {
|
init: function () {
|
||||||
if (this.initialized)
|
if (this.initialized)
|
||||||
return;
|
return;
|
||||||
|
@ -47,21 +52,66 @@ this.TabCrashReporter = {
|
||||||
if (!browser)
|
if (!browser)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.browserMap.set(browser, aSubject.childID);
|
this.browserMap.set(browser.permanentKey, aSubject.childID);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
submitCrashReport: function (aBrowser) {
|
/**
|
||||||
let childID = this.browserMap.get(aBrowser);
|
* Submits a crash report from about:tabcrashed
|
||||||
|
*
|
||||||
|
* @param aBrowser
|
||||||
|
* The <xul:browser> that the report was sent from.
|
||||||
|
* @param aFormData
|
||||||
|
* An Object with the following properties:
|
||||||
|
*
|
||||||
|
* includeURL (bool):
|
||||||
|
* Whether to include the URL that the user was on
|
||||||
|
* in the crashed tab before the crash occurred.
|
||||||
|
* URL (String)
|
||||||
|
* The URL that the user was on in the crashed tab
|
||||||
|
* before the crash occurred.
|
||||||
|
* emailMe (bool):
|
||||||
|
* Whether or not to include the user's email address
|
||||||
|
* in the crash report.
|
||||||
|
* email (String):
|
||||||
|
* The email address of the user.
|
||||||
|
* comments (String):
|
||||||
|
* Any additional comments from the user.
|
||||||
|
*
|
||||||
|
* Note that it is expected that all properties are set,
|
||||||
|
* even if they are empty.
|
||||||
|
*/
|
||||||
|
submitCrashReport: function (aBrowser, aFormData) {
|
||||||
|
let childID = this.browserMap.get(aBrowser.permanentKey);
|
||||||
let dumpID = this.childMap.get(childID);
|
let dumpID = this.childMap.get(childID);
|
||||||
if (!dumpID)
|
if (!dumpID)
|
||||||
return
|
return
|
||||||
|
|
||||||
if (CrashSubmit.submit(dumpID, { recordSubmission: true })) {
|
CrashSubmit.submit(dumpID, {
|
||||||
this.childMap.set(childID, null); // Avoid resubmission.
|
recordSubmission: true,
|
||||||
this.removeSubmitCheckboxesForSameCrash(childID);
|
extraExtraKeyVals: {
|
||||||
|
Comments: aFormData.comments,
|
||||||
|
Email: aFormData.email,
|
||||||
|
URL: aFormData.URL,
|
||||||
|
},
|
||||||
|
}).then(null, Cu.reportError);
|
||||||
|
|
||||||
|
this.prefs.setBoolPref("sendReport", true);
|
||||||
|
this.prefs.setBoolPref("includeURL", aFormData.includeURL);
|
||||||
|
this.prefs.setBoolPref("emailMe", aFormData.emailMe);
|
||||||
|
if (aFormData.emailMe) {
|
||||||
|
this.prefs.setCharPref("email", aFormData.email);
|
||||||
|
} else {
|
||||||
|
this.prefs.setCharPref("email", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.childMap.set(childID, null); // Avoid resubmission.
|
||||||
|
this.removeSubmitCheckboxesForSameCrash(childID);
|
||||||
|
},
|
||||||
|
|
||||||
|
dontSubmitCrashReport: function() {
|
||||||
|
this.prefs.setBoolPref("sendReport", false);
|
||||||
},
|
},
|
||||||
|
|
||||||
removeSubmitCheckboxesForSameCrash: function(childID) {
|
removeSubmitCheckboxesForSameCrash: function(childID) {
|
||||||
|
@ -79,8 +129,8 @@ this.TabCrashReporter = {
|
||||||
if (!doc.documentURI.startsWith("about:tabcrashed"))
|
if (!doc.documentURI.startsWith("about:tabcrashed"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (this.browserMap.get(browser) == childID) {
|
if (this.browserMap.get(browser.permanentKey) == childID) {
|
||||||
this.browserMap.delete(browser);
|
this.browserMap.delete(browser.permanentKey);
|
||||||
browser.contentDocument.documentElement.classList.remove("crashDumpAvailable");
|
browser.contentDocument.documentElement.classList.remove("crashDumpAvailable");
|
||||||
browser.contentDocument.documentElement.classList.add("crashDumpSubmitted");
|
browser.contentDocument.documentElement.classList.add("crashDumpSubmitted");
|
||||||
}
|
}
|
||||||
|
@ -97,11 +147,27 @@ this.TabCrashReporter = {
|
||||||
if (!this.childMap)
|
if (!this.childMap)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
let dumpID = this.childMap.get(this.browserMap.get(aBrowser));
|
let dumpID = this.childMap.get(this.browserMap.get(aBrowser.permanentKey));
|
||||||
if (!dumpID)
|
if (!dumpID)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
aBrowser.contentDocument.documentElement.classList.add("crashDumpAvailable");
|
let doc = aBrowser.contentDocument;
|
||||||
|
|
||||||
|
doc.documentElement.classList.add("crashDumpAvailable");
|
||||||
|
|
||||||
|
let sendReport = this.prefs.getBoolPref("sendReport");
|
||||||
|
doc.getElementById("sendReport").checked = sendReport;
|
||||||
|
|
||||||
|
let includeURL = this.prefs.getBoolPref("includeURL");
|
||||||
|
doc.getElementById("includeURL").checked = includeURL;
|
||||||
|
|
||||||
|
let emailMe = this.prefs.getBoolPref("emailMe");
|
||||||
|
doc.getElementById("emailMe").checked = emailMe;
|
||||||
|
|
||||||
|
if (emailMe) {
|
||||||
|
let email = this.prefs.getCharPref("email", "");
|
||||||
|
doc.getElementById("email").value = email;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
hideRestoreAllButton: function (aBrowser) {
|
hideRestoreAllButton: function (aBrowser) {
|
||||||
|
|
|
@ -98,12 +98,6 @@
|
||||||
-moz-appearance: -moz-window-titlebar;
|
-moz-appearance: -moz-window-titlebar;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (-moz-mac-yosemite-theme) {
|
|
||||||
#main-window:not(:-moz-lwtheme) > #titlebar {
|
|
||||||
-moz-appearance: -moz-mac-vibrancy-light;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#main-window:not([tabsintitlebar]) > #titlebar {
|
#main-window:not([tabsintitlebar]) > #titlebar {
|
||||||
height: 22px; /* The native titlebar on OS X is 22px tall. */
|
height: 22px; /* The native titlebar on OS X is 22px tall. */
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,3 +9,34 @@
|
||||||
#reportSent {
|
#reportSent {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#crash-reporter-container {
|
||||||
|
width: 80%;
|
||||||
|
background-color: var(--in-content-box-background-hover);
|
||||||
|
margin: 24px 0;
|
||||||
|
padding: 14px;
|
||||||
|
border: 1px solid var(--in-content-box-border-color);
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#crash-reporter-title {
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0 0 14px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"],
|
||||||
|
textarea {
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#options {
|
||||||
|
list-style: none;
|
||||||
|
margin-inline-start: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"],
|
||||||
|
#options > li {
|
||||||
|
margin: 14px 0 0 0;
|
||||||
|
}
|
||||||
|
|
|
@ -589,6 +589,7 @@ description > html|a {
|
||||||
}
|
}
|
||||||
|
|
||||||
.fxaAccountBoxButtons > button {
|
.fxaAccountBoxButtons > button {
|
||||||
|
text-align: center;
|
||||||
padding-left: 11px;
|
padding-left: 11px;
|
||||||
padding-right: 11px;
|
padding-right: 11px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
|
@ -2013,7 +2013,7 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--tab-toolbar-navbar-overlap: 0;
|
--tab-toolbar-navbar-overlap: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#nav-bar {
|
#nav-bar {
|
||||||
|
|
|
@ -223,9 +223,7 @@ menu.subviewbutton > .menu-right:-moz-locale-dir(rtl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#BMB_bookmarksPopup menupopup[placespopup=true] > hbox {
|
#BMB_bookmarksPopup menupopup[placespopup=true] > hbox {
|
||||||
/* After fixing of bug 1194480 the box-shadow can be removed again */
|
box-shadow: none;
|
||||||
/* box-shadow: none; */
|
|
||||||
box-shadow: 0 0 4px rgba(0,0,0,0.02);
|
|
||||||
background: -moz-field;
|
background: -moz-field;
|
||||||
border: 1px solid ThreeDShadow;
|
border: 1px solid ThreeDShadow;
|
||||||
}
|
}
|
||||||
|
|
|
@ -567,6 +567,8 @@ skip-if = e10s && debug
|
||||||
skip-if = e10s && debug
|
skip-if = e10s && debug
|
||||||
[browser_dbg_watch-expressions-02.js]
|
[browser_dbg_watch-expressions-02.js]
|
||||||
skip-if = e10s && debug
|
skip-if = e10s && debug
|
||||||
|
[browser_dbg_worker-window.js]
|
||||||
|
skip-if = e10s && debug
|
||||||
[browser_dbg_WorkerActor.attach.js]
|
[browser_dbg_WorkerActor.attach.js]
|
||||||
skip-if = e10s && debug
|
skip-if = e10s && debug
|
||||||
[browser_dbg_WorkerActor.attachThread.js]
|
[browser_dbg_WorkerActor.attachThread.js]
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
// Check to make sure that a worker can be attached to a toolbox
|
||||||
|
// directly, and that the toolbox has expected properties.
|
||||||
|
|
||||||
|
var TAB_URL = EXAMPLE_URL + "doc_WorkerActor.attachThread-tab.html";
|
||||||
|
var WORKER_URL = "code_WorkerActor.attachThread-worker.js";
|
||||||
|
|
||||||
|
add_task(function* () {
|
||||||
|
DebuggerServer.init();
|
||||||
|
DebuggerServer.addBrowserActors();
|
||||||
|
|
||||||
|
let client = new DebuggerClient(DebuggerServer.connectPipe());
|
||||||
|
yield connect(client);
|
||||||
|
|
||||||
|
let tab = yield addTab(TAB_URL);
|
||||||
|
let { tabs } = yield listTabs(client);
|
||||||
|
let [, tabClient] = yield attachTab(client, findTab(tabs, TAB_URL));
|
||||||
|
|
||||||
|
yield listWorkers(tabClient);
|
||||||
|
yield createWorkerInTab(tab, WORKER_URL);
|
||||||
|
|
||||||
|
let { workers } = yield listWorkers(tabClient);
|
||||||
|
let [, workerClient] = yield attachWorker(tabClient,
|
||||||
|
findWorker(workers, WORKER_URL));
|
||||||
|
|
||||||
|
let toolbox = yield gDevTools.showToolbox(TargetFactory.forWorker(workerClient),
|
||||||
|
"jsdebugger",
|
||||||
|
Toolbox.HostType.WINDOW);
|
||||||
|
|
||||||
|
is(toolbox._host.type, "window", "correct host");
|
||||||
|
ok(toolbox._host._window.document.title.contains(WORKER_URL),
|
||||||
|
"worker URL in host title");
|
||||||
|
|
||||||
|
let toolTabs = toolbox.doc.querySelectorAll(".devtools-tab");
|
||||||
|
let activeTools = [...toolTabs].map(tab=>tab.getAttribute("toolid"));
|
||||||
|
|
||||||
|
is(activeTools.join(","), "webconsole,jsdebugger,scratchpad,options",
|
||||||
|
"Correct set of tools supported by worker");
|
||||||
|
|
||||||
|
yield gDevTools.closeToolbox(TargetFactory.forWorker(workerClient));
|
||||||
|
terminateWorkerInTab(tab, WORKER_URL);
|
||||||
|
yield waitForWorkerClose(workerClient);
|
||||||
|
yield close(client);
|
||||||
|
});
|
|
@ -856,6 +856,10 @@ WorkerTarget.prototype = {
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get url() {
|
||||||
|
return this._workerClient.url;
|
||||||
|
},
|
||||||
|
|
||||||
get form() {
|
get form() {
|
||||||
return {
|
return {
|
||||||
from: this._workerClient.actor,
|
from: this._workerClient.actor,
|
||||||
|
|
|
@ -1493,10 +1493,8 @@ Toolbox.prototype = {
|
||||||
toolName = toolboxStrings("toolbox.defaultTitle");
|
toolName = toolboxStrings("toolbox.defaultTitle");
|
||||||
}
|
}
|
||||||
let title = toolboxStrings("toolbox.titleTemplate",
|
let title = toolboxStrings("toolbox.titleTemplate",
|
||||||
toolName,
|
toolName, this.target.name ||
|
||||||
this.target.isAddon ?
|
this.target.url);
|
||||||
this.target.name :
|
|
||||||
this.target.url || this.target.name);
|
|
||||||
this._host.setTitle(title);
|
this._host.setTitle(title);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ const {
|
||||||
throttle
|
throttle
|
||||||
} = require("devtools/client/styleinspector/utils");
|
} = require("devtools/client/styleinspector/utils");
|
||||||
const {
|
const {
|
||||||
|
escapeCSSComment,
|
||||||
parseDeclarations,
|
parseDeclarations,
|
||||||
parseSingleValue,
|
parseSingleValue,
|
||||||
parsePseudoClassesAndAttributes,
|
parsePseudoClassesAndAttributes,
|
||||||
|
@ -1117,7 +1118,7 @@ TextProperty.prototype = {
|
||||||
|
|
||||||
// Comment out property declarations that are not enabled
|
// Comment out property declarations that are not enabled
|
||||||
if (!this.enabled) {
|
if (!this.enabled) {
|
||||||
declaration = "/* " + declaration + " */";
|
declaration = "/* " + escapeCSSComment(declaration) + " */";
|
||||||
}
|
}
|
||||||
|
|
||||||
return declaration;
|
return declaration;
|
||||||
|
|
|
@ -103,6 +103,7 @@ add_task(function*() {
|
||||||
"\tbackground-color: #00F;[\\r\\n]+" +
|
"\tbackground-color: #00F;[\\r\\n]+" +
|
||||||
"\tfont-size: 12px;[\\r\\n]+" +
|
"\tfont-size: 12px;[\\r\\n]+" +
|
||||||
"\tborder-color: #00F !important;[\\r\\n]+" +
|
"\tborder-color: #00F !important;[\\r\\n]+" +
|
||||||
|
"\t--var: \"\\*/\";[\\r\\n]+" +
|
||||||
"}",
|
"}",
|
||||||
hidden: {
|
hidden: {
|
||||||
copyLocation: true,
|
copyLocation: true,
|
||||||
|
@ -144,7 +145,7 @@ add_task(function*() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
setup: function*() {
|
setup: function*() {
|
||||||
yield disableProperty(view);
|
yield disableProperty(view, 0);
|
||||||
},
|
},
|
||||||
desc: "Test Copy Rule with Disabled Property",
|
desc: "Test Copy Rule with Disabled Property",
|
||||||
node: ruleEditor.rule.textProps[2].editor.nameSpan,
|
node: ruleEditor.rule.textProps[2].editor.nameSpan,
|
||||||
|
@ -154,6 +155,30 @@ add_task(function*() {
|
||||||
"\tbackground-color: #00F;[\\r\\n]+" +
|
"\tbackground-color: #00F;[\\r\\n]+" +
|
||||||
"\tfont-size: 12px;[\\r\\n]+" +
|
"\tfont-size: 12px;[\\r\\n]+" +
|
||||||
"\tborder-color: #00F !important;[\\r\\n]+" +
|
"\tborder-color: #00F !important;[\\r\\n]+" +
|
||||||
|
"\t--var: \"\\*/\";[\\r\\n]+" +
|
||||||
|
"}",
|
||||||
|
hidden: {
|
||||||
|
copyLocation: true,
|
||||||
|
copyPropertyDeclaration: false,
|
||||||
|
copyPropertyName: false,
|
||||||
|
copyPropertyValue: true,
|
||||||
|
copySelector: true,
|
||||||
|
copyRule: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
setup: function*() {
|
||||||
|
yield disableProperty(view, 4);
|
||||||
|
},
|
||||||
|
desc: "Test Copy Rule with Disabled Property with Comment",
|
||||||
|
node: ruleEditor.rule.textProps[2].editor.nameSpan,
|
||||||
|
menuItem: contextmenu.menuitemCopyRule,
|
||||||
|
expectedPattern: "#testid {[\\r\\n]+" +
|
||||||
|
"\t\/\\* color: #F00; \\*\/[\\r\\n]+" +
|
||||||
|
"\tbackground-color: #00F;[\\r\\n]+" +
|
||||||
|
"\tfont-size: 12px;[\\r\\n]+" +
|
||||||
|
"\tborder-color: #00F !important;[\\r\\n]+" +
|
||||||
|
"\t/\\* --var: \"\\*\\\\\/\"; \\*\/[\\r\\n]+" +
|
||||||
"}",
|
"}",
|
||||||
hidden: {
|
hidden: {
|
||||||
copyLocation: true,
|
copyLocation: true,
|
||||||
|
@ -241,9 +266,9 @@ function* checkCopyStyle(view, node, menuItem, expectedPattern, hidden) {
|
||||||
view._contextmenu._menupopup.hidePopup();
|
view._contextmenu._menupopup.hidePopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
function* disableProperty(view) {
|
function* disableProperty(view, index) {
|
||||||
let ruleEditor = getRuleViewRuleEditor(view, 1);
|
let ruleEditor = getRuleViewRuleEditor(view, 1);
|
||||||
let propEditor = ruleEditor.rule.textProps[0].editor;
|
let propEditor = ruleEditor.rule.textProps[index].editor;
|
||||||
|
|
||||||
info("Disabling a property");
|
info("Disabling a property");
|
||||||
propEditor.enable.click();
|
propEditor.enable.click();
|
||||||
|
|
|
@ -7,4 +7,5 @@ html, body, #testid {
|
||||||
background-color: #00F;
|
background-color: #00F;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
border-color: #00F !important;
|
border-color: #00F !important;
|
||||||
|
--var: "*/";
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,11 +86,11 @@ AvStatusToSinkString(BluetoothA2dpConnectionState aState, nsAString& aString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BluetoothA2dpManager::InitA2dpResultHandler final
|
class BluetoothA2dpManager::InitResultHandler final
|
||||||
: public BluetoothA2dpResultHandler
|
: public BluetoothA2dpResultHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InitA2dpResultHandler(BluetoothProfileResultHandler* aRes)
|
InitResultHandler(BluetoothProfileResultHandler* aRes)
|
||||||
: mRes(aRes)
|
: mRes(aRes)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ BluetoothA2dpManager::InitA2dpInterface(BluetoothProfileResultHandler* aRes)
|
||||||
}
|
}
|
||||||
|
|
||||||
BluetoothA2dpManager* a2dpManager = BluetoothA2dpManager::Get();
|
BluetoothA2dpManager* a2dpManager = BluetoothA2dpManager::Get();
|
||||||
sBtA2dpInterface->Init(a2dpManager, new InitA2dpResultHandler(aRes));
|
sBtA2dpInterface->Init(a2dpManager, new InitResultHandler(aRes));
|
||||||
}
|
}
|
||||||
|
|
||||||
BluetoothA2dpManager::~BluetoothA2dpManager()
|
BluetoothA2dpManager::~BluetoothA2dpManager()
|
||||||
|
@ -227,11 +227,11 @@ BluetoothA2dpManager::Get()
|
||||||
return sBluetoothA2dpManager;
|
return sBluetoothA2dpManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BluetoothA2dpManager::CleanupA2dpResultHandler final
|
class BluetoothA2dpManager::CleanupResultHandler final
|
||||||
: public BluetoothA2dpResultHandler
|
: public BluetoothA2dpResultHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CleanupA2dpResultHandler(BluetoothProfileResultHandler* aRes)
|
CleanupResultHandler(BluetoothProfileResultHandler* aRes)
|
||||||
: mRes(aRes)
|
: mRes(aRes)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
@ -260,11 +260,11 @@ private:
|
||||||
nsRefPtr<BluetoothProfileResultHandler> mRes;
|
nsRefPtr<BluetoothProfileResultHandler> mRes;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BluetoothA2dpManager::CleanupA2dpResultHandlerRunnable final
|
class BluetoothA2dpManager::CleanupResultHandlerRunnable final
|
||||||
: public nsRunnable
|
: public nsRunnable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CleanupA2dpResultHandlerRunnable(BluetoothProfileResultHandler* aRes)
|
CleanupResultHandlerRunnable(BluetoothProfileResultHandler* aRes)
|
||||||
: mRes(aRes)
|
: mRes(aRes)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
@ -289,11 +289,11 @@ BluetoothA2dpManager::DeinitA2dpInterface(BluetoothProfileResultHandler* aRes)
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (sBtA2dpInterface) {
|
if (sBtA2dpInterface) {
|
||||||
sBtA2dpInterface->Cleanup(new CleanupA2dpResultHandler(aRes));
|
sBtA2dpInterface->Cleanup(new CleanupResultHandler(aRes));
|
||||||
} else if (aRes) {
|
} else if (aRes) {
|
||||||
// We dispatch a runnable here to make the profile resource handler
|
// We dispatch a runnable here to make the profile resource handler
|
||||||
// behave as if A2DP was initialized.
|
// behave as if A2DP was initialized.
|
||||||
nsRefPtr<nsRunnable> r = new CleanupA2dpResultHandlerRunnable(aRes);
|
nsRefPtr<nsRunnable> r = new CleanupResultHandlerRunnable(aRes);
|
||||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||||
BT_LOGR("Failed to dispatch cleanup-result-handler runnable");
|
BT_LOGR("Failed to dispatch cleanup-result-handler runnable");
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,11 +47,11 @@ protected:
|
||||||
virtual ~BluetoothA2dpManager();
|
virtual ~BluetoothA2dpManager();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class CleanupA2dpResultHandler;
|
class CleanupResultHandler;
|
||||||
class CleanupA2dpResultHandlerRunnable;
|
class CleanupResultHandlerRunnable;
|
||||||
class ConnectResultHandler;
|
class ConnectResultHandler;
|
||||||
class DisconnectResultHandler;
|
class DisconnectResultHandler;
|
||||||
class InitA2dpResultHandler;
|
class InitResultHandler;
|
||||||
class OnErrorProfileResultHandlerRunnable;
|
class OnErrorProfileResultHandlerRunnable;
|
||||||
|
|
||||||
BluetoothA2dpManager();
|
BluetoothA2dpManager();
|
||||||
|
|
|
@ -118,11 +118,11 @@ BluetoothAvrcpManager::Reset()
|
||||||
mPlayStatus = ControlPlayStatus::PLAYSTATUS_STOPPED;
|
mPlayStatus = ControlPlayStatus::PLAYSTATUS_STOPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BluetoothAvrcpManager::InitAvrcpResultHandler final
|
class BluetoothAvrcpManager::InitResultHandler final
|
||||||
: public BluetoothAvrcpResultHandler
|
: public BluetoothAvrcpResultHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InitAvrcpResultHandler(BluetoothProfileResultHandler* aRes)
|
InitResultHandler(BluetoothProfileResultHandler* aRes)
|
||||||
: mRes(aRes)
|
: mRes(aRes)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ BluetoothAvrcpManager::InitAvrcpInterface(BluetoothProfileResultHandler* aRes)
|
||||||
}
|
}
|
||||||
|
|
||||||
BluetoothAvrcpManager* avrcpManager = BluetoothAvrcpManager::Get();
|
BluetoothAvrcpManager* avrcpManager = BluetoothAvrcpManager::Get();
|
||||||
sBtAvrcpInterface->Init(avrcpManager, new InitAvrcpResultHandler(aRes));
|
sBtAvrcpInterface->Init(avrcpManager, new InitResultHandler(aRes));
|
||||||
}
|
}
|
||||||
|
|
||||||
BluetoothAvrcpManager::~BluetoothAvrcpManager()
|
BluetoothAvrcpManager::~BluetoothAvrcpManager()
|
||||||
|
@ -245,11 +245,11 @@ BluetoothAvrcpManager::Get()
|
||||||
return sBluetoothAvrcpManager;
|
return sBluetoothAvrcpManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BluetoothAvrcpManager::CleanupAvrcpResultHandler final
|
class BluetoothAvrcpManager::CleanupResultHandler final
|
||||||
: public BluetoothAvrcpResultHandler
|
: public BluetoothAvrcpResultHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CleanupAvrcpResultHandler(BluetoothProfileResultHandler* aRes)
|
CleanupResultHandler(BluetoothProfileResultHandler* aRes)
|
||||||
: mRes(aRes)
|
: mRes(aRes)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
@ -285,25 +285,19 @@ private:
|
||||||
nsRefPtr<BluetoothProfileResultHandler> mRes;
|
nsRefPtr<BluetoothProfileResultHandler> mRes;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BluetoothAvrcpManager::CleanupAvrcpResultHandlerRunnable final
|
class BluetoothAvrcpManager::CleanupResultHandlerRunnable final
|
||||||
: public nsRunnable
|
: public nsRunnable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CleanupAvrcpResultHandlerRunnable(BluetoothProfileResultHandler* aRes)
|
CleanupResultHandlerRunnable(BluetoothProfileResultHandler* aRes)
|
||||||
: mRes(aRes)
|
: mRes(aRes)
|
||||||
{ }
|
{
|
||||||
|
MOZ_ASSERT(mRes);
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHOD Run() override
|
NS_IMETHOD Run() override
|
||||||
{
|
{
|
||||||
sBtAvrcpInterface = nullptr;
|
mRes->Deinit();
|
||||||
if (sBtAvrcpInterface) {
|
|
||||||
sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(mRes));
|
|
||||||
} else if (mRes) {
|
|
||||||
/* Not all backends support AVRCP. If it's not available
|
|
||||||
* we signal success from here.
|
|
||||||
*/
|
|
||||||
mRes->Deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -319,11 +313,11 @@ BluetoothAvrcpManager::DeinitAvrcpInterface(BluetoothProfileResultHandler* aRes)
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
if (sBtAvrcpInterface) {
|
if (sBtAvrcpInterface) {
|
||||||
sBtAvrcpInterface->Cleanup(new CleanupAvrcpResultHandler(aRes));
|
sBtAvrcpInterface->Cleanup(new CleanupResultHandler(aRes));
|
||||||
} else if (aRes) {
|
} else if (aRes) {
|
||||||
// We dispatch a runnable here to make the profile resource handler
|
// We dispatch a runnable here to make the profile resource handler
|
||||||
// behave as if A2DP was initialized.
|
// behave as if AVRCP was initialized.
|
||||||
nsRefPtr<nsRunnable> r = new CleanupAvrcpResultHandlerRunnable(aRes);
|
nsRefPtr<nsRunnable> r = new CleanupResultHandlerRunnable(aRes);
|
||||||
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
if (NS_FAILED(NS_DispatchToMainThread(r))) {
|
||||||
BT_LOGR("Failed to dispatch cleanup-result-handler runnable");
|
BT_LOGR("Failed to dispatch cleanup-result-handler runnable");
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,11 +60,11 @@ protected:
|
||||||
virtual ~BluetoothAvrcpManager();
|
virtual ~BluetoothAvrcpManager();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class CleanupAvrcpResultHandler;
|
class CleanupResultHandler;
|
||||||
class CleanupAvrcpResultHandlerRunnable;
|
class CleanupResultHandlerRunnable;
|
||||||
class ConnectRunnable;
|
class ConnectRunnable;
|
||||||
class DisconnectRunnable;
|
class DisconnectRunnable;
|
||||||
class InitAvrcpResultHandler;
|
class InitResultHandler;
|
||||||
class OnErrorProfileResultHandlerRunnable;
|
class OnErrorProfileResultHandlerRunnable;
|
||||||
|
|
||||||
BluetoothAvrcpManager();
|
BluetoothAvrcpManager();
|
||||||
|
|
|
@ -170,129 +170,31 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Init operator class for ConnectionStateNotification
|
|
||||||
class BluetoothDaemonA2dpModule::ConnectionStateInitOp final
|
|
||||||
: private PDUInitOp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ConnectionStateInitOp(DaemonSocketPDU& aPDU)
|
|
||||||
: PDUInitOp(aPDU)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
operator () (BluetoothA2dpConnectionState& aArg1,
|
|
||||||
BluetoothAddress& aArg2) const
|
|
||||||
{
|
|
||||||
DaemonSocketPDU& pdu = GetPDU();
|
|
||||||
|
|
||||||
/* Read state */
|
|
||||||
nsresult rv = UnpackPDU(pdu, aArg1);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read address */
|
|
||||||
rv = UnpackPDU(pdu, aArg2);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
WarnAboutTrailingData();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonA2dpModule::ConnectionStateNtf(
|
BluetoothDaemonA2dpModule::ConnectionStateNtf(
|
||||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
||||||
{
|
{
|
||||||
ConnectionStateNotification::Dispatch(
|
ConnectionStateNotification::Dispatch(
|
||||||
&BluetoothA2dpNotificationHandler::ConnectionStateNotification,
|
&BluetoothA2dpNotificationHandler::ConnectionStateNotification,
|
||||||
ConnectionStateInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for AudioStateNotification
|
|
||||||
class BluetoothDaemonA2dpModule::AudioStateInitOp final
|
|
||||||
: private PDUInitOp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AudioStateInitOp(DaemonSocketPDU& aPDU)
|
|
||||||
: PDUInitOp(aPDU)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
operator () (BluetoothA2dpAudioState& aArg1,
|
|
||||||
BluetoothAddress& aArg2) const
|
|
||||||
{
|
|
||||||
DaemonSocketPDU& pdu = GetPDU();
|
|
||||||
|
|
||||||
/* Read state */
|
|
||||||
nsresult rv = UnpackPDU(pdu, aArg1);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read address */
|
|
||||||
rv = UnpackPDU(pdu, aArg2);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
WarnAboutTrailingData();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonA2dpModule::AudioStateNtf(
|
BluetoothDaemonA2dpModule::AudioStateNtf(
|
||||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
||||||
{
|
{
|
||||||
AudioStateNotification::Dispatch(
|
AudioStateNotification::Dispatch(
|
||||||
&BluetoothA2dpNotificationHandler::AudioStateNotification,
|
&BluetoothA2dpNotificationHandler::AudioStateNotification,
|
||||||
AudioStateInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for AudioConfigNotification
|
|
||||||
class BluetoothDaemonA2dpModule::AudioConfigInitOp final
|
|
||||||
: private PDUInitOp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AudioConfigInitOp(DaemonSocketPDU& aPDU)
|
|
||||||
: PDUInitOp(aPDU)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
operator () (BluetoothAddress& aArg1, uint32_t aArg2, uint8_t aArg3) const
|
|
||||||
{
|
|
||||||
DaemonSocketPDU& pdu = GetPDU();
|
|
||||||
|
|
||||||
/* Read address */
|
|
||||||
nsresult rv = UnpackPDU(pdu, aArg1);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read sample rate */
|
|
||||||
rv = UnpackPDU(pdu, aArg2);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read channel count */
|
|
||||||
rv = UnpackPDU(pdu, aArg3);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
WarnAboutTrailingData();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonA2dpModule::AudioConfigNtf(
|
BluetoothDaemonA2dpModule::AudioConfigNtf(
|
||||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
||||||
{
|
{
|
||||||
AudioConfigNotification::Dispatch(
|
AudioConfigNotification::Dispatch(
|
||||||
&BluetoothA2dpNotificationHandler::AudioConfigNotification,
|
&BluetoothA2dpNotificationHandler::AudioConfigNotification,
|
||||||
AudioConfigInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -110,10 +110,6 @@ protected:
|
||||||
const BluetoothAddress&, uint32_t, uint8_t>
|
const BluetoothAddress&, uint32_t, uint8_t>
|
||||||
AudioConfigNotification;
|
AudioConfigNotification;
|
||||||
|
|
||||||
class ConnectionStateInitOp;
|
|
||||||
class AudioStateInitOp;
|
|
||||||
class AudioConfigInitOp;
|
|
||||||
|
|
||||||
void ConnectionStateNtf(const DaemonSocketPDUHeader& aHeader,
|
void ConnectionStateNtf(const DaemonSocketPDUHeader& aHeader,
|
||||||
DaemonSocketPDU& aPDU);
|
DaemonSocketPDU& aPDU);
|
||||||
|
|
||||||
|
|
|
@ -738,40 +738,13 @@ BluetoothDaemonAvrcpModule::VolumeChangeNtf(
|
||||||
UnpackPDUInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for PassthroughCmdNotification
|
|
||||||
class BluetoothDaemonAvrcpModule::PassthroughCmdInitOp final
|
|
||||||
: private PDUInitOp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PassthroughCmdInitOp(DaemonSocketPDU& aPDU)
|
|
||||||
: PDUInitOp(aPDU)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
operator () (int& aArg1, int& aArg2) const
|
|
||||||
{
|
|
||||||
DaemonSocketPDU& pdu = GetPDU();
|
|
||||||
|
|
||||||
nsresult rv = UnpackPDU(pdu, UnpackConversion<uint8_t, int>(aArg1));
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
rv = UnpackPDU(pdu, UnpackConversion<uint8_t, int>(aArg2));
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
WarnAboutTrailingData();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonAvrcpModule::PassthroughCmdNtf(
|
BluetoothDaemonAvrcpModule::PassthroughCmdNtf(
|
||||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
||||||
{
|
{
|
||||||
PassthroughCmdNotification::Dispatch(
|
PassthroughCmdNotification::Dispatch(
|
||||||
&BluetoothAvrcpNotificationHandler::PassthroughCmdNotification,
|
&BluetoothAvrcpNotificationHandler::PassthroughCmdNotification,
|
||||||
PassthroughCmdInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -243,14 +243,13 @@ protected:
|
||||||
VolumeChangeNotification;
|
VolumeChangeNotification;
|
||||||
|
|
||||||
typedef mozilla::ipc::DaemonNotificationRunnable2<
|
typedef mozilla::ipc::DaemonNotificationRunnable2<
|
||||||
NotificationHandlerWrapper, void, int, int>
|
NotificationHandlerWrapper, void, uint8_t, uint8_t, int, int>
|
||||||
PassthroughCmdNotification;
|
PassthroughCmdNotification;
|
||||||
|
|
||||||
class GetElementAttrInitOp;
|
class GetElementAttrInitOp;
|
||||||
class GetPlayerAppAttrsTextInitOp;
|
class GetPlayerAppAttrsTextInitOp;
|
||||||
class GetPlayerAppValueInitOp;
|
class GetPlayerAppValueInitOp;
|
||||||
class GetPlayerAppValuesTextInitOp;
|
class GetPlayerAppValuesTextInitOp;
|
||||||
class PassthroughCmdInitOp;
|
|
||||||
class RemoteFeatureInitOp;
|
class RemoteFeatureInitOp;
|
||||||
|
|
||||||
void RemoteFeatureNtf(const DaemonSocketPDUHeader& aHeader,
|
void RemoteFeatureNtf(const DaemonSocketPDUHeader& aHeader,
|
||||||
|
|
|
@ -945,201 +945,40 @@ BluetoothDaemonCoreModule::DiscoveryStateChangedNtf(
|
||||||
UnpackPDUInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for PinRequestNotification
|
|
||||||
class BluetoothDaemonCoreModule::PinRequestInitOp final
|
|
||||||
: private PDUInitOp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PinRequestInitOp(DaemonSocketPDU& aPDU)
|
|
||||||
: PDUInitOp(aPDU)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
operator () (BluetoothAddress& aArg1, BluetoothRemoteName& aArg2,
|
|
||||||
uint32_t& aArg3) const
|
|
||||||
{
|
|
||||||
DaemonSocketPDU& pdu = GetPDU();
|
|
||||||
|
|
||||||
/* Read remote address */
|
|
||||||
nsresult rv = UnpackPDU(pdu, aArg1);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read remote name */
|
|
||||||
rv = UnpackPDU(pdu, aArg2);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read CoD */
|
|
||||||
rv = UnpackPDU(pdu, aArg3);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
WarnAboutTrailingData();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonCoreModule::PinRequestNtf(
|
BluetoothDaemonCoreModule::PinRequestNtf(
|
||||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
||||||
{
|
{
|
||||||
PinRequestNotification::Dispatch(
|
PinRequestNotification::Dispatch(
|
||||||
&BluetoothNotificationHandler::PinRequestNotification,
|
&BluetoothNotificationHandler::PinRequestNotification,
|
||||||
PinRequestInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for SspRequestNotification
|
|
||||||
class BluetoothDaemonCoreModule::SspRequestInitOp final
|
|
||||||
: private PDUInitOp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SspRequestInitOp(DaemonSocketPDU& aPDU)
|
|
||||||
: PDUInitOp(aPDU)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
operator () (BluetoothAddress& aArg1, BluetoothRemoteName& aArg2,
|
|
||||||
uint32_t& aArg3, BluetoothSspVariant& aArg4,
|
|
||||||
uint32_t& aArg5) const
|
|
||||||
{
|
|
||||||
DaemonSocketPDU& pdu = GetPDU();
|
|
||||||
|
|
||||||
/* Read remote address */
|
|
||||||
nsresult rv = UnpackPDU(pdu, aArg1);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read remote name */
|
|
||||||
rv = UnpackPDU(pdu, aArg2);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read CoD */
|
|
||||||
rv = UnpackPDU(pdu, aArg3);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read pairing variant */
|
|
||||||
rv = UnpackPDU(pdu, aArg4);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read passkey */
|
|
||||||
rv = UnpackPDU(pdu, aArg5);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
WarnAboutTrailingData();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonCoreModule::SspRequestNtf(
|
BluetoothDaemonCoreModule::SspRequestNtf(
|
||||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
||||||
{
|
{
|
||||||
SspRequestNotification::Dispatch(
|
SspRequestNotification::Dispatch(
|
||||||
&BluetoothNotificationHandler::SspRequestNotification,
|
&BluetoothNotificationHandler::SspRequestNotification,
|
||||||
SspRequestInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for BondStateChangedNotification
|
|
||||||
class BluetoothDaemonCoreModule::BondStateChangedInitOp final
|
|
||||||
: private PDUInitOp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BondStateChangedInitOp(DaemonSocketPDU& aPDU)
|
|
||||||
: PDUInitOp(aPDU)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
operator () (BluetoothStatus& aArg1, BluetoothAddress& aArg2,
|
|
||||||
BluetoothBondState& aArg3) const
|
|
||||||
{
|
|
||||||
DaemonSocketPDU& pdu = GetPDU();
|
|
||||||
|
|
||||||
/* Read status */
|
|
||||||
nsresult rv = UnpackPDU(pdu, aArg1);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read remote address */
|
|
||||||
rv = UnpackPDU(pdu, aArg2);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read bond state */
|
|
||||||
rv = UnpackPDU(pdu, aArg3);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
WarnAboutTrailingData();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonCoreModule::BondStateChangedNtf(
|
BluetoothDaemonCoreModule::BondStateChangedNtf(
|
||||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
||||||
{
|
{
|
||||||
BondStateChangedNotification::Dispatch(
|
BondStateChangedNotification::Dispatch(
|
||||||
&BluetoothNotificationHandler::BondStateChangedNotification,
|
&BluetoothNotificationHandler::BondStateChangedNotification,
|
||||||
BondStateChangedInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for AclStateChangedNotification
|
|
||||||
class BluetoothDaemonCoreModule::AclStateChangedInitOp final
|
|
||||||
: private PDUInitOp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AclStateChangedInitOp(DaemonSocketPDU& aPDU)
|
|
||||||
: PDUInitOp(aPDU)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
operator () (BluetoothStatus& aArg1, BluetoothAddress& aArg2,
|
|
||||||
BluetoothAclState& aArg3) const
|
|
||||||
{
|
|
||||||
DaemonSocketPDU& pdu = GetPDU();
|
|
||||||
|
|
||||||
/* Read status */
|
|
||||||
nsresult rv = UnpackPDU(pdu, aArg1);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read remote address */
|
|
||||||
rv = UnpackPDU(pdu, aArg2);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read ACL state */
|
|
||||||
rv = UnpackPDU(pdu, aArg3);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
WarnAboutTrailingData();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonCoreModule::AclStateChangedNtf(
|
BluetoothDaemonCoreModule::AclStateChangedNtf(
|
||||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
||||||
{
|
{
|
||||||
AclStateChangedNotification::Dispatch(
|
AclStateChangedNotification::Dispatch(
|
||||||
&BluetoothNotificationHandler::AclStateChangedNotification,
|
&BluetoothNotificationHandler::AclStateChangedNotification,
|
||||||
AclStateChangedInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for DutModeRecvNotification
|
// Init operator class for DutModeRecvNotification
|
||||||
|
|
|
@ -298,14 +298,10 @@ private:
|
||||||
NotificationHandlerWrapper, void, BluetoothStatus, uint16_t>
|
NotificationHandlerWrapper, void, BluetoothStatus, uint16_t>
|
||||||
LeTestModeNotification;
|
LeTestModeNotification;
|
||||||
|
|
||||||
class AclStateChangedInitOp;
|
|
||||||
class AdapterPropertiesInitOp;
|
class AdapterPropertiesInitOp;
|
||||||
class BondStateChangedInitOp;
|
|
||||||
class DeviceFoundInitOp;
|
class DeviceFoundInitOp;
|
||||||
class DutModeRecvInitOp;
|
class DutModeRecvInitOp;
|
||||||
class PinRequestInitOp;
|
|
||||||
class RemoteDevicePropertiesInitOp;
|
class RemoteDevicePropertiesInitOp;
|
||||||
class SspRequestInitOp;
|
|
||||||
|
|
||||||
void AdapterStateChangedNtf(const DaemonSocketPDUHeader& aHeader,
|
void AdapterStateChangedNtf(const DaemonSocketPDUHeader& aHeader,
|
||||||
DaemonSocketPDU& aPDU);
|
DaemonSocketPDU& aPDU);
|
||||||
|
|
|
@ -1568,56 +1568,13 @@ BluetoothDaemonGattModule::ClientScanResultNtf(
|
||||||
ClientScanResultInitOp(aPDU));
|
ClientScanResultInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for ClientConnect/DisconnectNotification
|
|
||||||
class BluetoothDaemonGattModule::ClientConnectDisconnectInitOp final
|
|
||||||
: private PDUInitOp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ClientConnectDisconnectInitOp(DaemonSocketPDU& aPDU)
|
|
||||||
: PDUInitOp(aPDU)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
operator () (int& aArg1,
|
|
||||||
BluetoothGattStatus& aArg2,
|
|
||||||
int& aArg3,
|
|
||||||
BluetoothAddress& aArg4) const
|
|
||||||
{
|
|
||||||
DaemonSocketPDU& pdu = GetPDU();
|
|
||||||
|
|
||||||
/* Read connection ID */
|
|
||||||
nsresult rv = UnpackPDU(pdu, aArg1);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
/* Read status */
|
|
||||||
rv = UnpackPDU(pdu, aArg2);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
/* Read client interface */
|
|
||||||
rv = UnpackPDU(pdu, aArg3);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
/* Read address */
|
|
||||||
rv = UnpackPDU(pdu, aArg4);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
WarnAboutTrailingData();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonGattModule::ClientConnectNtf(
|
BluetoothDaemonGattModule::ClientConnectNtf(
|
||||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
||||||
{
|
{
|
||||||
ClientConnectNotification::Dispatch(
|
ClientConnectNotification::Dispatch(
|
||||||
&BluetoothGattNotificationHandler::ConnectNotification,
|
&BluetoothGattNotificationHandler::ConnectNotification,
|
||||||
ClientConnectDisconnectInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1626,7 +1583,7 @@ BluetoothDaemonGattModule::ClientDisconnectNtf(
|
||||||
{
|
{
|
||||||
ClientDisconnectNotification::Dispatch(
|
ClientDisconnectNotification::Dispatch(
|
||||||
&BluetoothGattNotificationHandler::DisconnectNotification,
|
&BluetoothGattNotificationHandler::DisconnectNotification,
|
||||||
ClientConnectDisconnectInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1737,56 +1694,13 @@ BluetoothDaemonGattModule::ClientExecuteWriteNtf(
|
||||||
UnpackPDUInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for ClientReadRemoteRssiNotification
|
|
||||||
class BluetoothDaemonGattModule::ClientReadRemoteRssiInitOp final
|
|
||||||
: private PDUInitOp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ClientReadRemoteRssiInitOp(DaemonSocketPDU& aPDU)
|
|
||||||
: PDUInitOp(aPDU)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
operator () (int& aArg1,
|
|
||||||
BluetoothAddress& aArg2,
|
|
||||||
int& aArg3,
|
|
||||||
BluetoothGattStatus& aArg4) const
|
|
||||||
{
|
|
||||||
DaemonSocketPDU& pdu = GetPDU();
|
|
||||||
|
|
||||||
/* Read client interface */
|
|
||||||
nsresult rv = UnpackPDU(pdu, aArg1);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
/* Read address */
|
|
||||||
rv = UnpackPDU(pdu, aArg2);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
/* Read RSSI */
|
|
||||||
rv = UnpackPDU(pdu, aArg3);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
/* Read status */
|
|
||||||
rv = UnpackPDU(pdu, aArg4);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
WarnAboutTrailingData();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonGattModule::ClientReadRemoteRssiNtf(
|
BluetoothDaemonGattModule::ClientReadRemoteRssiNtf(
|
||||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
||||||
{
|
{
|
||||||
ClientReadRemoteRssiNotification::Dispatch(
|
ClientReadRemoteRssiNotification::Dispatch(
|
||||||
&BluetoothGattNotificationHandler::ReadRemoteRssiNotification,
|
&BluetoothGattNotificationHandler::ReadRemoteRssiNotification,
|
||||||
ClientReadRemoteRssiInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1922,68 +1836,13 @@ BluetoothDaemonGattModule::ServerServiceDeletedNtf(
|
||||||
UnpackPDUInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for ServerRequestReadNotification
|
|
||||||
class BluetoothDaemonGattModule::ServerRequestReadInitOp final
|
|
||||||
: private PDUInitOp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ServerRequestReadInitOp(DaemonSocketPDU& aPDU)
|
|
||||||
: PDUInitOp(aPDU)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
operator () (int& aArg1,
|
|
||||||
int& aArg2,
|
|
||||||
BluetoothAddress& aArg3,
|
|
||||||
BluetoothAttributeHandle& aArg4,
|
|
||||||
int& aArg5,
|
|
||||||
bool& aArg6) const
|
|
||||||
{
|
|
||||||
DaemonSocketPDU& pdu = GetPDU();
|
|
||||||
|
|
||||||
/* Read connection ID */
|
|
||||||
nsresult rv = UnpackPDU(pdu, aArg1);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
/* Read trans ID */
|
|
||||||
rv = UnpackPDU(pdu, aArg2);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
/* Read address */
|
|
||||||
rv = UnpackPDU(pdu, aArg3);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
/* Read attribute handle */
|
|
||||||
rv = UnpackPDU(pdu, aArg4);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
/* Read offset */
|
|
||||||
rv = UnpackPDU(pdu, aArg5);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
/* Read isLong */
|
|
||||||
rv = UnpackPDU(pdu, aArg6);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
WarnAboutTrailingData();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonGattModule::ServerRequestReadNtf(
|
BluetoothDaemonGattModule::ServerRequestReadNtf(
|
||||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
||||||
{
|
{
|
||||||
ServerRequestReadNotification::Dispatch(
|
ServerRequestReadNotification::Dispatch(
|
||||||
&BluetoothGattNotificationHandler::RequestReadNotification,
|
&BluetoothGattNotificationHandler::RequestReadNotification,
|
||||||
ServerRequestReadInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for ServerRequestWriteNotification
|
// Init operator class for ServerRequestWriteNotification
|
||||||
|
@ -2069,56 +1928,13 @@ BluetoothDaemonGattModule::ServerRequestWriteNtf(
|
||||||
ServerRequestWriteInitOp(aPDU));
|
ServerRequestWriteInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for ServerRequestExecuteWriteNotification
|
|
||||||
class BluetoothDaemonGattModule::ServerRequestExecuteWriteInitOp final
|
|
||||||
: private PDUInitOp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ServerRequestExecuteWriteInitOp(DaemonSocketPDU& aPDU)
|
|
||||||
: PDUInitOp(aPDU)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
operator () (int& aArg1,
|
|
||||||
int& aArg2,
|
|
||||||
BluetoothAddress& aArg3,
|
|
||||||
bool& aArg4) const
|
|
||||||
{
|
|
||||||
DaemonSocketPDU& pdu = GetPDU();
|
|
||||||
|
|
||||||
/* Read connection ID */
|
|
||||||
nsresult rv = UnpackPDU(pdu, aArg1);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
/* Read trans ID */
|
|
||||||
rv = UnpackPDU(pdu, aArg2);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
/* Read address */
|
|
||||||
rv = UnpackPDU(pdu, aArg3);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
/* Read execute write */
|
|
||||||
rv = UnpackPDU(pdu, aArg4);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
WarnAboutTrailingData();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonGattModule::ServerRequestExecuteWriteNtf(
|
BluetoothDaemonGattModule::ServerRequestExecuteWriteNtf(
|
||||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
||||||
{
|
{
|
||||||
ServerRequestExecuteWriteNotification::Dispatch(
|
ServerRequestExecuteWriteNotification::Dispatch(
|
||||||
&BluetoothGattNotificationHandler::RequestExecuteWriteNotification,
|
&BluetoothGattNotificationHandler::RequestExecuteWriteNotification,
|
||||||
ServerRequestExecuteWriteInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -681,14 +681,10 @@ protected:
|
||||||
BluetoothGattStatus, int>
|
BluetoothGattStatus, int>
|
||||||
ServerResponseConfirmationNotification;
|
ServerResponseConfirmationNotification;
|
||||||
|
|
||||||
class ClientScanResultInitOp;
|
|
||||||
class ClientConnectDisconnectInitOp;
|
|
||||||
class ClientReadRemoteRssiInitOp;
|
|
||||||
class ClientGetDeviceTypeInitOp;
|
class ClientGetDeviceTypeInitOp;
|
||||||
|
class ClientScanResultInitOp;
|
||||||
class ServerConnectionInitOp;
|
class ServerConnectionInitOp;
|
||||||
class ServerRequestReadInitOp;
|
|
||||||
class ServerRequestWriteInitOp;
|
class ServerRequestWriteInitOp;
|
||||||
class ServerRequestExecuteWriteInitOp;
|
|
||||||
|
|
||||||
void ClientRegisterNtf(const DaemonSocketPDUHeader& aHeader,
|
void ClientRegisterNtf(const DaemonSocketPDUHeader& aHeader,
|
||||||
DaemonSocketPDU& aPDU);
|
DaemonSocketPDU& aPDU);
|
||||||
|
|
|
@ -777,44 +777,13 @@ BluetoothDaemonHandsfreeModule::ConnectionStateNtf(
|
||||||
ConnectionStateInitOp(aPDU));
|
ConnectionStateInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for AudioStateNotification
|
|
||||||
class BluetoothDaemonHandsfreeModule::AudioStateInitOp final
|
|
||||||
: private PDUInitOp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AudioStateInitOp(DaemonSocketPDU& aPDU)
|
|
||||||
: PDUInitOp(aPDU)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
operator () (BluetoothHandsfreeAudioState& aArg1,
|
|
||||||
BluetoothAddress& aArg2) const
|
|
||||||
{
|
|
||||||
DaemonSocketPDU& pdu = GetPDU();
|
|
||||||
|
|
||||||
/* Read state */
|
|
||||||
nsresult rv = UnpackPDU(pdu, aArg1);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read address */
|
|
||||||
rv = UnpackPDU(pdu, aArg2);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
WarnAboutTrailingData();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonHandsfreeModule::AudioStateNtf(
|
BluetoothDaemonHandsfreeModule::AudioStateNtf(
|
||||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
||||||
{
|
{
|
||||||
AudioStateNotification::Dispatch(
|
AudioStateNotification::Dispatch(
|
||||||
&BluetoothHandsfreeNotificationHandler::AudioStateNotification,
|
&BluetoothHandsfreeNotificationHandler::AudioStateNotification,
|
||||||
AudioStateInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for VoiceRecognitionNotification
|
// Init operator class for VoiceRecognitionNotification
|
||||||
|
@ -1381,44 +1350,13 @@ BluetoothDaemonHandsfreeModule::KeyPressedNtf(
|
||||||
KeyPressedInitOp(aPDU));
|
KeyPressedInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init operator class for WbsNotification
|
|
||||||
class BluetoothDaemonHandsfreeModule::WbsInitOp final
|
|
||||||
: private PDUInitOp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
WbsInitOp(DaemonSocketPDU& aPDU)
|
|
||||||
: PDUInitOp(aPDU)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
operator () (BluetoothHandsfreeWbsConfig& aArg1, BluetoothAddress& aArg2) const
|
|
||||||
{
|
|
||||||
DaemonSocketPDU& pdu = GetPDU();
|
|
||||||
|
|
||||||
/* Read state */
|
|
||||||
nsresult rv = UnpackPDU(pdu, aArg1);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read address */
|
|
||||||
rv = UnpackPDU(pdu, aArg2);
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
WarnAboutTrailingData();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothDaemonHandsfreeModule::WbsNtf(
|
BluetoothDaemonHandsfreeModule::WbsNtf(
|
||||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU)
|
||||||
{
|
{
|
||||||
WbsNotification::Dispatch(
|
WbsNotification::Dispatch(
|
||||||
&BluetoothHandsfreeNotificationHandler::WbsNotification,
|
&BluetoothHandsfreeNotificationHandler::WbsNotification,
|
||||||
WbsInitOp(aPDU));
|
UnpackPDUInitOp(aPDU));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -314,7 +314,6 @@ protected:
|
||||||
WbsNotification;
|
WbsNotification;
|
||||||
|
|
||||||
class ConnectionStateInitOp;
|
class ConnectionStateInitOp;
|
||||||
class AudioStateInitOp;
|
|
||||||
class VoiceRecognitionInitOp;
|
class VoiceRecognitionInitOp;
|
||||||
class AnswerCallInitOp;
|
class AnswerCallInitOp;
|
||||||
class HangupCallInitOp;
|
class HangupCallInitOp;
|
||||||
|
@ -330,7 +329,6 @@ protected:
|
||||||
class VolumeInitOp;
|
class VolumeInitOp;
|
||||||
class UnknownAtInitOp;
|
class UnknownAtInitOp;
|
||||||
class KeyPressedInitOp;
|
class KeyPressedInitOp;
|
||||||
class WbsInitOp;
|
|
||||||
|
|
||||||
void ConnectionStateNtf(const DaemonSocketPDUHeader& aHeader,
|
void ConnectionStateNtf(const DaemonSocketPDUHeader& aHeader,
|
||||||
DaemonSocketPDU& aPDU);
|
DaemonSocketPDU& aPDU);
|
||||||
|
|
|
@ -1890,9 +1890,11 @@ BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState)
|
||||||
|
|
||||||
if (!mEnabled) {
|
if (!mEnabled) {
|
||||||
static void (* const sDeinitManager[])(BluetoothProfileResultHandler*) = {
|
static void (* const sDeinitManager[])(BluetoothProfileResultHandler*) = {
|
||||||
BluetoothHfpManager::DeinitHfpInterface,
|
// Cleanup interfaces in opposite order to initialization.
|
||||||
|
BluetoothGattManager::DeinitGattInterface,
|
||||||
|
BluetoothAvrcpManager::DeinitAvrcpInterface,
|
||||||
BluetoothA2dpManager::DeinitA2dpInterface,
|
BluetoothA2dpManager::DeinitA2dpInterface,
|
||||||
BluetoothGattManager::DeinitGattInterface
|
BluetoothHfpManager::DeinitHfpInterface
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return error if BluetoothService is unavailable
|
// Return error if BluetoothService is unavailable
|
||||||
|
|
|
@ -916,6 +916,8 @@ BrowserElementChild.prototype = {
|
||||||
// Pass along the position where the context menu should be located
|
// Pass along the position where the context menu should be located
|
||||||
menuData.clientX = e.clientX;
|
menuData.clientX = e.clientX;
|
||||||
menuData.clientY = e.clientY;
|
menuData.clientY = e.clientY;
|
||||||
|
menuData.screenX = e.screenX;
|
||||||
|
menuData.screenY = e.screenY;
|
||||||
|
|
||||||
// The value returned by the contextmenu sync call is true if the embedder
|
// The value returned by the contextmenu sync call is true if the embedder
|
||||||
// called preventDefault() on its contextmenu event.
|
// called preventDefault() on its contextmenu event.
|
||||||
|
|
|
@ -2211,10 +2211,9 @@ TelephonyService.prototype = {
|
||||||
aFailCause = RIL.GECKO_CALL_ERROR_NORMAL_CALL_CLEARING) {
|
aFailCause = RIL.GECKO_CALL_ERROR_NORMAL_CALL_CLEARING) {
|
||||||
if (DEBUG) debug("_disconnectCalls: " + JSON.stringify(aCalls));
|
if (DEBUG) debug("_disconnectCalls: " + JSON.stringify(aCalls));
|
||||||
|
|
||||||
// Child cannot live without parent. Let's find all the calls that need to
|
// In addition to the disconnected call itself, its decedent calls should be
|
||||||
// be disconnected.
|
// treated as disconnected calls as well.
|
||||||
let disconnectedCalls = aCalls.slice();
|
let disconnectedCalls = aCalls.slice();
|
||||||
|
|
||||||
for (let call in aCalls) {
|
for (let call in aCalls) {
|
||||||
while (call.childId) {
|
while (call.childId) {
|
||||||
call = this._currentCalls[aClientId][call.childId];
|
call = this._currentCalls[aClientId][call.childId];
|
||||||
|
@ -2231,8 +2230,8 @@ TelephonyService.prototype = {
|
||||||
call.state = nsITelephonyService.CALL_STATE_DISCONNECTED;
|
call.state = nsITelephonyService.CALL_STATE_DISCONNECTED;
|
||||||
call.disconnectedReason = aFailCause;
|
call.disconnectedReason = aFailCause;
|
||||||
|
|
||||||
if (call.parentId) {
|
let parentCall = this._currentCalls[aClientId][call.parentId];
|
||||||
let parentCall = this._currentCalls[aClientId][call.parentId];
|
if (parentCall) {
|
||||||
delete parentCall.childId;
|
delete parentCall.childId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,6 +99,121 @@ var emulator = (function() {
|
||||||
};
|
};
|
||||||
}());
|
}());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modem Helper
|
||||||
|
*
|
||||||
|
* TODO: Should select which modem here to support multi-SIM
|
||||||
|
*/
|
||||||
|
|
||||||
|
function modemHelperGenerator() {
|
||||||
|
function Modem(aClientID) {
|
||||||
|
this.clientID = aClientID;
|
||||||
|
}
|
||||||
|
Modem.prototype = {
|
||||||
|
clientID: 0,
|
||||||
|
|
||||||
|
voiceTypeToTech: function(aVoiceType) {
|
||||||
|
switch(aVoiceType) {
|
||||||
|
case "gsm":
|
||||||
|
case "gprs":
|
||||||
|
case "edge":
|
||||||
|
return "gsm";
|
||||||
|
|
||||||
|
case "umts":
|
||||||
|
case "hsdpa":
|
||||||
|
case "hsupa":
|
||||||
|
case "hspa":
|
||||||
|
case "hspa+":
|
||||||
|
return "wcdma";
|
||||||
|
|
||||||
|
case "is95a":
|
||||||
|
case "is95b":
|
||||||
|
case "1xrtt":
|
||||||
|
return "cdma";
|
||||||
|
|
||||||
|
case "evdo0":
|
||||||
|
case "evdoa":
|
||||||
|
case "evdob":
|
||||||
|
return "evdo";
|
||||||
|
|
||||||
|
case "ehrpd":
|
||||||
|
return "ehrpd";
|
||||||
|
|
||||||
|
case "lte":
|
||||||
|
return "lte";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
isCDMA: function() {
|
||||||
|
var mobileConn = navigator.mozMobileConnections[this.clientID];
|
||||||
|
var tech = mobileConn && this.voiceTypeToTech(mobileConn.voice.type);
|
||||||
|
return tech === "cdma" || tech === "evdo" || tech == "ehrpd";
|
||||||
|
},
|
||||||
|
|
||||||
|
isGSM: function() {
|
||||||
|
var mobileConn = navigator.mozMobileConnections[this.clientID];
|
||||||
|
var tech = mobileConn && this.voiceTypeToTech(mobileConn.voice.type);
|
||||||
|
return tech === "gsm" || tech === "wcdma" || tech === "lte";
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Promise:
|
||||||
|
*/
|
||||||
|
changeTech: function(aTech, aMask) {
|
||||||
|
let target = navigator.mozMobileConnections[this.clientID];
|
||||||
|
|
||||||
|
let mask = aMask || {
|
||||||
|
gsm: "gsm",
|
||||||
|
wcdma: "gsm/wcdma",
|
||||||
|
cdma: "cdma",
|
||||||
|
evdo: "evdo0",
|
||||||
|
ehrpd: "ehrpd",
|
||||||
|
lte: "lte"
|
||||||
|
}[aTech];
|
||||||
|
|
||||||
|
let waitForExpectedTech = () => {
|
||||||
|
return new Promise((aResolve, aReject) => {
|
||||||
|
let listener = aEvent => {
|
||||||
|
log("MobileConnection[" + this.clientID + "] " +
|
||||||
|
"received event 'voicechange'");
|
||||||
|
if (aTech === this.voiceTypeToTech(target.voice.type)) {
|
||||||
|
target.removeEventListener("voicechange", listener);
|
||||||
|
aResolve();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
target.addEventListener("voicechange", listener);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Should select a modem here to support multi-SIM
|
||||||
|
let changeToExpectedTech = () => {
|
||||||
|
return Promise.resolve()
|
||||||
|
.then(() => emulator.runCmd("modem tech " + aTech + " " + mask))
|
||||||
|
.then(() => emulator.runCmd("modem tech"))
|
||||||
|
.then(result => is(result[0], aTech + " " + mask,
|
||||||
|
"Check modem 'tech/preferred mask'"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return aTech === this.voiceTypeToTech(target.voice.type)
|
||||||
|
? Promise.resolve()
|
||||||
|
: Promise.all([waitForExpectedTech(), changeToExpectedTech()]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let modems = [];
|
||||||
|
for (let i = 0; i < navigator.mozMobileConnections.length; ++i) {
|
||||||
|
modems.push(new Modem(i));
|
||||||
|
}
|
||||||
|
return modems;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Modems = modemHelperGenerator();
|
||||||
|
let Modem = Modems[0];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Telephony related helper functions.
|
* Telephony related helper functions.
|
||||||
*/
|
*/
|
||||||
|
@ -276,70 +391,6 @@ var emulator = (function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param aVoiceType
|
|
||||||
* The voice type of a mobileConnection, which can be obtained from
|
|
||||||
* |<mobileConnection>.voice.type|.
|
|
||||||
* @return A string with format of the emulator voice tech.
|
|
||||||
*/
|
|
||||||
function voiceTypeToTech(aVoiceType) {
|
|
||||||
switch(aVoiceType) {
|
|
||||||
case "gsm":
|
|
||||||
case "gprs":
|
|
||||||
case "edge":
|
|
||||||
return "gsm";
|
|
||||||
|
|
||||||
case "umts":
|
|
||||||
case "hsdpa":
|
|
||||||
case "hsupa":
|
|
||||||
case "hspa":
|
|
||||||
case "hspa+":
|
|
||||||
return "wcdma";
|
|
||||||
|
|
||||||
case "is95a":
|
|
||||||
case "is95b":
|
|
||||||
case "1xrtt":
|
|
||||||
return "cdma";
|
|
||||||
|
|
||||||
case "evdo0":
|
|
||||||
case "evdoa":
|
|
||||||
case "evdob":
|
|
||||||
return "evdo";
|
|
||||||
|
|
||||||
case "ehrpd":
|
|
||||||
case "lte":
|
|
||||||
return "lte";
|
|
||||||
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Promise
|
|
||||||
*/
|
|
||||||
function changeModemTech(aTech, aPreferredMask) {
|
|
||||||
let mobileConn = navigator.mozMobileConnections[0];
|
|
||||||
|
|
||||||
function isTechMatched() {
|
|
||||||
return aTech === voiceTypeToTech(mobileConn.voice.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
let promise1 = isTechMatched() ? Promise.resolve()
|
|
||||||
: waitForEvent(mobileConn,
|
|
||||||
"voicechange",
|
|
||||||
isTechMatched);
|
|
||||||
|
|
||||||
let promise2 = Promise.resolve()
|
|
||||||
.then(() => emulator.runCmd("modem tech " + aTech + " " + aPreferredMask))
|
|
||||||
.then(() => emulator.runCmd("modem tech"))
|
|
||||||
.then(result => is(result[0],
|
|
||||||
aTech + " " + aPreferredMask,
|
|
||||||
"Check modem 'tech/preferred mask'"));
|
|
||||||
|
|
||||||
return Promise.all([promise1, promise2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Promise
|
* @return Promise
|
||||||
*/
|
*/
|
||||||
|
@ -361,7 +412,7 @@ var emulator = (function() {
|
||||||
|
|
||||||
return Promise.all(hangUpPromises)
|
return Promise.all(hangUpPromises)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return emulator.runCmd("gsm clear").then(waitForNoCall);
|
return emulator.runCmd("telephony clear").then(waitForNoCall);
|
||||||
})
|
})
|
||||||
.then(waitForNoCall);
|
.then(waitForNoCall);
|
||||||
}
|
}
|
||||||
|
@ -423,6 +474,11 @@ var emulator = (function() {
|
||||||
checkState(null, [], "", []);
|
checkState(null, [], "", []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
**** Check Functions ****
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenient helper to compare two call lists (order is not important).
|
* Convenient helper to compare two call lists (order is not important).
|
||||||
*/
|
*/
|
||||||
|
@ -478,7 +534,7 @@ var emulator = (function() {
|
||||||
* @return Promise
|
* @return Promise
|
||||||
*/
|
*/
|
||||||
function checkEmulatorCallList(expectedCallList) {
|
function checkEmulatorCallList(expectedCallList) {
|
||||||
return emulator.runCmd("gsm list").then(result => {
|
return emulator.runCmd("telephony list").then(result => {
|
||||||
log("Call list is now: " + result);
|
log("Call list is now: " + result);
|
||||||
for (let i = 0; i < expectedCallList.length; ++i) {
|
for (let i = 0; i < expectedCallList.length; ++i) {
|
||||||
is(result[i], expectedCallList[i], "emulator calllist");
|
is(result[i], expectedCallList[i], "emulator calllist");
|
||||||
|
@ -532,8 +588,168 @@ var emulator = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request utility functions.
|
* The factory function for creating an expected call.
|
||||||
|
*
|
||||||
|
* @param aReference
|
||||||
|
* The reference of the telephonyCall object.
|
||||||
|
* @param aNumber
|
||||||
|
* The call number.
|
||||||
|
* @param aConference
|
||||||
|
* Shows whether the call belongs to the conference.
|
||||||
|
* @param aDirection
|
||||||
|
* The direction of the call, "in" for inbound, and "out" for outbound.
|
||||||
|
* @param aState
|
||||||
|
* The expected state of the call.
|
||||||
|
* @param aEmulatorState
|
||||||
|
* The state logged in emulator now, may be different from aState.
|
||||||
|
* @param aDisconnectedReason
|
||||||
|
* The disconnected reason if the call becomed disconnected.
|
||||||
*/
|
*/
|
||||||
|
function createExptectedCall(aReference, aNumber, aConference, aDirection,
|
||||||
|
aState, aEmulatorState, aDisconnectedReason) {
|
||||||
|
return {
|
||||||
|
reference: aReference,
|
||||||
|
number: aNumber,
|
||||||
|
conference: aConference,
|
||||||
|
direction: aDirection,
|
||||||
|
state: aState,
|
||||||
|
emulatorState: aEmulatorState,
|
||||||
|
disconnectedReason: aDisconnectedReason
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check telephony.active
|
||||||
|
*
|
||||||
|
* @param aExpectedCalls
|
||||||
|
* An array of expected calls.
|
||||||
|
* @param aExpectedCallsInConference
|
||||||
|
* An array of expected calls in the conference.
|
||||||
|
*/
|
||||||
|
function checkActive(aExpectedCalls, aExpectedCallsInConference) {
|
||||||
|
// Get the active call
|
||||||
|
let calls = aExpectedCalls && aExpectedCalls.filter(aExpectedCall => {
|
||||||
|
return aExpectedCall.state === "connected" ||
|
||||||
|
aExpectedCall.state === "alerting" ||
|
||||||
|
aExpectedCall.state === "dialing";
|
||||||
|
});
|
||||||
|
|
||||||
|
ok(calls.length < 2, "Too many actives call in telephony.calls");
|
||||||
|
let activeCall = calls.length ? calls[0].reference : null;
|
||||||
|
|
||||||
|
// Get the active conference
|
||||||
|
let callsInConference = aExpectedCallsInConference || [];
|
||||||
|
let activeConference = callsInConference.length &&
|
||||||
|
callsInConference[0].state === "connected"
|
||||||
|
? navigator.mozTelephony.conferenceGroup
|
||||||
|
: null;
|
||||||
|
|
||||||
|
// Check telephony.active
|
||||||
|
ok(!(activeCall && activeConference),
|
||||||
|
"An active call cannot coexist with an active conference call.");
|
||||||
|
is(telephony.active, activeCall || activeConference, "check Active");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the data in telephony and emulator meets our expectation.
|
||||||
|
*
|
||||||
|
* NOTE: Conference call is not supported in this function yet, so related
|
||||||
|
* checks are skipped.
|
||||||
|
*
|
||||||
|
* Fulfill params:
|
||||||
|
* {
|
||||||
|
* reference, -- the reference of the call object instance.
|
||||||
|
* number, -- the call number.
|
||||||
|
* conference, -- shows whether it belongs to the conference.
|
||||||
|
* direction, -- "in" for inbound, and "out" for outbound.
|
||||||
|
* state, -- the call state.
|
||||||
|
* emulatorState, -- the call state logged in emulator now.
|
||||||
|
* disconnectedReason, -- the disconnected reason of a disconnected call.
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @param aExpectedCalls
|
||||||
|
* An array of call records.
|
||||||
|
* @return Promise
|
||||||
|
*/
|
||||||
|
function equals(aExpectedCalls) {
|
||||||
|
// Classify calls
|
||||||
|
let callsInTelephony = [];
|
||||||
|
let CallsInConference = [];
|
||||||
|
|
||||||
|
aExpectedCalls.forEach(function(aCall) {
|
||||||
|
if (aCall.state === "disconnected") {
|
||||||
|
is(aCall.disconnectedReason,
|
||||||
|
aCall.reference.disconnectedReason,
|
||||||
|
"Check disconnectedReason");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aCall.conference) {
|
||||||
|
CallsInConference.push(aCall);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
callsInTelephony.push(aCall);
|
||||||
|
ok(!aCall.secondId, "For a telephony call, the secondId must be null");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check the active connection
|
||||||
|
checkActive(callsInTelephony, CallsInConference);
|
||||||
|
|
||||||
|
// Check telephony.calls
|
||||||
|
is(telephony.calls.length,
|
||||||
|
callsInTelephony.length,
|
||||||
|
"Check telephony.calls.length");
|
||||||
|
|
||||||
|
callsInTelephony.forEach(aExpectedCall => {
|
||||||
|
let number = aExpectedCall.number;
|
||||||
|
let call = telephony.calls.find(aCall => aCall.id.number === number);
|
||||||
|
if (!call) {
|
||||||
|
ok(false, "telephony.calls lost the call(number: " + number + ")");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
is(call, aExpectedCall.reference,
|
||||||
|
"Check the object reference of number:" + number);
|
||||||
|
|
||||||
|
is(call.state, aExpectedCall.state,
|
||||||
|
"Check call.state of number:" + number);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check conference.calls
|
||||||
|
// NOTE: This function doesn't support conference call now, so the length of
|
||||||
|
// |CallsInConference| should be 0, and the conference state shoul be "".
|
||||||
|
is(conference.state, "", "Conference call is not supported yet.");
|
||||||
|
is(CallsInConference.length, 0, "Conference call is not supported yet.");
|
||||||
|
|
||||||
|
// Check the emulator call list
|
||||||
|
// NOTE: Conference is not supported yet, so |CallsInConference| is ignored.
|
||||||
|
let strings = callsInTelephony.map(aCall => {
|
||||||
|
// The emulator doesn't have records for disconnected calls.
|
||||||
|
if (aCall.emulatorState === "disconnected") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let state = {
|
||||||
|
alerting: "ringing",
|
||||||
|
connected: "active",
|
||||||
|
held: "held",
|
||||||
|
incoming: "incoming"
|
||||||
|
}[aCall.state];
|
||||||
|
|
||||||
|
state = aCall.emulatorState || state;
|
||||||
|
let prefix = (aCall.direction === "in") ? "inbound from "
|
||||||
|
: "outbound to ";
|
||||||
|
|
||||||
|
return state ? (prefix + aCall.number + " : " + state) : null;
|
||||||
|
});
|
||||||
|
|
||||||
|
return checkEmulatorCallList(strings.filter(aString => aString));
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
**** Request utility functions ****
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make an outgoing call.
|
* Make an outgoing call.
|
||||||
|
@ -558,7 +774,13 @@ var emulator = (function() {
|
||||||
is(outCall.state, "dialing");
|
is(outCall.state, "dialing");
|
||||||
is(outCall.serviceId, serviceId);
|
is(outCall.serviceId, serviceId);
|
||||||
})
|
})
|
||||||
.then(() => waitForNamedStateEvent(outCall, "alerting"));
|
.then(() => {
|
||||||
|
// A CDMA call goes to connected state directly when the operator find
|
||||||
|
// its callee, which makes the "connected" state in CDMA calls behaves
|
||||||
|
// like the "alerting" state in GSM calls.
|
||||||
|
let state = Modems[serviceId].isGSM() ? "alerting" : "connected";
|
||||||
|
return waitForNamedStateEvent(outCall, state);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -581,7 +803,13 @@ var emulator = (function() {
|
||||||
is(outCall.id.number, number);
|
is(outCall.id.number, number);
|
||||||
is(outCall.state, "dialing");
|
is(outCall.state, "dialing");
|
||||||
})
|
})
|
||||||
.then(() => waitForNamedStateEvent(outCall, "alerting"))
|
.then(() => {
|
||||||
|
// Similar to function |dial|, a CDMA call directly goes to connected
|
||||||
|
// state when the operator find its callee.
|
||||||
|
let state = Modems[outCall.serviceId].isGSM() ? "alerting"
|
||||||
|
: "connected";
|
||||||
|
return waitForNamedStateEvent(outCall, state);
|
||||||
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
is(outCall.emergency, true, "check emergency");
|
is(outCall.emergency, true, "check emergency");
|
||||||
return outCall;
|
return outCall;
|
||||||
|
@ -651,19 +879,23 @@ var emulator = (function() {
|
||||||
/**
|
/**
|
||||||
* Hold a call.
|
* Hold a call.
|
||||||
*
|
*
|
||||||
* @param call
|
* @param aCall
|
||||||
* A TelephonyCall object.
|
* A TelephonyCall object.
|
||||||
|
* @param aWaitForEvent
|
||||||
|
* Decide whether to wait for the state event.
|
||||||
* @return Promise<TelephonyCall>
|
* @return Promise<TelephonyCall>
|
||||||
*/
|
*/
|
||||||
function hold(call) {
|
function hold(aCall, aWaitForEvent = true) {
|
||||||
log("Putting the call on hold.");
|
log("Putting the call on hold.");
|
||||||
|
|
||||||
let promises = [];
|
let promises = [];
|
||||||
|
|
||||||
promises.push(waitForNamedStateEvent(call, "held"));
|
if (aWaitForEvent) {
|
||||||
promises.push(call.hold());
|
promises.push(waitForNamedStateEvent(aCall, "held"));
|
||||||
|
}
|
||||||
|
promises.push(aCall.hold());
|
||||||
|
|
||||||
return Promise.all(promises).then(() => call);
|
return Promise.all(promises).then(() => aCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -673,7 +905,7 @@ var emulator = (function() {
|
||||||
* A TelephonyCall object.
|
* A TelephonyCall object.
|
||||||
* @return Promise<TelephonyCall>
|
* @return Promise<TelephonyCall>
|
||||||
*/
|
*/
|
||||||
function resume(call) {
|
function resume(call, aWaitForEvent = true) {
|
||||||
log("Resuming the held call.");
|
log("Resuming the held call.");
|
||||||
|
|
||||||
let promises = [];
|
let promises = [];
|
||||||
|
@ -721,8 +953,10 @@ var emulator = (function() {
|
||||||
numberPresentation = numberPresentation || "";
|
numberPresentation = numberPresentation || "";
|
||||||
name = name || "";
|
name = name || "";
|
||||||
namePresentation = namePresentation || "";
|
namePresentation = namePresentation || "";
|
||||||
emulator.runCmd("gsm call " + number + "," + numberPresentation + "," + name +
|
emulator.runCmd("telephony call " + number +
|
||||||
"," + namePresentation);
|
"," + numberPresentation +
|
||||||
|
"," + name +
|
||||||
|
"," + namePresentation);
|
||||||
|
|
||||||
return waitForEvent(telephony, "incoming")
|
return waitForEvent(telephony, "incoming")
|
||||||
.then(event => {
|
.then(event => {
|
||||||
|
@ -747,9 +981,14 @@ var emulator = (function() {
|
||||||
function remoteAnswer(call) {
|
function remoteAnswer(call) {
|
||||||
log("Remote answering the call: " + call.id.number);
|
log("Remote answering the call: " + call.id.number);
|
||||||
|
|
||||||
emulator.runCmd("gsm accept " + call.id.number);
|
emulator.runCmd("telephony accept " + call.id.number);
|
||||||
|
|
||||||
return waitForNamedStateEvent(call, "connected");
|
// A CDMA call goes to connected state directly when the operator find its
|
||||||
|
// callee, which makes the "connected" state in CDMA calls behaves like the
|
||||||
|
// "alerting" state in GSM calls, so we don't have to wait for the call to
|
||||||
|
// change to "connected" state here for CDMA calls.
|
||||||
|
return Modem.isCDMA() ? Promise.resolve()
|
||||||
|
: waitForNamedStateEvent(call, "connected");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -762,7 +1001,7 @@ var emulator = (function() {
|
||||||
function remoteHangUp(call) {
|
function remoteHangUp(call) {
|
||||||
log("Remote hanging up the call: " + call.id.number);
|
log("Remote hanging up the call: " + call.id.number);
|
||||||
|
|
||||||
emulator.runCmd("gsm cancel " + call.id.number);
|
emulator.runCmd("telephony cancel " + call.id.number);
|
||||||
|
|
||||||
return waitForNamedStateEvent(call, "disconnected");
|
return waitForNamedStateEvent(call, "disconnected");
|
||||||
}
|
}
|
||||||
|
@ -1216,7 +1455,6 @@ var emulator = (function() {
|
||||||
this.gWaitForNamedStateEvent = waitForNamedStateEvent;
|
this.gWaitForNamedStateEvent = waitForNamedStateEvent;
|
||||||
this.gWaitForStateChangeEvent = waitForStateChangeEvent;
|
this.gWaitForStateChangeEvent = waitForStateChangeEvent;
|
||||||
this.gCheckInitialState = checkInitialState;
|
this.gCheckInitialState = checkInitialState;
|
||||||
this.gChangeModemTech = changeModemTech;
|
|
||||||
this.gClearCalls = clearCalls;
|
this.gClearCalls = clearCalls;
|
||||||
this.gOutCallStrPool = outCallStrPool;
|
this.gOutCallStrPool = outCallStrPool;
|
||||||
this.gInCallStrPool = inCallStrPool;
|
this.gInCallStrPool = inCallStrPool;
|
||||||
|
@ -1244,6 +1482,25 @@ var emulator = (function() {
|
||||||
this.gSetupConference = setupConference;
|
this.gSetupConference = setupConference;
|
||||||
this.gSetRadioEnabled = setRadioEnabled;
|
this.gSetRadioEnabled = setRadioEnabled;
|
||||||
this.gSetRadioEnabledAll = setRadioEnabledAll;
|
this.gSetRadioEnabledAll = setRadioEnabledAll;
|
||||||
|
|
||||||
|
// Telephony helper
|
||||||
|
this.TelephonyHelper = {
|
||||||
|
dial: dial,
|
||||||
|
answer: answer,
|
||||||
|
hangUp: hangUp,
|
||||||
|
hold: hold,
|
||||||
|
resume: resume,
|
||||||
|
equals: equals,
|
||||||
|
createExptectedCall: createExptectedCall
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remote Utils, TODO: This should be an array for multi-SIM scenarios
|
||||||
|
this.Remotes = [{
|
||||||
|
dial: remoteDial,
|
||||||
|
answer: remoteAnswer,
|
||||||
|
hangUp: remoteHangUp
|
||||||
|
}];
|
||||||
|
this.Remote = this.Remotes[0];
|
||||||
}());
|
}());
|
||||||
|
|
||||||
function _startTest(permissions, test) {
|
function _startTest(permissions, test) {
|
||||||
|
|
|
@ -24,6 +24,8 @@ qemu = true
|
||||||
[test_dtmf.js]
|
[test_dtmf.js]
|
||||||
[test_emergency.js]
|
[test_emergency.js]
|
||||||
[test_emergency_label.js]
|
[test_emergency_label.js]
|
||||||
|
[test_gsm_cdma_incoming_basic_operations.js]
|
||||||
|
[test_gsm_cdma_outgoing_basic_operations.js]
|
||||||
[test_incall_mmi_call_hold.js]
|
[test_incall_mmi_call_hold.js]
|
||||||
[test_incall_mmi_call_waiting.js]
|
[test_incall_mmi_call_waiting.js]
|
||||||
[test_incall_mmi_conference.js]
|
[test_incall_mmi_conference.js]
|
||||||
|
@ -31,7 +33,6 @@ qemu = true
|
||||||
[test_incoming_already_connected.js]
|
[test_incoming_already_connected.js]
|
||||||
[test_incoming_already_held.js]
|
[test_incoming_already_held.js]
|
||||||
[test_incoming_answer_hangup_oncallschanged.js]
|
[test_incoming_answer_hangup_oncallschanged.js]
|
||||||
[test_incoming_basic_operations.js]
|
|
||||||
[test_incoming_onstatechange.js]
|
[test_incoming_onstatechange.js]
|
||||||
[test_mmi_call_barring.js]
|
[test_mmi_call_barring.js]
|
||||||
[test_mmi_call_forwarding.js]
|
[test_mmi_call_forwarding.js]
|
||||||
|
@ -52,7 +53,6 @@ qemu = true
|
||||||
[test_outgoing_answer_radio_off.js]
|
[test_outgoing_answer_radio_off.js]
|
||||||
[test_outgoing_auto_hold.js]
|
[test_outgoing_auto_hold.js]
|
||||||
[test_outgoing_badNumber.js]
|
[test_outgoing_badNumber.js]
|
||||||
[test_outgoing_basic_operations.js]
|
|
||||||
[test_outgoing_busy.js]
|
[test_outgoing_busy.js]
|
||||||
[test_outgoing_from_stk.js]
|
[test_outgoing_from_stk.js]
|
||||||
[test_outgoing_onstatechange.js]
|
[test_outgoing_onstatechange.js]
|
||||||
|
@ -64,3 +64,4 @@ qemu = true
|
||||||
[test_system_message_telephony_call_ended.js]
|
[test_system_message_telephony_call_ended.js]
|
||||||
[test_TelephonyUtils.js]
|
[test_TelephonyUtils.js]
|
||||||
[test_temporary_clir.js]
|
[test_temporary_clir.js]
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ function test_oneCall() {
|
||||||
let p = waitForStateChanged(aAllInfo => {
|
let p = waitForStateChanged(aAllInfo => {
|
||||||
return aAllInfo[0].callState === Ci.nsITelephonyService.CALL_STATE_CONNECTED;
|
return aAllInfo[0].callState === Ci.nsITelephonyService.CALL_STATE_CONNECTED;
|
||||||
});
|
});
|
||||||
emulator.runCmd("gsm accept " + number);
|
emulator.runCmd("telephony accept " + number);
|
||||||
return p;
|
return p;
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -87,7 +87,7 @@ function test_oneCall() {
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
let p = TelephonyUtils.waitForNoCalls();
|
let p = TelephonyUtils.waitForNoCalls();
|
||||||
emulator.runCmd("gsm cancel " + number);
|
emulator.runCmd("telephony cancel " + number);
|
||||||
return p;
|
return p;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ startTest(function() {
|
||||||
|
|
||||||
// Disable the Hold function of the emulator, then hold the active call,
|
// Disable the Hold function of the emulator, then hold the active call,
|
||||||
// where the hold request will fail and the call will remain active.
|
// where the hold request will fail and the call will remain active.
|
||||||
.then(() => emulator.runCmd("gsm disable hold"))
|
.then(() => emulator.runCmd("telephony disable hold"))
|
||||||
.then(() => gHold(inCall))
|
.then(() => gHold(inCall))
|
||||||
.then(() => ok(false, "This hold request should be rejected."),
|
.then(() => ok(false, "This hold request should be rejected."),
|
||||||
() => log("This hold request is rejected as expected."))
|
() => log("This hold request is rejected as expected."))
|
||||||
|
@ -33,7 +33,7 @@ startTest(function() {
|
||||||
|
|
||||||
// Enable the Hold function of the emulator, then hold the active call,
|
// Enable the Hold function of the emulator, then hold the active call,
|
||||||
// where the hold request should succeed and the call should become held.
|
// where the hold request should succeed and the call should become held.
|
||||||
.then(() => emulator.runCmd("gsm enable hold"))
|
.then(() => emulator.runCmd("telephony enable hold"))
|
||||||
.then(() => gHold(inCall))
|
.then(() => gHold(inCall))
|
||||||
.then(() => log("This hold request is resolved as expected."),
|
.then(() => log("This hold request is resolved as expected."),
|
||||||
() => ok(false, "This hold request should be resolved."))
|
() => ok(false, "This hold request should be resolved."))
|
||||||
|
@ -47,6 +47,6 @@ startTest(function() {
|
||||||
|
|
||||||
// Clean Up
|
// Clean Up
|
||||||
.catch(error => ok(false, "Promise reject: " + error))
|
.catch(error => ok(false, "Promise reject: " + error))
|
||||||
.then(() => emulator.runCmd("gsm enable hold"))
|
.then(() => emulator.runCmd("telephony enable hold"))
|
||||||
.then(finish);
|
.then(finish);
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,170 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
MARIONETTE_TIMEOUT = 90000;
|
||||||
|
MARIONETTE_HEAD_JS = 'head.js';
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**** Basic Operations ****
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
const IncomingNumber = "1111110000";
|
||||||
|
|
||||||
|
function exptectedCall(aCall, aState, aEmulatorState = null) {
|
||||||
|
let disconnectedReason = aState === "disconnected" ? "NormalCallClearing"
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return TelephonyHelper.createExptectedCall(aCall, IncomingNumber, false,
|
||||||
|
"in", aState, aEmulatorState,
|
||||||
|
disconnectedReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
function incoming(aNumber) {
|
||||||
|
let ret;
|
||||||
|
return Remote.dial(aNumber)
|
||||||
|
.then(call => ret = call)
|
||||||
|
.then(() => TelephonyHelper.equals([exptectedCall(ret, "incoming")]))
|
||||||
|
.then(() => ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
function answer(aCall) {
|
||||||
|
let call = exptectedCall(aCall, "connected");
|
||||||
|
return TelephonyHelper.answer(aCall)
|
||||||
|
.then(() => TelephonyHelper.equals([call]))
|
||||||
|
.then(() => aCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hold(aCall) {
|
||||||
|
// Since a CDMA call doesn't have any notification for its state changing to
|
||||||
|
// "held" state, a telephonyCall is still remains in "connected" state when
|
||||||
|
// the call actually goes to "held" state, and we shouldn't wait for the state
|
||||||
|
// change event here.
|
||||||
|
let state = Modem.isGSM() ? "held" : "connected";
|
||||||
|
let call = exptectedCall(aCall, state,"held");
|
||||||
|
return TelephonyHelper.hold(aCall, Modem.isGSM())
|
||||||
|
.then(() => TelephonyHelper.equals([call]))
|
||||||
|
.then(() => aCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resume(aCall) {
|
||||||
|
// Similar to the hold case, there is no notification for a CDMA call's state
|
||||||
|
// change. Besides, a CDMA call still remains in "connected" state here, so we
|
||||||
|
// have to use |hold()| function here to resume the call. Otherwise, if we use
|
||||||
|
// |resume()| function, we'll get an invalid state error.
|
||||||
|
let call = exptectedCall(aCall, "connected");
|
||||||
|
return Modem.isGSM() ? TelephonyHelper.resume(aCall)
|
||||||
|
: TelephonyHelper.hold(aCall, false)
|
||||||
|
.then(() => TelephonyHelper.equals([call]))
|
||||||
|
.then(() => aCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hangUp(aCall) {
|
||||||
|
let call = exptectedCall(aCall, "disconnected");
|
||||||
|
return TelephonyHelper.hangUp(aCall)
|
||||||
|
.then(() => TelephonyHelper.equals([call]))
|
||||||
|
.then(() => aCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
function remoteHangUp(aCall) {
|
||||||
|
let call = exptectedCall(aCall, "disconnected");
|
||||||
|
return Remote.hangUp(aCall)
|
||||||
|
.then(() => TelephonyHelper.equals([call]))
|
||||||
|
.then(() => aCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**** Testcases ****
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
function testIncomingReject() {
|
||||||
|
log("= testIncomingReject =");
|
||||||
|
return incoming(IncomingNumber)
|
||||||
|
.then(call => hangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testIncomingCancel() {
|
||||||
|
log("= testIncomingCancel =");
|
||||||
|
return incoming(IncomingNumber)
|
||||||
|
.then(call => remoteHangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testIncomingAnswerHangUp() {
|
||||||
|
log("= testIncomingAnswerHangUp =");
|
||||||
|
return incoming(IncomingNumber)
|
||||||
|
.then(call => answer(call))
|
||||||
|
.then(call => hangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testIncomingAnswerRemoteHangUp() {
|
||||||
|
log("= testIncomingAnswerRemoteHangUp =");
|
||||||
|
return incoming(IncomingNumber)
|
||||||
|
.then(call => answer(call))
|
||||||
|
.then(call => remoteHangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testIncomingAnswerHoldHangUp() {
|
||||||
|
log("= testIncomingAnswerHoldHangUp =");
|
||||||
|
return incoming(IncomingNumber)
|
||||||
|
.then(call => answer(call))
|
||||||
|
.then(call => hold(call))
|
||||||
|
.then(call => hangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testIncomingAnswerHoldRemoteHangUp() {
|
||||||
|
log("= testIncomingAnswerHoldRemoteHangUp =");
|
||||||
|
return incoming(IncomingNumber)
|
||||||
|
.then(call => answer(call))
|
||||||
|
.then(call => hold(call))
|
||||||
|
.then(call => remoteHangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testIncomingAnswerHoldResumeHangUp() {
|
||||||
|
log("= testIncomingAnswerHoldResumeHangUp =");
|
||||||
|
return incoming(IncomingNumber)
|
||||||
|
.then(call => answer(call))
|
||||||
|
.then(call => hold(call))
|
||||||
|
.then(call => resume(call))
|
||||||
|
.then(call => hangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testIncomingAnswerHoldResumeRemoteHangUp() {
|
||||||
|
log("= testIncomingAnswerHoldResumeRemoteHangUp =");
|
||||||
|
return incoming(IncomingNumber)
|
||||||
|
.then(call => answer(call))
|
||||||
|
.then(call => hold(call))
|
||||||
|
.then(call => resume(call))
|
||||||
|
.then(call => remoteHangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**** Test Launcher ****
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
function runTestSuite(aTech, aTechMask) {
|
||||||
|
return Promise.resolve()
|
||||||
|
// Setup Environment
|
||||||
|
.then(() => Modem.changeTech(aTech, aTechMask))
|
||||||
|
|
||||||
|
// Tests
|
||||||
|
.then(() => testIncomingReject())
|
||||||
|
.then(() => testIncomingCancel())
|
||||||
|
.then(() => testIncomingAnswerHangUp())
|
||||||
|
.then(() => testIncomingAnswerRemoteHangUp())
|
||||||
|
.then(() => testIncomingAnswerHoldHangUp())
|
||||||
|
.then(() => testIncomingAnswerHoldRemoteHangUp())
|
||||||
|
.then(() => testIncomingAnswerHoldResumeHangUp())
|
||||||
|
.then(() => testIncomingAnswerHoldResumeRemoteHangUp())
|
||||||
|
|
||||||
|
// Restore Environment
|
||||||
|
.then(() => Modem.changeTech("wcdma"));
|
||||||
|
}
|
||||||
|
|
||||||
|
startTest(function() {
|
||||||
|
return Promise.resolve()
|
||||||
|
.then(() => runTestSuite("cdma"))
|
||||||
|
.then(() => runTestSuite("wcdma"))
|
||||||
|
|
||||||
|
.catch(error => ok(false, "Promise reject: " + error))
|
||||||
|
.then(finish);
|
||||||
|
});
|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
MARIONETTE_TIMEOUT = 90000;
|
||||||
|
MARIONETTE_HEAD_JS = 'head.js';
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**** Basic Operations ****
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
const OutgoingNumber = "5555551111";
|
||||||
|
|
||||||
|
function exptectedCall(aCall, aState, aEmulatorState = null) {
|
||||||
|
let disconnectedReason = aState === "disconnected" ? "NormalCallClearing"
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return TelephonyHelper.createExptectedCall(aCall, OutgoingNumber, false,
|
||||||
|
"out", aState, aEmulatorState,
|
||||||
|
disconnectedReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
function outgoing(aNumber) {
|
||||||
|
let ret;
|
||||||
|
|
||||||
|
// Since a CDMA call doesn't have "alerting" state, it directly goes to
|
||||||
|
// "connected" state instead.
|
||||||
|
let state = Modem.isCDMA() ? "connected" : "alerting";
|
||||||
|
return TelephonyHelper.dial(aNumber)
|
||||||
|
.then(call => ret = call)
|
||||||
|
.then(() => TelephonyHelper.equals([exptectedCall(ret, state)]))
|
||||||
|
.then(() => ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
function remoteAnswer(aCall) {
|
||||||
|
let call = exptectedCall(aCall, "connected");
|
||||||
|
return Remote.answer(aCall)
|
||||||
|
.then(() => TelephonyHelper.equals([call]))
|
||||||
|
.then(() => aCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hold(aCall) {
|
||||||
|
// Since a CDMA call doesn't have any notification for its state changing to
|
||||||
|
// "held" state, a telephonyCall is still remains in "connected" state when
|
||||||
|
// the call actually goes to "held" state, and we shouldn't wait for the state
|
||||||
|
// change event here.
|
||||||
|
let state = Modem.isGSM() ? "held" : "connected";
|
||||||
|
let call = exptectedCall(aCall, state, "held");
|
||||||
|
return TelephonyHelper.hold(aCall, Modem.isGSM())
|
||||||
|
.then(() => TelephonyHelper.equals([call]))
|
||||||
|
.then(() => aCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resume(aCall) {
|
||||||
|
// Similar to the hold case, there is no notification for a CDMA call's state
|
||||||
|
// change. Besides, a CDMA call still remains in "connected" state here, so we
|
||||||
|
// have to use |hold()| function here to resume the call. Otherwise, if we use
|
||||||
|
// |resume()| function, we'll get an invalid state error.
|
||||||
|
let call = exptectedCall(aCall, "connected");
|
||||||
|
return Modem.isGSM() ? TelephonyHelper.resume(aCall)
|
||||||
|
: TelephonyHelper.hold(aCall, false)
|
||||||
|
.then(() => TelephonyHelper.equals([call]))
|
||||||
|
.then(() => aCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hangUp(aCall) {
|
||||||
|
let call = exptectedCall(aCall, "disconnected");
|
||||||
|
return TelephonyHelper.hangUp(aCall)
|
||||||
|
.then(() => TelephonyHelper.equals([call]))
|
||||||
|
.then(() => aCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
function remoteHangUp(aCall) {
|
||||||
|
let call = exptectedCall(aCall, "disconnected");
|
||||||
|
return Remote.hangUp(aCall)
|
||||||
|
.then(() => TelephonyHelper.equals([call]))
|
||||||
|
.then(() => aCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
**** Testcases ****
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
function testOutgoingReject() {
|
||||||
|
log("= testOutgoingReject =");
|
||||||
|
return outgoing(OutgoingNumber)
|
||||||
|
.then(call => remoteHangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOutgoingCancel() {
|
||||||
|
log("= testOutgoingCancel =");
|
||||||
|
return outgoing(OutgoingNumber)
|
||||||
|
.then(call => hangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOutgoingAnswerHangUp() {
|
||||||
|
log("= testOutgoingAnswerHangUp =");
|
||||||
|
return outgoing(OutgoingNumber)
|
||||||
|
.then(call => remoteAnswer(call))
|
||||||
|
.then(call => hangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOutgoingAnswerRemoteHangUp() {
|
||||||
|
log("= testOutgoingAnswerRemoteHangUp =");
|
||||||
|
return outgoing(OutgoingNumber)
|
||||||
|
.then(call => remoteAnswer(call))
|
||||||
|
.then(call => remoteHangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOutgoingAnswerHoldHangUp() {
|
||||||
|
log("= testOutgoingAnswerHoldHangUp =");
|
||||||
|
return outgoing(OutgoingNumber)
|
||||||
|
.then(call => remoteAnswer(call))
|
||||||
|
.then(call => hold(call))
|
||||||
|
.then(call => hangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOutgoingAnswerHoldRemoteHangUp() {
|
||||||
|
log("= testOutgoingAnswerHoldRemoteHangUp =");
|
||||||
|
return outgoing(OutgoingNumber)
|
||||||
|
.then(call => remoteAnswer(call))
|
||||||
|
.then(call => hold(call))
|
||||||
|
.then(call => remoteHangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOutgoingAnswerHoldResumeHangUp() {
|
||||||
|
log("= testOutgoingAnswerHoldResumeHangUp =");
|
||||||
|
return outgoing(OutgoingNumber)
|
||||||
|
.then(call => remoteAnswer(call))
|
||||||
|
.then(call => hold(call))
|
||||||
|
.then(call => resume(call))
|
||||||
|
.then(call => hangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOutgoingAnswerHoldResumeRemoteHangUp() {
|
||||||
|
log("= testOutgoingAnswerHoldResumeRemoteHangUp =");
|
||||||
|
return outgoing(OutgoingNumber)
|
||||||
|
.then(call => remoteAnswer(call))
|
||||||
|
.then(call => hold(call))
|
||||||
|
.then(call => resume(call))
|
||||||
|
.then(call => remoteHangUp(call));
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
/*** Test Launcher ***/
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
function runTestSuite(aTech, aTechMask) {
|
||||||
|
return Promise.resolve()
|
||||||
|
// Setup Environment
|
||||||
|
.then(() => Modem.changeTech(aTech, aTechMask))
|
||||||
|
|
||||||
|
// Tests
|
||||||
|
.then(() => testOutgoingReject())
|
||||||
|
.then(() => testOutgoingCancel())
|
||||||
|
.then(() => testOutgoingAnswerHangUp())
|
||||||
|
.then(() => testOutgoingAnswerRemoteHangUp())
|
||||||
|
.then(() => testOutgoingAnswerHoldHangUp())
|
||||||
|
.then(() => testOutgoingAnswerHoldRemoteHangUp())
|
||||||
|
.then(() => testOutgoingAnswerHoldResumeHangUp())
|
||||||
|
.then(() => testOutgoingAnswerHoldResumeRemoteHangUp())
|
||||||
|
|
||||||
|
// Restore Environment
|
||||||
|
.then(() => Modem.changeTech("wcdma"));
|
||||||
|
}
|
||||||
|
|
||||||
|
startTest(function() {
|
||||||
|
return Promise.resolve()
|
||||||
|
.then(() => runTestSuite("cdma"))
|
||||||
|
.then(() => runTestSuite("wcdma"))
|
||||||
|
|
||||||
|
.catch(error => ok(false, "Promise reject: " + error))
|
||||||
|
.then(finish);
|
||||||
|
});
|
||||||
|
|
|
@ -1,123 +0,0 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
MARIONETTE_TIMEOUT = 90000;
|
|
||||||
MARIONETTE_HEAD_JS = 'head.js';
|
|
||||||
|
|
||||||
const inNumber = "5555552222";
|
|
||||||
const inInfo = gInCallStrPool(inNumber);
|
|
||||||
var inCall;
|
|
||||||
|
|
||||||
function incoming() {
|
|
||||||
return gRemoteDial(inNumber)
|
|
||||||
.then(call => inCall = call)
|
|
||||||
.then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
|
|
||||||
.then(() => is(inCall.disconnectedReason, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
function answer() {
|
|
||||||
return gAnswer(inCall)
|
|
||||||
.then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
|
|
||||||
.then(() => is(inCall.disconnectedReason, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
function hold() {
|
|
||||||
return gHold(inCall)
|
|
||||||
.then(() => gCheckAll(null, [inCall], "", [], [inInfo.held]))
|
|
||||||
.then(() => is(inCall.disconnectedReason, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
function resume() {
|
|
||||||
return gResume(inCall)
|
|
||||||
.then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
|
|
||||||
.then(() => is(inCall.disconnectedReason, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
function hangUp() {
|
|
||||||
return gHangUp(inCall)
|
|
||||||
.then(() => gCheckAll(null, [], "", [], []))
|
|
||||||
.then(() => is(inCall.disconnectedReason, "NormalCallClearing"));
|
|
||||||
}
|
|
||||||
|
|
||||||
function remoteHangUp() {
|
|
||||||
return gRemoteHangUp(inCall)
|
|
||||||
.then(() => gCheckAll(null, [], "", [], []))
|
|
||||||
.then(() => is(inCall.disconnectedReason, "NormalCallClearing"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test cases.
|
|
||||||
|
|
||||||
function testIncomingReject() {
|
|
||||||
log("= testIncomingReject =");
|
|
||||||
return incoming()
|
|
||||||
.then(() => hangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
function testIncomingCancel() {
|
|
||||||
log("= testIncomingCancel =");
|
|
||||||
return incoming()
|
|
||||||
.then(() => remoteHangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
function testIncomingAnswerHangUp() {
|
|
||||||
log("= testIncomingAnswerHangUp =");
|
|
||||||
return incoming()
|
|
||||||
.then(() => answer())
|
|
||||||
.then(() => hangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
function testIncomingAnswerRemoteHangUp() {
|
|
||||||
log("= testIncomingAnswerRemoteHangUp =");
|
|
||||||
return incoming()
|
|
||||||
.then(() => answer())
|
|
||||||
.then(() => remoteHangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
function testIncomingAnswerHoldHangUp() {
|
|
||||||
log("= testIncomingAnswerHoldHangUp =");
|
|
||||||
return incoming()
|
|
||||||
.then(() => answer())
|
|
||||||
.then(() => hold())
|
|
||||||
.then(() => hangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
function testIncomingAnswerHoldRemoteHangUp() {
|
|
||||||
log("= testIncomingAnswerHoldRemoteHangUp =");
|
|
||||||
return incoming()
|
|
||||||
.then(() => answer())
|
|
||||||
.then(() => hold())
|
|
||||||
.then(() => remoteHangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
function testIncomingAnswerHoldResumeHangUp() {
|
|
||||||
log("= testIncomingAnswerHoldResumeHangUp =");
|
|
||||||
return incoming()
|
|
||||||
.then(() => answer())
|
|
||||||
.then(() => hold())
|
|
||||||
.then(() => resume())
|
|
||||||
.then(() => hangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
function testIncomingAnswerHoldResumeRemoteHangUp() {
|
|
||||||
log("= testIncomingAnswerHoldResumeRemoteHangUp =");
|
|
||||||
return incoming()
|
|
||||||
.then(() => answer())
|
|
||||||
.then(() => hold())
|
|
||||||
.then(() => resume())
|
|
||||||
.then(() => remoteHangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
startTest(function() {
|
|
||||||
Promise.resolve()
|
|
||||||
.then(() => testIncomingReject())
|
|
||||||
.then(() => testIncomingCancel())
|
|
||||||
.then(() => testIncomingAnswerHangUp())
|
|
||||||
.then(() => testIncomingAnswerRemoteHangUp())
|
|
||||||
.then(() => testIncomingAnswerHoldHangUp())
|
|
||||||
.then(() => testIncomingAnswerHoldRemoteHangUp())
|
|
||||||
.then(() => testIncomingAnswerHoldResumeHangUp())
|
|
||||||
.then(() => testIncomingAnswerHoldResumeRemoteHangUp())
|
|
||||||
|
|
||||||
.catch(error => ok(false, "Promise reject: " + error))
|
|
||||||
.then(finish);
|
|
||||||
});
|
|
|
@ -39,7 +39,7 @@ var settings = [
|
||||||
startTest(function() {
|
startTest(function() {
|
||||||
|
|
||||||
let promise = settings.reduce((aPromise, aSetting) => {
|
let promise = settings.reduce((aPromise, aSetting) => {
|
||||||
return aPromise.then(() => gChangeModemTech(aSetting.tech, aSetting.mask));
|
return aPromise.then(() => Modem.changeTech(aSetting.tech, aSetting.mask));
|
||||||
}, Promise.resolve());
|
}, Promise.resolve());
|
||||||
|
|
||||||
return promise
|
return promise
|
||||||
|
@ -47,7 +47,7 @@ startTest(function() {
|
||||||
.catch(error => ok(false, "Promise reject: " + error))
|
.catch(error => ok(false, "Promise reject: " + error))
|
||||||
|
|
||||||
// Switch to the default modem tech
|
// Switch to the default modem tech
|
||||||
.then(() => gChangeModemTech("wcdma", "gsm/wcdma"))
|
.then(() => Modem.changeTech("wcdma", "gsm/wcdma"))
|
||||||
.catch(error => ok(false, "Fetal Error: Promise reject: " + error))
|
.catch(error => ok(false, "Fetal Error: Promise reject: " + error))
|
||||||
|
|
||||||
.then(finish);
|
.then(finish);
|
||||||
|
|
|
@ -37,7 +37,7 @@ function testAutoHoldCallFailed() {
|
||||||
const callNumber2 = "0900000012";
|
const callNumber2 = "0900000012";
|
||||||
|
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
.then(() => emulator.runCmd("gsm disable hold"))
|
.then(() => emulator.runCmd("telephony disable hold"))
|
||||||
.then(() => gDial(callNumber1))
|
.then(() => gDial(callNumber1))
|
||||||
.then(call => { outCall1 = call; })
|
.then(call => { outCall1 = call; })
|
||||||
.then(() => gRemoteAnswer(outCall1))
|
.then(() => gRemoteAnswer(outCall1))
|
||||||
|
@ -51,7 +51,7 @@ function testAutoHoldCallFailed() {
|
||||||
return gRemoteHangUpCalls([outCall2]);
|
return gRemoteHangUpCalls([outCall2]);
|
||||||
}, () => log("The second |dial()| is rejected as expected."))
|
}, () => log("The second |dial()| is rejected as expected."))
|
||||||
.then(() => gRemoteHangUpCalls([outCall1]))
|
.then(() => gRemoteHangUpCalls([outCall1]))
|
||||||
.then(() => emulator.runCmd("gsm enable hold"));
|
.then(() => emulator.runCmd("telephony enable hold"));
|
||||||
}
|
}
|
||||||
|
|
||||||
function testAutoHoldConferenceCall() {
|
function testAutoHoldConferenceCall() {
|
||||||
|
@ -87,7 +87,7 @@ startTest(function() {
|
||||||
.then(() => testAutoHoldConferenceCall())
|
.then(() => testAutoHoldConferenceCall())
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
ok(false, "Promise reject: " + error);
|
ok(false, "Promise reject: " + error);
|
||||||
emulator.runCmd("gsm enable hold");
|
emulator.runCmd("telephony enable hold");
|
||||||
})
|
})
|
||||||
.then(finish);
|
.then(finish);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,123 +0,0 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
MARIONETTE_TIMEOUT = 90000;
|
|
||||||
MARIONETTE_HEAD_JS = 'head.js';
|
|
||||||
|
|
||||||
const outNumber = "5555551111";
|
|
||||||
const outInfo = gOutCallStrPool(outNumber);
|
|
||||||
var outCall;
|
|
||||||
|
|
||||||
function outgoing() {
|
|
||||||
return gDial(outNumber)
|
|
||||||
.then(call => outCall = call)
|
|
||||||
.then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing]))
|
|
||||||
.then(() => is(outCall.disconnectedReason, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
function answer() {
|
|
||||||
return gRemoteAnswer(outCall)
|
|
||||||
.then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
|
|
||||||
.then(() => is(outCall.disconnectedReason, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
function hangUp() {
|
|
||||||
return gHangUp(outCall)
|
|
||||||
.then(() => gCheckAll(null, [], "", [], []))
|
|
||||||
.then(() => is(outCall.disconnectedReason, "NormalCallClearing"));
|
|
||||||
}
|
|
||||||
|
|
||||||
function remoteHangUp() {
|
|
||||||
return gRemoteHangUp(outCall)
|
|
||||||
.then(() => gCheckAll(null, [], "", [], []))
|
|
||||||
.then(() => is(outCall.disconnectedReason, "NormalCallClearing"));
|
|
||||||
}
|
|
||||||
|
|
||||||
function hold() {
|
|
||||||
return gHold(outCall)
|
|
||||||
.then(() => gCheckAll(null, [outCall], "", [], [outInfo.held]))
|
|
||||||
.then(() => is(outCall.disconnectedReason, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
function resume() {
|
|
||||||
return gResume(outCall)
|
|
||||||
.then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
|
|
||||||
.then(() => is(outCall.disconnectedReason, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test cases.
|
|
||||||
|
|
||||||
function testOutgoingReject() {
|
|
||||||
log("= testOutgoingReject =");
|
|
||||||
return outgoing()
|
|
||||||
.then(() => remoteHangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
function testOutgoingCancel() {
|
|
||||||
log("= testOutgoingCancel =");
|
|
||||||
return outgoing()
|
|
||||||
.then(() => hangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
function testOutgoingAnswerHangUp() {
|
|
||||||
log("= testOutgoingAnswerHangUp =");
|
|
||||||
return outgoing()
|
|
||||||
.then(() => answer())
|
|
||||||
.then(() => hangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
function testOutgoingAnswerRemoteHangUp() {
|
|
||||||
log("= testOutgoingAnswerRemoteHangUp =");
|
|
||||||
return outgoing()
|
|
||||||
.then(() => answer())
|
|
||||||
.then(() => remoteHangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
function testOutgoingAnswerHoldHangUp() {
|
|
||||||
log("= testOutgoingAnswerHoldHangUp =");
|
|
||||||
return outgoing()
|
|
||||||
.then(() => answer())
|
|
||||||
.then(() => hold())
|
|
||||||
.then(() => hangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
function testOutgoingAnswerHoldRemoteHangUp() {
|
|
||||||
log("= testOutgoingAnswerHoldRemoteHangUp =");
|
|
||||||
return outgoing()
|
|
||||||
.then(() => answer())
|
|
||||||
.then(() => hold())
|
|
||||||
.then(() => remoteHangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
function testOutgoingAnswerHoldResumeHangUp() {
|
|
||||||
log("= testOutgoingAnswerHoldResumeHangUp =");
|
|
||||||
return outgoing()
|
|
||||||
.then(() => answer())
|
|
||||||
.then(() => hold())
|
|
||||||
.then(() => resume())
|
|
||||||
.then(() => hangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
function testOutgoingAnswerHoldResumeRemoteHangUp() {
|
|
||||||
log("= testOutgoingAnswerHoldResumeRemoteHangUp =");
|
|
||||||
return outgoing()
|
|
||||||
.then(() => answer())
|
|
||||||
.then(() => hold())
|
|
||||||
.then(() => resume())
|
|
||||||
.then(() => remoteHangUp());
|
|
||||||
}
|
|
||||||
|
|
||||||
startTest(function() {
|
|
||||||
Promise.resolve()
|
|
||||||
.then(() => testOutgoingReject())
|
|
||||||
.then(() => testOutgoingCancel())
|
|
||||||
.then(() => testOutgoingAnswerHangUp())
|
|
||||||
.then(() => testOutgoingAnswerRemoteHangUp())
|
|
||||||
.then(() => testOutgoingAnswerHoldHangUp())
|
|
||||||
.then(() => testOutgoingAnswerHoldRemoteHangUp())
|
|
||||||
.then(() => testOutgoingAnswerHoldResumeHangUp())
|
|
||||||
.then(() => testOutgoingAnswerHoldResumeRemoteHangUp())
|
|
||||||
|
|
||||||
.catch(error => ok(false, "Promise reject: " + error))
|
|
||||||
.then(finish);
|
|
||||||
});
|
|
|
@ -19,7 +19,7 @@ startTest(function() {
|
||||||
is(event.call.error.name, "BusyError");
|
is(event.call.error.name, "BusyError");
|
||||||
is(event.call.disconnectedReason, "Busy");
|
is(event.call.disconnectedReason, "Busy");
|
||||||
});
|
});
|
||||||
let p2 = emulator.runCmd("gsm busy " + outNumber);
|
let p2 = emulator.runCmd("telephony busy " + outNumber);
|
||||||
return Promise.all([p1, p2]);
|
return Promise.all([p1, p2]);
|
||||||
})
|
})
|
||||||
.then(() => gCheckAll(null, [], "", [], []))
|
.then(() => gCheckAll(null, [], "", [], []))
|
||||||
|
|
|
@ -1023,6 +1023,41 @@ public:
|
||||||
WarnAboutTrailingData();
|
WarnAboutTrailingData();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T1, typename T2, typename T3, typename T4,
|
||||||
|
typename T5, typename T6>
|
||||||
|
nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4,
|
||||||
|
T5& aArg5, T6& aArg6) const
|
||||||
|
{
|
||||||
|
DaemonSocketPDU& pdu = GetPDU();
|
||||||
|
|
||||||
|
nsresult rv = UnpackPDU(pdu, aArg1);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
rv = UnpackPDU(pdu, aArg2);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
rv = UnpackPDU(pdu, aArg3);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
rv = UnpackPDU(pdu, aArg4);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
rv = UnpackPDU(pdu, aArg5);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
rv = UnpackPDU(pdu, aArg6);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
WarnAboutTrailingData();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace DaemonSocketPDUHelpers
|
} // namespace DaemonSocketPDUHelpers
|
||||||
|
|
|
@ -2,14 +2,19 @@
|
||||||
<!-- 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/. -->
|
||||||
<FrameLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
<!-- Ignore UseCompoundDrawables because they caused a regression in bug 1208790. -->
|
||||||
android:layout_height="match_parent"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent">
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
tools:ignore="UseCompoundDrawables"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingRight="?android:attr/scrollbarSize">
|
||||||
|
|
||||||
<TextView android:id="@+id/label_search_hint"
|
<TextView android:id="@+id/label_search_hint"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
android:text="@string/pref_search_hint"
|
android:text="@string/pref_search_hint"
|
||||||
android:layout_marginTop="5dip"
|
android:layout_marginTop="5dip"
|
||||||
android:layout_marginBottom="6dip"
|
android:layout_marginBottom="6dip"
|
||||||
|
@ -17,8 +22,13 @@
|
||||||
android:layout_marginRight="6dip"
|
android:layout_marginRight="6dip"
|
||||||
android:paddingTop="8dp"
|
android:paddingTop="8dp"
|
||||||
android:paddingBottom="8dp"
|
android:paddingBottom="8dp"
|
||||||
android:paddingRight="8dip"
|
android:paddingRight="6dip"
|
||||||
android:drawableRight="@drawable/tip_addsearch"
|
android:layout_weight="1"/>
|
||||||
android:drawablePadding="6dp"/>
|
|
||||||
|
|
||||||
</FrameLayout>
|
<ImageView android:layout_height="wrap_content"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
android:paddingTop="12dip"
|
||||||
|
android:src="@drawable/tip_addsearch"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
|
@ -11,7 +11,6 @@ import org.mozilla.gecko.GeckoAppShell;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.content.SharedPreferences.Editor;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class Allocator {
|
public class Allocator {
|
||||||
|
@ -46,6 +45,8 @@ public class Allocator {
|
||||||
|
|
||||||
SharedPreferences mPrefs;
|
SharedPreferences mPrefs;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation") // Suppressing deprecation notification for Context.MODE_MULTI_PROCESS until we
|
||||||
|
// reach a timeline for removal of the whole feature. (Bug 1171213)
|
||||||
protected Allocator(Context context) {
|
protected Allocator(Context context) {
|
||||||
mPrefs = context.getSharedPreferences("webapps", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS);
|
mPrefs = context.getSharedPreferences("webapps", Context.MODE_PRIVATE | Context.MODE_MULTI_PROCESS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ var CastingApps = {
|
||||||
mirrorStopMenuId: -1,
|
mirrorStopMenuId: -1,
|
||||||
_blocked: null,
|
_blocked: null,
|
||||||
_bound: null,
|
_bound: null,
|
||||||
|
_interval: 120 * 1000, // 120 seconds
|
||||||
|
|
||||||
init: function ca_init() {
|
init: function ca_init() {
|
||||||
if (!this.isCastingEnabled()) {
|
if (!this.isCastingEnabled()) {
|
||||||
|
@ -78,8 +79,8 @@ var CastingApps = {
|
||||||
mediaPlayerDevice.init();
|
mediaPlayerDevice.init();
|
||||||
SimpleServiceDiscovery.registerDevice(mediaPlayerDevice);
|
SimpleServiceDiscovery.registerDevice(mediaPlayerDevice);
|
||||||
|
|
||||||
// Search for devices continuously every 120 seconds
|
// Search for devices continuously
|
||||||
SimpleServiceDiscovery.search(120 * 1000);
|
SimpleServiceDiscovery.search(this._interval);
|
||||||
|
|
||||||
this._castMenuId = NativeWindow.contextmenus.add(
|
this._castMenuId = NativeWindow.contextmenus.add(
|
||||||
Strings.browser.GetStringFromName("contextmenu.sendToDevice"),
|
Strings.browser.GetStringFromName("contextmenu.sendToDevice"),
|
||||||
|
@ -93,6 +94,8 @@ var CastingApps = {
|
||||||
Services.obs.addObserver(this, "Casting:Mirror", false);
|
Services.obs.addObserver(this, "Casting:Mirror", false);
|
||||||
Services.obs.addObserver(this, "ssdp-service-found", false);
|
Services.obs.addObserver(this, "ssdp-service-found", false);
|
||||||
Services.obs.addObserver(this, "ssdp-service-lost", false);
|
Services.obs.addObserver(this, "ssdp-service-lost", false);
|
||||||
|
Services.obs.addObserver(this, "application-background", false);
|
||||||
|
Services.obs.addObserver(this, "application-foreground", false);
|
||||||
|
|
||||||
BrowserApp.deck.addEventListener("TabSelect", this, true);
|
BrowserApp.deck.addEventListener("TabSelect", this, true);
|
||||||
BrowserApp.deck.addEventListener("pageshow", this, true);
|
BrowserApp.deck.addEventListener("pageshow", this, true);
|
||||||
|
@ -195,15 +198,20 @@ var CastingApps = {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "ssdp-service-found":
|
case "ssdp-service-found":
|
||||||
{
|
this.serviceAdded(SimpleServiceDiscovery.findServiceForID(aData));
|
||||||
this.serviceAdded(SimpleServiceDiscovery.findServiceForID(aData));
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "ssdp-service-lost":
|
case "ssdp-service-lost":
|
||||||
{
|
this.serviceLost(SimpleServiceDiscovery.findServiceForID(aData));
|
||||||
this.serviceLost(SimpleServiceDiscovery.findServiceForID(aData));
|
break;
|
||||||
break;
|
case "application-background":
|
||||||
}
|
// Turn off polling while in the background
|
||||||
|
this._interval = SimpleServiceDiscovery.search(0);
|
||||||
|
SimpleServiceDiscovery.stopSearch();
|
||||||
|
break;
|
||||||
|
case "application-foreground":
|
||||||
|
// Turn polling on when app comes back to foreground
|
||||||
|
SimpleServiceDiscovery.search(this._interval);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ this.EXPORTED_SYMBOLS = [
|
||||||
|
|
||||||
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/AppConstants.jsm");
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://gre/modules/Task.jsm");
|
Cu.import("resource://gre/modules/Task.jsm");
|
||||||
|
@ -458,5 +459,147 @@ this.BrowserTestUtils = {
|
||||||
tab.ownerDocument.defaultView.gBrowser.removeTab(tab);
|
tab.ownerDocument.defaultView.gBrowser.removeTab(tab);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crashes a remote browser tab and cleans up the generated minidumps.
|
||||||
|
* Resolves with the data from the .extra file (the crash annotations).
|
||||||
|
*
|
||||||
|
* @param (Browser) browser
|
||||||
|
* A remote <xul:browser> element. Must not be null.
|
||||||
|
*
|
||||||
|
* @returns (Promise)
|
||||||
|
* @resolves An Object with key-value pairs representing the data from the
|
||||||
|
* crash report's extra file (if applicable).
|
||||||
|
*/
|
||||||
|
crashBrowser: Task.async(function*(browser) {
|
||||||
|
let extra = {};
|
||||||
|
let KeyValueParser = {};
|
||||||
|
if (AppConstants.MOZ_CRASHREPORTER) {
|
||||||
|
Cu.import("resource://gre/modules/KeyValueParser.jsm", KeyValueParser);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!browser.isRemoteBrowser) {
|
||||||
|
throw new Error("<xul:browser> needs to be remote in order to crash");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the directory where crash dumps are stored.
|
||||||
|
*
|
||||||
|
* @return nsIFile
|
||||||
|
*/
|
||||||
|
function getMinidumpDirectory() {
|
||||||
|
let dir = Services.dirsvc.get('ProfD', Ci.nsIFile);
|
||||||
|
dir.append("minidumps");
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a file from a directory. This is a no-op if the file does not
|
||||||
|
* exist.
|
||||||
|
*
|
||||||
|
* @param directory
|
||||||
|
* The nsIFile representing the directory to remove from.
|
||||||
|
* @param filename
|
||||||
|
* A string for the file to remove from the directory.
|
||||||
|
*/
|
||||||
|
function removeFile(directory, filename) {
|
||||||
|
let file = directory.clone();
|
||||||
|
file.append(filename);
|
||||||
|
if (file.exists()) {
|
||||||
|
file.remove(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This frame script is injected into the remote browser, and used to
|
||||||
|
// intentionally crash the tab. We crash by using js-ctypes and dereferencing
|
||||||
|
// a bad pointer. The crash should happen immediately upon loading this
|
||||||
|
// frame script.
|
||||||
|
let frame_script = () => {
|
||||||
|
const Cu = Components.utils;
|
||||||
|
Cu.import("resource://gre/modules/ctypes.jsm");
|
||||||
|
|
||||||
|
let dies = function() {
|
||||||
|
privateNoteIntentionalCrash();
|
||||||
|
let zero = new ctypes.intptr_t(8);
|
||||||
|
let badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
|
||||||
|
badptr.contents
|
||||||
|
};
|
||||||
|
|
||||||
|
dump("\nEt tu, Brute?\n");
|
||||||
|
dies();
|
||||||
|
}
|
||||||
|
|
||||||
|
let crashCleanupPromise = new Promise((resolve, reject) => {
|
||||||
|
let observer = (subject, topic, data) => {
|
||||||
|
if (topic != "ipc:content-shutdown") {
|
||||||
|
return reject("Received incorrect observer topic: " + topic);
|
||||||
|
}
|
||||||
|
if (!(subject instanceof Ci.nsIPropertyBag2)) {
|
||||||
|
return reject("Subject did not implement nsIPropertyBag2");
|
||||||
|
}
|
||||||
|
// we might see this called as the process terminates due to previous tests.
|
||||||
|
// We are only looking for "abnormal" exits...
|
||||||
|
if (!subject.hasKey("abnormal")) {
|
||||||
|
dump("\nThis is a normal termination and isn't the one we are looking for...\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let dumpID;
|
||||||
|
if ('nsICrashReporter' in Ci) {
|
||||||
|
dumpID = subject.getPropertyAsAString('dumpID');
|
||||||
|
if (!dumpID) {
|
||||||
|
return reject("dumpID was not present despite crash reporting " +
|
||||||
|
"being enabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dumpID) {
|
||||||
|
let minidumpDirectory = getMinidumpDirectory();
|
||||||
|
let extrafile = minidumpDirectory.clone();
|
||||||
|
extrafile.append(dumpID + '.extra');
|
||||||
|
if (extrafile.exists()) {
|
||||||
|
dump(`\nNo .extra file for dumpID: ${dumpID}\n`);
|
||||||
|
if (AppConstants.MOZ_CRASHREPORTER) {
|
||||||
|
extra = KeyValueParser.parseKeyValuePairsFromFile(extrafile);
|
||||||
|
} else {
|
||||||
|
dump('\nCrashReporter not enabled - will not return any extra data\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeFile(minidumpDirectory, dumpID + '.dmp');
|
||||||
|
removeFile(minidumpDirectory, dumpID + '.extra');
|
||||||
|
}
|
||||||
|
|
||||||
|
Services.obs.removeObserver(observer, 'ipc:content-shutdown');
|
||||||
|
dump("\nCrash cleaned up\n");
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
Services.obs.addObserver(observer, 'ipc:content-shutdown', false);
|
||||||
|
});
|
||||||
|
|
||||||
|
let aboutTabCrashedLoadPromise = new Promise((resolve, reject) => {
|
||||||
|
browser.addEventListener("AboutTabCrashedLoad", function onCrash() {
|
||||||
|
browser.removeEventListener("AboutTabCrashedLoad", onCrash, false);
|
||||||
|
dump("\nabout:tabcrashed loaded\n");
|
||||||
|
resolve();
|
||||||
|
}, false, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
// This frame script will crash the remote browser as soon as it is
|
||||||
|
// evaluated.
|
||||||
|
let mm = browser.messageManager;
|
||||||
|
mm.loadFrameScript("data:,(" + frame_script.toString() + ")();", false);
|
||||||
|
|
||||||
|
yield Promise.all([crashCleanupPromise, aboutTabCrashedLoadPromise]);
|
||||||
|
|
||||||
|
let gBrowser = browser.ownerDocument.defaultView.gBrowser;
|
||||||
|
let tab = gBrowser.getTabForBrowser(browser);
|
||||||
|
if (tab.getAttribute("crashed") != "true") {
|
||||||
|
throw new Error("Tab should be marked as crashed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return extra;
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,72 +9,6 @@
|
||||||
// Running this test in ASAN is slow.
|
// Running this test in ASAN is slow.
|
||||||
requestLongerTimeout(2);
|
requestLongerTimeout(2);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a Promise that resolves once a remote <xul:browser> has experienced
|
|
||||||
* a crash. Resolves with the data from the .extra file (the crash annotations).
|
|
||||||
*
|
|
||||||
* @param browser
|
|
||||||
* The <xul:browser> that will crash
|
|
||||||
* @return Promise
|
|
||||||
*/
|
|
||||||
function crashBrowser(browser) {
|
|
||||||
let kv = {};
|
|
||||||
Cu.import("resource://gre/modules/KeyValueParser.jsm", kv);
|
|
||||||
// This frame script is injected into the remote browser, and used to
|
|
||||||
// intentionally crash the tab. We crash by using js-ctypes and dereferencing
|
|
||||||
// a bad pointer. The crash should happen immediately upon loading this
|
|
||||||
// frame script.
|
|
||||||
let frame_script = () => {
|
|
||||||
const Cu = Components.utils;
|
|
||||||
Cu.import("resource://gre/modules/ctypes.jsm");
|
|
||||||
|
|
||||||
let dies = function() {
|
|
||||||
privateNoteIntentionalCrash();
|
|
||||||
let zero = new ctypes.intptr_t(8);
|
|
||||||
let badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
|
|
||||||
let crash = badptr.contents;
|
|
||||||
};
|
|
||||||
|
|
||||||
dump("Et tu, Brute?");
|
|
||||||
dies();
|
|
||||||
};
|
|
||||||
|
|
||||||
function checkSubject(subject, data) {
|
|
||||||
return subject instanceof Ci.nsIPropertyBag2 &&
|
|
||||||
subject.hasKey("abnormal");
|
|
||||||
};
|
|
||||||
let crashPromise = TestUtils.topicObserved('ipc:content-shutdown',
|
|
||||||
checkSubject);
|
|
||||||
let crashDataPromise = crashPromise.then(([subject, data]) => {
|
|
||||||
ok(subject instanceof Ci.nsIPropertyBag2);
|
|
||||||
|
|
||||||
let dumpID;
|
|
||||||
if ('nsICrashReporter' in Ci) {
|
|
||||||
dumpID = subject.getPropertyAsAString('dumpID');
|
|
||||||
ok(dumpID, "dumpID is present and not an empty string");
|
|
||||||
}
|
|
||||||
|
|
||||||
let extra = null;
|
|
||||||
if (dumpID) {
|
|
||||||
let minidumpDirectory = getMinidumpDirectory();
|
|
||||||
let extrafile = minidumpDirectory.clone();
|
|
||||||
extrafile.append(dumpID + '.extra');
|
|
||||||
ok(extrafile.exists(), 'found .extra file');
|
|
||||||
extra = kv.parseKeyValuePairsFromFile(extrafile);
|
|
||||||
removeFile(minidumpDirectory, dumpID + '.dmp');
|
|
||||||
removeFile(minidumpDirectory, dumpID + '.extra');
|
|
||||||
}
|
|
||||||
|
|
||||||
return extra;
|
|
||||||
});
|
|
||||||
|
|
||||||
// This frame script will crash the remote browser as soon as it is
|
|
||||||
// evaluated.
|
|
||||||
let mm = browser.messageManager;
|
|
||||||
mm.loadFrameScript("data:,(" + frame_script.toString() + ")();", false);
|
|
||||||
return crashDataPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a file from a directory. This is a no-op if the file does not
|
* Removes a file from a directory. This is a no-op if the file does not
|
||||||
* exist.
|
* exist.
|
||||||
|
@ -130,7 +64,7 @@ add_task(function* test_content_url_annotation() {
|
||||||
yield promise;
|
yield promise;
|
||||||
|
|
||||||
// Crash the tab
|
// Crash the tab
|
||||||
let annotations = yield crashBrowser(browser);
|
let annotations = yield BrowserTestUtils.crashBrowser(browser);
|
||||||
|
|
||||||
ok("URL" in annotations, "annotated a URL");
|
ok("URL" in annotations, "annotated a URL");
|
||||||
is(annotations.URL, redirect_url,
|
is(annotations.URL, redirect_url,
|
||||||
|
|
|
@ -483,7 +483,7 @@ this.DownloadUtils = {
|
||||||
if (aBytes === Infinity) {
|
if (aBytes === Infinity) {
|
||||||
aBytes = "Infinity";
|
aBytes = "Infinity";
|
||||||
} else {
|
} else {
|
||||||
if (Intl) {
|
if (typeof Intl != "undefined") {
|
||||||
aBytes = getLocaleNumberFormat(fractionDigits)
|
aBytes = getLocaleNumberFormat(fractionDigits)
|
||||||
.format(aBytes);
|
.format(aBytes);
|
||||||
} else if (gDecimalSymbol != ".") {
|
} else if (gDecimalSymbol != ".") {
|
||||||
|
|
|
@ -406,13 +406,11 @@ xul|button[type="menu"] > xul|menupopup xul|menuseparator {
|
||||||
|
|
||||||
/* textboxes */
|
/* textboxes */
|
||||||
|
|
||||||
*|textbox {
|
html|input[type="text"],
|
||||||
|
html|textarea,
|
||||||
|
xul|textbox {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
height: 30px;
|
|
||||||
color: var(--in-content-text-color);
|
color: var(--in-content-text-color);
|
||||||
line-height: 20px;
|
|
||||||
padding-right: 10px;
|
|
||||||
padding-left: 10px;
|
|
||||||
border: 1px solid var(--in-content-box-border-color);
|
border: 1px solid var(--in-content-box-border-color);
|
||||||
-moz-border-top-colors: none !important;
|
-moz-border-top-colors: none !important;
|
||||||
-moz-border-right-colors: none !important;
|
-moz-border-right-colors: none !important;
|
||||||
|
@ -422,12 +420,27 @@ xul|button[type="menu"] > xul|menupopup xul|menuseparator {
|
||||||
background-color: var(--in-content-box-background);
|
background-color: var(--in-content-box-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
html|textbox:focus,
|
xul|textbox {
|
||||||
|
min-height: 30px;
|
||||||
|
padding-right: 10px;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html|input[type="text"],
|
||||||
|
html|textarea {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html|input[type="text"]:focus,
|
||||||
|
html|textarea:focus,
|
||||||
xul|textbox[focused] {
|
xul|textbox[focused] {
|
||||||
border-color: var(--in-content-border-focus);
|
border-color: var(--in-content-border-focus);
|
||||||
}
|
}
|
||||||
|
|
||||||
html|textbox:disabled,
|
html|input[type="text"]:disabled,
|
||||||
|
html|textarea:disabled,
|
||||||
xul|textbox[disabled="true"] {
|
xul|textbox[disabled="true"] {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче