mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge b2g-inbound to m-c. a=merge
This commit is contained in:
commit
f5d8dbcd9f
@ -15,9 +15,9 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
@ -15,9 +15,9 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
@ -19,8 +19,8 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aac9cc4bb94cf720baf8f7ee419b4d76ac86b1ac"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="10b3daf0093db94c64e78a72ac43a93b68976087"/>
|
||||
|
@ -17,8 +17,8 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5c487ecd9afbcea1d507b9e4dfd09b3a8787fa65"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
|
@ -15,9 +15,9 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
@ -15,9 +15,9 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
@ -19,8 +19,8 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="aac9cc4bb94cf720baf8f7ee419b4d76ac86b1ac"/>
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="10b3daf0093db94c64e78a72ac43a93b68976087"/>
|
||||
|
@ -15,9 +15,9 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "477b5672811ed970a7476fe6f67dba546a302dce",
|
||||
"git_revision": "45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "5bab67b888d1491d1718cf1a7349bcef3114cbab",
|
||||
"revision": "936633804b786ab99d2afc97311dc5cedeade648",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -17,8 +17,8 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5c487ecd9afbcea1d507b9e4dfd09b3a8787fa65"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
|
@ -15,9 +15,9 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="477b5672811ed970a7476fe6f67dba546a302dce"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="45dc6306cf502a4f00ae9f8bd8293a8a3a37c07b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="fffc68521ebb1501d6b015c6d1c4a17a04fdb2e2"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5deaf27fd266316f27e68206cc3be0e6f47ded54"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
|
@ -281,6 +281,7 @@
|
||||
@RESPATH@/components/necko_file.xpt
|
||||
@RESPATH@/components/necko_ftp.xpt
|
||||
@RESPATH@/components/necko_http.xpt
|
||||
@RESPATH@/components/necko_mdns.xpt
|
||||
@RESPATH@/components/necko_res.xpt
|
||||
@RESPATH@/components/necko_socket.xpt
|
||||
@RESPATH@/components/necko_strconv.xpt
|
||||
|
@ -286,6 +286,7 @@
|
||||
@RESPATH@/components/necko_file.xpt
|
||||
@RESPATH@/components/necko_ftp.xpt
|
||||
@RESPATH@/components/necko_http.xpt
|
||||
@RESPATH@/components/necko_mdns.xpt
|
||||
@RESPATH@/components/necko_res.xpt
|
||||
@RESPATH@/components/necko_socket.xpt
|
||||
@RESPATH@/components/necko_strconv.xpt
|
||||
|
@ -395,6 +395,9 @@ DiskInit.h
|
||||
dlfcn.h
|
||||
dlgs.h
|
||||
dl.h
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
dns_sd.h
|
||||
#endif
|
||||
docobj.h
|
||||
dos/dosextens.h
|
||||
dos.h
|
||||
|
@ -227,7 +227,7 @@ if test -n "$gonkdir" ; then
|
||||
MOZ_SECUREELEMENT=1
|
||||
;;
|
||||
17|18)
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include -I$gonkdir/external/mdnsresponder/mDNSShared"
|
||||
if test -d "$gonkdir/external/bluetooth/bluez"; then
|
||||
GONK_INCLUDES="$GONK_INCLUDES -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib"
|
||||
MOZ_B2G_BT=1
|
||||
@ -252,7 +252,7 @@ if test -n "$gonkdir" ; then
|
||||
MOZ_SECUREELEMENT=1
|
||||
;;
|
||||
19)
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include -I$gonkdir/external/mdnsresponder/mDNSShared"
|
||||
MOZ_B2G_CAMERA=1
|
||||
MOZ_B2G_BT=1
|
||||
MOZ_B2G_BT_BLUEDROID=1
|
||||
@ -271,7 +271,7 @@ if test -n "$gonkdir" ; then
|
||||
MOZ_FMP4=1
|
||||
;;
|
||||
21|22)
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include -I$gonkdir/external/mdnsresponder/mDNSShared"
|
||||
MOZ_AUDIO_OFFLOAD=1
|
||||
MOZ_OMX_DECODER=1
|
||||
MOZ_OMX_ENCODER=1
|
||||
|
@ -479,7 +479,10 @@ BluetoothGattManager::UnregisterClient(int aClientIf,
|
||||
|
||||
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
|
||||
ClientIfComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
client->mUnregisterClientRunnable = aRunnable;
|
||||
@ -580,7 +583,7 @@ BluetoothGattManager::StartLeScan(const nsTArray<nsString>& aServiceUuids,
|
||||
size_t index = sClients->IndexOf(appUuidStr, 0 /* Start */, UuidComparator());
|
||||
|
||||
// Reject the startLeScan request if the clientIf is being used.
|
||||
if (index != sClients->NoIndex) {
|
||||
if (NS_WARN_IF(index != sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("start LE scan failed"));
|
||||
return;
|
||||
@ -738,7 +741,10 @@ BluetoothGattManager::Disconnect(const nsAString& aAppUuid,
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
client->mDisconnectRunnable = aRunnable;
|
||||
@ -782,7 +788,10 @@ BluetoothGattManager::Discover(const nsAString& aAppUuid,
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
MOZ_ASSERT(client->mConnId > 0);
|
||||
@ -851,7 +860,10 @@ BluetoothGattManager::ReadRemoteRssi(int aClientIf,
|
||||
|
||||
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
|
||||
ClientIfComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
client->mReadRemoteRssiRunnable = aRunnable;
|
||||
@ -915,7 +927,10 @@ BluetoothGattManager::RegisterNotifications(
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
@ -988,7 +1003,10 @@ BluetoothGattManager::DeregisterNotifications(
|
||||
ENSURE_GATT_CLIENT_INTF_IS_READY_VOID(aRunnable);
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
@ -1049,9 +1067,7 @@ BluetoothGattManager::ReadCharacteristicValue(
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
// Reject the read characteristic value request
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("ReadCharacteristicValue failed"));
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1131,9 +1147,7 @@ BluetoothGattManager::WriteCharacteristicValue(
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
// Reject the write characteristic value request
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("WriteCharacteristicValue failed"));
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1214,9 +1228,7 @@ BluetoothGattManager::ReadDescriptorValue(
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
// Reject the read descriptor value request
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("ReadDescriptorValue failed"));
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1297,9 +1309,7 @@ BluetoothGattManager::WriteDescriptorValue(
|
||||
|
||||
size_t index = sClients->IndexOf(aAppUuid, 0 /* Start */, UuidComparator());
|
||||
if (NS_WARN_IF(index == sClients->NoIndex)) {
|
||||
// Reject the write descriptor value request
|
||||
DispatchReplyError(aRunnable,
|
||||
NS_LITERAL_STRING("WriteDescriptorValue failed"));
|
||||
DispatchReplyError(aRunnable, STATUS_PARM_INVALID);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1352,7 +1362,8 @@ BluetoothGattManager::RegisterClientNotification(BluetoothGattStatus aStatus,
|
||||
UuidToString(aAppUuid, uuid);
|
||||
|
||||
size_t index = sClients->IndexOf(uuid, 0 /* Start */, UuidComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
BluetoothService* bs = BluetoothService::Get();
|
||||
@ -1447,7 +1458,8 @@ BluetoothGattManager::ConnectNotification(int aConnId,
|
||||
|
||||
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
|
||||
ClientIfComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
if (aStatus != GATT_STATUS_SUCCESS) {
|
||||
@ -1499,7 +1511,8 @@ BluetoothGattManager::DisconnectNotification(int aConnId,
|
||||
|
||||
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
|
||||
ClientIfComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
if (aStatus != GATT_STATUS_SUCCESS) {
|
||||
@ -1545,7 +1558,7 @@ BluetoothGattManager::SearchCompleteNotification(int aConnId,
|
||||
|
||||
size_t index = sClients->IndexOf(aConnId, 0 /* Start */,
|
||||
ConnIdComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
MOZ_ASSERT(client->mDiscoverRunnable);
|
||||
@ -1582,7 +1595,7 @@ BluetoothGattManager::SearchResultNotification(
|
||||
|
||||
size_t index = sClients->IndexOf(aConnId, 0 /* Start */,
|
||||
ConnIdComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
// Save to mServices for distributing to application and discovering
|
||||
// included services, characteristics of this service later
|
||||
@ -1603,7 +1616,7 @@ BluetoothGattManager::GetCharacteristicNotification(
|
||||
|
||||
size_t index = sClients->IndexOf(aConnId, 0 /* Start */,
|
||||
ConnIdComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
MOZ_ASSERT(client->mDiscoverRunnable);
|
||||
@ -1655,7 +1668,7 @@ BluetoothGattManager::GetDescriptorNotification(
|
||||
|
||||
size_t index = sClients->IndexOf(aConnId, 0 /* Start */,
|
||||
ConnIdComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
MOZ_ASSERT(client->mDiscoverRunnable);
|
||||
@ -1699,7 +1712,7 @@ BluetoothGattManager::GetIncludedServiceNotification(
|
||||
|
||||
size_t index = sClients->IndexOf(aConnId, 0 /* Start */,
|
||||
ConnIdComparator());
|
||||
MOZ_ASSERT(index != sClients->NoIndex);
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
MOZ_ASSERT(client->mDiscoverRunnable);
|
||||
@ -2018,6 +2031,7 @@ BluetoothGattManager::ReadRemoteRssiNotification(int aClientIf,
|
||||
size_t index = sClients->IndexOf(aClientIf, 0 /* Start */,
|
||||
ClientIfComparator());
|
||||
NS_ENSURE_TRUE_VOID(index != sClients->NoIndex);
|
||||
|
||||
nsRefPtr<BluetoothGattClient> client = sClients->ElementAt(index);
|
||||
|
||||
if (aStatus != GATT_STATUS_SUCCESS) { // operation failed
|
||||
|
@ -385,16 +385,20 @@ BluetoothDevice::UpdatePropertiesFromAdvData(const nsTArray<uint8_t>& aAdvData)
|
||||
char uuidStr[36];
|
||||
if (type == GAP_INCOMPLETE_UUID16 || type == GAP_COMPLETE_UUID16) {
|
||||
// Convert 16-bits UUID into string.
|
||||
sprintf(uuidStr, "0000%04x-0000-1000-8000-00805f9b34fb", uuid[0]);
|
||||
} else if (type == GAP_INCOMPLETE_UUID32 || type == GAP_COMPLETE_UUID32) {
|
||||
snprintf(uuidStr, sizeof(uuidStr),
|
||||
"0000%04x-0000-1000-8000-00805f9b34fb", uuid[0]);
|
||||
} else if (type == GAP_INCOMPLETE_UUID32 ||
|
||||
type == GAP_COMPLETE_UUID32) {
|
||||
// Convert 32-bits UUID into string.
|
||||
sprintf(uuidStr, "%04x%04x-0000-1000-8000-00805f9b34fb",
|
||||
uuid[1], uuid[0]);
|
||||
} else if (type == GAP_INCOMPLETE_UUID128 || type == GAP_COMPLETE_UUID128) {
|
||||
snprintf(uuidStr, sizeof(uuidStr),
|
||||
"%04x%04x-0000-1000-8000-00805f9b34fb", uuid[1], uuid[0]);
|
||||
} else if (type == GAP_INCOMPLETE_UUID128 ||
|
||||
type == GAP_COMPLETE_UUID128) {
|
||||
// Convert 128-bits UUID into string.
|
||||
sprintf(uuidStr, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
|
||||
uuid[7], uuid[6], uuid[5], uuid[4],
|
||||
uuid[3], uuid[2], uuid[1], uuid[0]);
|
||||
snprintf(uuidStr, sizeof(uuidStr),
|
||||
"%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
|
||||
uuid[7], uuid[6], uuid[5], uuid[4],
|
||||
uuid[3], uuid[2], uuid[1], uuid[0]);
|
||||
}
|
||||
nsString uuidNsString;
|
||||
uuidNsString.AssignLiteral(uuidStr);
|
||||
|
@ -326,6 +326,9 @@ int
|
||||
GonkCameraHardware::AutoFocus()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s\n", __func__);
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
return mCamera->autoFocus();
|
||||
}
|
||||
|
||||
@ -333,6 +336,9 @@ int
|
||||
GonkCameraHardware::CancelAutoFocus()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s\n", __func__);
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
return mCamera->cancelAutoFocus();
|
||||
}
|
||||
|
||||
@ -340,8 +346,11 @@ int
|
||||
GonkCameraHardware::StartFaceDetection()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s\n", __func__);
|
||||
int rv = INVALID_OPERATION;
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
|
||||
int rv = INVALID_OPERATION;
|
||||
#if ANDROID_VERSION >= 15
|
||||
rv = mCamera->sendCommand(CAMERA_CMD_START_FACE_DETECTION, CAMERA_FACE_DETECTION_HW, 0);
|
||||
#endif
|
||||
@ -356,8 +365,11 @@ int
|
||||
GonkCameraHardware::StopFaceDetection()
|
||||
{
|
||||
DOM_CAMERA_LOGI("%s\n", __func__);
|
||||
int rv = INVALID_OPERATION;
|
||||
if (mClosing) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
|
||||
int rv = INVALID_OPERATION;
|
||||
#if ANDROID_VERSION >= 15
|
||||
rv = mCamera->sendCommand(CAMERA_CMD_STOP_FACE_DETECTION, 0, 0);
|
||||
#endif
|
||||
@ -371,6 +383,9 @@ GonkCameraHardware::StopFaceDetection()
|
||||
int
|
||||
GonkCameraHardware::TakePicture()
|
||||
{
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
return mCamera->takePicture(CAMERA_MSG_SHUTTER | CAMERA_MSG_COMPRESSED_IMAGE);
|
||||
}
|
||||
|
||||
@ -383,6 +398,9 @@ GonkCameraHardware::CancelTakePicture()
|
||||
int
|
||||
GonkCameraHardware::PushParameters(const GonkCameraParameters& aParams)
|
||||
{
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
const String8 s = aParams.Flatten();
|
||||
return mCamera->setParameters(s);
|
||||
}
|
||||
@ -390,6 +408,9 @@ GonkCameraHardware::PushParameters(const GonkCameraParameters& aParams)
|
||||
nsresult
|
||||
GonkCameraHardware::PullParameters(GonkCameraParameters& aParams)
|
||||
{
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
const String8 s = mCamera->getParameters();
|
||||
return aParams.Unflatten(s);
|
||||
}
|
||||
@ -398,6 +419,9 @@ GonkCameraHardware::PullParameters(GonkCameraParameters& aParams)
|
||||
int
|
||||
GonkCameraHardware::PushParameters(const CameraParameters& aParams)
|
||||
{
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
String8 s = aParams.flatten();
|
||||
return mCamera->setParameters(s);
|
||||
}
|
||||
@ -405,8 +429,10 @@ GonkCameraHardware::PushParameters(const CameraParameters& aParams)
|
||||
void
|
||||
GonkCameraHardware::PullParameters(CameraParameters& aParams)
|
||||
{
|
||||
const String8 s = mCamera->getParameters();
|
||||
aParams.unflatten(s);
|
||||
if (!NS_WARN_IF(mClosing)) {
|
||||
const String8 s = mCamera->getParameters();
|
||||
aParams.unflatten(s);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -414,6 +440,9 @@ int
|
||||
GonkCameraHardware::StartPreview()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
return mCamera->startPreview();
|
||||
}
|
||||
|
||||
@ -421,16 +450,20 @@ void
|
||||
GonkCameraHardware::StopPreview()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
mCamera->stopPreview();
|
||||
if (!mClosing) {
|
||||
mCamera->stopPreview();
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
GonkCameraHardware::StartRecording()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
int rv = OK;
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
|
||||
rv = mCamera->startRecording();
|
||||
int rv = mCamera->startRecording();
|
||||
if (rv != OK) {
|
||||
DOM_CAMERA_LOGE("mHardware->startRecording() failed with status %d", rv);
|
||||
}
|
||||
@ -441,6 +474,9 @@ int
|
||||
GonkCameraHardware::StopRecording()
|
||||
{
|
||||
DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
|
||||
if (mClosing) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
mCamera->stopRecording();
|
||||
return OK;
|
||||
}
|
||||
@ -456,12 +492,17 @@ GonkCameraHardware::SetListener(const sp<GonkCameraListener>& aListener)
|
||||
void
|
||||
GonkCameraHardware::ReleaseRecordingFrame(const sp<IMemory>& aFrame)
|
||||
{
|
||||
mCamera->releaseRecordingFrame(aFrame);
|
||||
if (!NS_WARN_IF(mClosing)) {
|
||||
mCamera->releaseRecordingFrame(aFrame);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
GonkCameraHardware::StoreMetaDataInBuffers(bool aEnabled)
|
||||
{
|
||||
if (NS_WARN_IF(mClosing)) {
|
||||
return DEAD_OBJECT;
|
||||
}
|
||||
return mCamera->storeMetaDataInBuffers(aEnabled);
|
||||
}
|
||||
|
@ -218,10 +218,9 @@ NfcContentHelper.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
notifyUserAcceptedP2P: function notifyUserAcceptedP2P(appId, tabId) {
|
||||
notifyUserAcceptedP2P: function notifyUserAcceptedP2P(appId) {
|
||||
cpmm.sendAsyncMessage("NFC:NotifyUserAcceptedP2P", {
|
||||
appId: appId,
|
||||
tabId: tabId
|
||||
appId: appId
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -292,7 +292,7 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
message.target.sendAsyncMessage(message.name + "Response", respMsg);
|
||||
},
|
||||
|
||||
notifyUserAcceptedP2P: function notifyUserAcceptedP2P(appId, tabId) {
|
||||
notifyUserAcceptedP2P: function notifyUserAcceptedP2P(appId) {
|
||||
let target = this.peerTargets[appId];
|
||||
let sessionToken = SessionHelper.getCurrentP2PToken();
|
||||
let isValid = (sessionToken != null) && (target != null);
|
||||
@ -301,7 +301,7 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
return;
|
||||
}
|
||||
|
||||
this.notifyDOMEvent(target, {tabId: tabId,
|
||||
this.notifyDOMEvent(target, {tabId: this.focusApp,
|
||||
event: NFC.PEER_EVENT_READY,
|
||||
sessionToken: sessionToken});
|
||||
},
|
||||
@ -408,7 +408,7 @@ XPCOMUtils.defineLazyGetter(this, "gMessageManager", function () {
|
||||
this.checkP2PRegistration(message);
|
||||
return null;
|
||||
case "NFC:NotifyUserAcceptedP2P":
|
||||
this.notifyUserAcceptedP2P(message.data.appId, message.data.tabId);
|
||||
this.notifyUserAcceptedP2P(message.data.appId);
|
||||
return null;
|
||||
case "NFC:NotifySendFileStatus":
|
||||
// Upon receiving the status of sendFile operation, send the response
|
||||
|
@ -124,7 +124,7 @@ interface nsINfcBrowserAPI : nsISupports
|
||||
in boolean isFocus);
|
||||
};
|
||||
|
||||
[scriptable, uuid(f0ed35c5-3f59-4806-b6bb-e77b879887af)]
|
||||
[scriptable, uuid(75f0c8c0-2e5a-491f-a75d-4f3849c4feec)]
|
||||
interface nsINfcContentHelper : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -277,10 +277,8 @@ interface nsINfcContentHelper : nsISupports
|
||||
*
|
||||
* @param appId
|
||||
* Application ID that is capable of handling NFC_EVENT_PEER_READY event
|
||||
* @param tabId
|
||||
* Tab Id of the window calling this interface.
|
||||
*/
|
||||
void notifyUserAcceptedP2P(in unsigned long appId, in uint64_t tabId);
|
||||
void notifyUserAcceptedP2P(in unsigned long appId);
|
||||
|
||||
/**
|
||||
* Notify the status of sendFile operation to parent process
|
||||
|
@ -420,7 +420,7 @@ MozNFCImpl.prototype = {
|
||||
notifyUserAcceptedP2P: function notifyUserAcceptedP2P(manifestUrl) {
|
||||
let appID = appsService.getAppLocalIdByManifestURL(manifestUrl);
|
||||
// Notify chrome process of user's acknowledgement
|
||||
this._nfcContentHelper.notifyUserAcceptedP2P(appID, this._tabId);
|
||||
this._nfcContentHelper.notifyUserAcceptedP2P(appID);
|
||||
},
|
||||
|
||||
notifySendFileStatus: function notifySendFileStatus(status, requestId) {
|
||||
|
@ -22,7 +22,8 @@ NS_IMPL_ISUPPORTS(PresentationDeviceManager,
|
||||
nsIPresentationDeviceManager,
|
||||
nsIPresentationDeviceListener,
|
||||
nsIPresentationDeviceEventListener,
|
||||
nsIObserver)
|
||||
nsIObserver,
|
||||
nsISupportsWeakReference)
|
||||
|
||||
PresentationDeviceManager::PresentationDeviceManager()
|
||||
{
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "nsIPresentationDeviceManager.h"
|
||||
#include "nsIPresentationDeviceProvider.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -20,6 +21,7 @@ class PresentationDeviceManager final : public nsIPresentationDeviceManager
|
||||
, public nsIPresentationDeviceListener
|
||||
, public nsIPresentationDeviceEventListener
|
||||
, public nsIObserver
|
||||
, public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
493
dom/presentation/provider/MulticastDNSDeviceProvider.cpp
Normal file
493
dom/presentation/provider/MulticastDNSDeviceProvider.cpp
Normal file
@ -0,0 +1,493 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MulticastDNSDeviceProvider.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIPresentationDevice.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
inline static PRLogModuleInfo*
|
||||
GetProviderLog()
|
||||
{
|
||||
static PRLogModuleInfo* log = PR_NewLogModule("MulticastDNSDeviceProvider");
|
||||
return log;
|
||||
}
|
||||
#undef LOG_I
|
||||
#define LOG_I(...) PR_LOG(GetProviderLog(), PR_LOG_NOTICE, (__VA_ARGS__))
|
||||
#undef LOG_E
|
||||
#define LOG_E(...) PR_LOG(GetProviderLog(), PR_LOG_ERROR, (__VA_ARGS__))
|
||||
|
||||
#define SERVICE_TYPE "_mozilla_papi._tcp."
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace presentation {
|
||||
|
||||
/**
|
||||
* This wrapper is used to break circular-reference problem.
|
||||
*/
|
||||
class DNSServiceWrappedListener final
|
||||
: public nsIDNSServiceDiscoveryListener
|
||||
, public nsIDNSRegistrationListener
|
||||
, public nsIDNSServiceResolveListener
|
||||
, public nsITCPPresentationServerListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_FORWARD_SAFE_NSIDNSSERVICEDISCOVERYLISTENER(mListener)
|
||||
NS_FORWARD_SAFE_NSIDNSREGISTRATIONLISTENER(mListener)
|
||||
NS_FORWARD_SAFE_NSIDNSSERVICERESOLVELISTENER(mListener)
|
||||
NS_FORWARD_SAFE_NSITCPPRESENTATIONSERVERLISTENER(mListener)
|
||||
|
||||
explicit DNSServiceWrappedListener() = default;
|
||||
|
||||
nsresult SetListener(MulticastDNSDeviceProvider* aListener)
|
||||
{
|
||||
mListener = aListener;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~DNSServiceWrappedListener() = default;
|
||||
|
||||
MulticastDNSDeviceProvider* mListener = nullptr;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(DNSServiceWrappedListener,
|
||||
nsIDNSServiceDiscoveryListener,
|
||||
nsIDNSRegistrationListener,
|
||||
nsIDNSServiceResolveListener,
|
||||
nsITCPPresentationServerListener)
|
||||
|
||||
NS_IMPL_ISUPPORTS(MulticastDNSDeviceProvider,
|
||||
nsIPresentationDeviceProvider,
|
||||
nsIDNSServiceDiscoveryListener,
|
||||
nsIDNSRegistrationListener,
|
||||
nsIDNSServiceResolveListener,
|
||||
nsITCPPresentationServerListener)
|
||||
|
||||
MulticastDNSDeviceProvider::~MulticastDNSDeviceProvider()
|
||||
{
|
||||
Uninit();
|
||||
}
|
||||
|
||||
nsresult
|
||||
MulticastDNSDeviceProvider::Init()
|
||||
{
|
||||
if (mInitialized) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
mMulticastDNS = do_GetService(DNSSERVICEDISCOVERY_CONTRACT_ID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mWrappedListener = new DNSServiceWrappedListener();
|
||||
if (NS_WARN_IF(!mWrappedListener)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mWrappedListener->SetListener(this)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mPresentationServer = do_CreateInstance("@mozilla.org/presentation-device/tcp-presentation-server;1", &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(mPresentationServer->SetListener(mWrappedListener)))) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->Init(EmptyCString(), 0)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
uint16_t port = 0;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->GetPort(&port)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv = RegisterService(port)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mInitialized = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MulticastDNSDeviceProvider::Uninit()
|
||||
{
|
||||
if (!mInitialized) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mPresentationServer) {
|
||||
mPresentationServer->Close();
|
||||
mPresentationServer = nullptr;
|
||||
}
|
||||
|
||||
if (mDiscoveryRequest) {
|
||||
mDiscoveryRequest->Cancel(NS_OK);
|
||||
mDiscoveryRequest = nullptr;
|
||||
}
|
||||
if (mRegisterRequest) {
|
||||
mRegisterRequest->Cancel(NS_OK);
|
||||
mRegisterRequest = nullptr;
|
||||
}
|
||||
mMulticastDNS = nullptr;
|
||||
|
||||
if (mWrappedListener) {
|
||||
mWrappedListener->SetListener(nullptr);
|
||||
mWrappedListener = nullptr;
|
||||
}
|
||||
|
||||
mInitialized = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MulticastDNSDeviceProvider::RegisterService(uint32_t aPort)
|
||||
{
|
||||
LOG_I("RegisterService: %d", aPort);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIDNSServiceInfo> serviceInfo = do_CreateInstance(DNSSERVICEINFO_CONTRACT_ID, &rv);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = serviceInfo->SetServiceType(NS_LITERAL_CSTRING(SERVICE_TYPE))))) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = serviceInfo->SetPort(aPort)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (mRegisterRequest) {
|
||||
mRegisterRequest->Cancel(NS_OK);
|
||||
mRegisterRequest = nullptr;
|
||||
}
|
||||
return mMulticastDNS->RegisterService(serviceInfo, mWrappedListener, getter_AddRefs(mRegisterRequest));
|
||||
}
|
||||
|
||||
// nsIPresentationDeviceProvider
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::GetListener(nsIPresentationDeviceListener** aListener)
|
||||
{
|
||||
if (NS_WARN_IF(!aListener)) {
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresentationDeviceListener> listener = do_QueryReferent(mDeviceListener);
|
||||
listener.forget(aListener);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::SetListener(nsIPresentationDeviceListener* aListener)
|
||||
{
|
||||
mDeviceListener = do_GetWeakReference(aListener);
|
||||
|
||||
nsresult rv;
|
||||
if (mDeviceListener) {
|
||||
if (NS_WARN_IF(NS_FAILED(rv = Init()))) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
if (NS_WARN_IF(NS_FAILED(rv = Uninit()))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::ForceDiscovery()
|
||||
{
|
||||
LOG_I("ForceDiscovery");
|
||||
MOZ_ASSERT(mInitialized);
|
||||
MOZ_ASSERT(mMulticastDNS);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (mDiscoveryRequest) {
|
||||
mDiscoveryRequest->Cancel(NS_OK);
|
||||
mDiscoveryRequest = nullptr;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mMulticastDNS->StartDiscovery(
|
||||
NS_LITERAL_CSTRING(SERVICE_TYPE),
|
||||
mWrappedListener,
|
||||
getter_AddRefs(mDiscoveryRequest))))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIDNSServiceDiscoveryListener
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnDiscoveryStarted(const nsACString& aServiceType)
|
||||
{
|
||||
LOG_I("OnDiscoveryStarted");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnDiscoveryStopped(const nsACString& aServiceType)
|
||||
{
|
||||
LOG_I("OnDiscoveryStopped");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnServiceFound(nsIDNSServiceInfo* aServiceInfo)
|
||||
{
|
||||
if (NS_WARN_IF(!aServiceInfo)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsresult rv ;
|
||||
|
||||
nsAutoCString serviceName;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceName(serviceName)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
LOG_I("OnServiceFound: %s", serviceName.get());
|
||||
|
||||
if (mRegisteredName == serviceName) {
|
||||
LOG_I("ignore self");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPresentationDevice> device;
|
||||
if (NS_SUCCEEDED(mPresentationServer->GetTCPDevice(serviceName,
|
||||
getter_AddRefs(device)))) {
|
||||
LOG_I("device exists");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mMulticastDNS) {
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mMulticastDNS->ResolveService(aServiceInfo, mWrappedListener)))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnServiceLost(nsIDNSServiceInfo* aServiceInfo)
|
||||
{
|
||||
if (NS_WARN_IF(!aServiceInfo)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString serviceName;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceName(serviceName)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
LOG_I("OnServiceLost: %s", serviceName.get());
|
||||
|
||||
nsCOMPtr<nsIPresentationDevice> device;
|
||||
if (NS_FAILED(mPresentationServer->GetTCPDevice(serviceName, getter_AddRefs(device)))) {
|
||||
return NS_OK; // ignore non-existing device;
|
||||
}
|
||||
|
||||
NS_WARN_IF(NS_FAILED(mPresentationServer->RemoveTCPDevice(serviceName)));
|
||||
|
||||
nsCOMPtr<nsIPresentationDeviceListener> listener;
|
||||
GetListener(getter_AddRefs(listener));
|
||||
if (listener) {
|
||||
listener->RemoveDevice(device);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnStartDiscoveryFailed(const nsACString& aServiceType, int32_t aErrorCode)
|
||||
{
|
||||
LOG_E("OnStartDiscoveryFailed: %d", aErrorCode);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnStopDiscoveryFailed(const nsACString& aServiceType, int32_t aErrorCode)
|
||||
{
|
||||
LOG_E("OnStopDiscoveryFailed: %d", aErrorCode);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIDNSRegistrationListener
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnServiceRegistered(nsIDNSServiceInfo* aServiceInfo)
|
||||
{
|
||||
if (NS_WARN_IF(!aServiceInfo)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString name;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceName(name)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
LOG_I("OnServiceRegistered (%s)", name.get());
|
||||
mRegisteredName = name;
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->SetId(name)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnServiceUnregistered(nsIDNSServiceInfo* aServiceInfo)
|
||||
{
|
||||
LOG_I("OnServiceUnregistered");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnRegistrationFailed(nsIDNSServiceInfo* aServiceInfo, int32_t aErrorCode)
|
||||
{
|
||||
LOG_E("OnRegistrationFailed: %d", aErrorCode);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (aErrorCode == nsIDNSRegistrationListener::ERROR_SERVICE_NOT_RUNNING) {
|
||||
uint16_t port = 0;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->GetPort(&port)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv = RegisterService(port)))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnUnregistrationFailed(nsIDNSServiceInfo* aServiceInfo, int32_t aErrorCode)
|
||||
{
|
||||
LOG_E("OnUnregistrationFailed: %d", aErrorCode);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIDNSServiceResolveListener
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnServiceResolved(nsIDNSServiceInfo* aServiceInfo)
|
||||
{
|
||||
if (NS_WARN_IF(!aServiceInfo)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString serviceName;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceName(serviceName)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
LOG_I("OnServiceResolved: %s", serviceName.get());
|
||||
|
||||
nsCOMPtr<nsIPresentationDevice> device;
|
||||
nsCOMPtr<nsIPresentationDeviceListener> listener;
|
||||
GetListener(getter_AddRefs(listener));
|
||||
|
||||
if (NS_SUCCEEDED(mPresentationServer->GetTCPDevice(serviceName,
|
||||
getter_AddRefs(device)))) {
|
||||
NS_WARN_IF(NS_FAILED(mPresentationServer->RemoveTCPDevice(serviceName)));
|
||||
if (listener) {
|
||||
NS_WARN_IF(NS_FAILED(listener->RemoveDevice(device)));
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString host;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetHost(host)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
uint16_t port;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetPort(&port)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsAutoCString serviceType;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = aServiceInfo->GetServiceType(serviceType)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->CreateTCPDevice(serviceName,
|
||||
serviceName,
|
||||
serviceType,
|
||||
host,
|
||||
port,
|
||||
getter_AddRefs(device))))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (listener) {
|
||||
listener->AddDevice(device);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnResolveFailed(nsIDNSServiceInfo* aServiceInfo, int32_t aErrorCode)
|
||||
{
|
||||
LOG_E("OnResolveFailed: %d", aErrorCode);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsITCPPresentationServerListener
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnClose(nsresult aReason)
|
||||
{
|
||||
LOG_I("OnClose: %x", aReason);
|
||||
|
||||
if (mRegisterRequest) {
|
||||
mRegisterRequest->Cancel(aReason);
|
||||
mRegisterRequest = nullptr;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (NS_FAILED(aReason)) {
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->Init(EmptyCString(), 0)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
uint16_t port = 0;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->GetPort(&port)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv = RegisterService(port)))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace presentation
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
64
dom/presentation/provider/MulticastDNSDeviceProvider.h
Normal file
64
dom/presentation/provider/MulticastDNSDeviceProvider.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_presentation_provider_MulticastDNSDeviceProvider_h
|
||||
#define mozilla_dom_presentation_provider_MulticastDNSDeviceProvider_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "nsIDNSServiceDiscovery.h"
|
||||
#include "nsIPresentationDeviceProvider.h"
|
||||
#include "nsITCPPresentationServer.h"
|
||||
#include "nsRefPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsWeakPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace presentation {
|
||||
|
||||
class DNSServiceWrappedListener;
|
||||
class MulticastDNSService;
|
||||
|
||||
class MulticastDNSDeviceProvider final
|
||||
: public nsIPresentationDeviceProvider
|
||||
, public nsIDNSServiceDiscoveryListener
|
||||
, public nsIDNSRegistrationListener
|
||||
, public nsIDNSServiceResolveListener
|
||||
, public nsITCPPresentationServerListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPRESENTATIONDEVICEPROVIDER
|
||||
NS_DECL_NSIDNSSERVICEDISCOVERYLISTENER
|
||||
NS_DECL_NSIDNSREGISTRATIONLISTENER
|
||||
NS_DECL_NSIDNSSERVICERESOLVELISTENER
|
||||
NS_DECL_NSITCPPRESENTATIONSERVERLISTENER
|
||||
|
||||
explicit MulticastDNSDeviceProvider() = default;
|
||||
nsresult Init();
|
||||
nsresult Uninit();
|
||||
|
||||
private:
|
||||
virtual ~MulticastDNSDeviceProvider();
|
||||
nsresult RegisterService(uint32_t aPort);
|
||||
|
||||
bool mInitialized = false;
|
||||
nsWeakPtr mDeviceListener;
|
||||
nsCOMPtr<nsITCPPresentationServer> mPresentationServer;
|
||||
nsCOMPtr<nsIDNSServiceDiscovery> mMulticastDNS;
|
||||
nsRefPtr<DNSServiceWrappedListener> mWrappedListener;
|
||||
|
||||
nsCOMPtr<nsICancelable> mDiscoveryRequest;
|
||||
nsCOMPtr<nsICancelable> mRegisterRequest;
|
||||
|
||||
nsCString mRegisteredName;
|
||||
};
|
||||
|
||||
} // namespace presentation
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_presentation_provider_MulticastDNSDeviceProvider_h
|
@ -0,0 +1,44 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MulticastDNSDeviceProvider.h"
|
||||
#include "mozilla/ModuleUtils.h"
|
||||
|
||||
#define MULTICAST_DNS_PROVIDER_CID \
|
||||
{0x814f947a, 0x52f7, 0x41c9, \
|
||||
{ 0x94, 0xa1, 0x36, 0x84, 0x79, 0x72, 0x84, 0xac }}
|
||||
|
||||
#define MULTICAST_DNS_PROVIDER_CONTRACT_ID "@mozilla.org/presentation-device/multicastdns-provider;1"
|
||||
|
||||
using mozilla::dom::presentation::MulticastDNSDeviceProvider;
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(MulticastDNSDeviceProvider)
|
||||
NS_DEFINE_NAMED_CID(MULTICAST_DNS_PROVIDER_CID);
|
||||
|
||||
static const mozilla::Module::CIDEntry kPresentationDeviceProviderCIDs[] = {
|
||||
{ &kMULTICAST_DNS_PROVIDER_CID, false, nullptr, MulticastDNSDeviceProviderConstructor },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module::ContractIDEntry kPresentationDeviceProviderContracts[] = {
|
||||
{ MULTICAST_DNS_PROVIDER_CONTRACT_ID, &kMULTICAST_DNS_PROVIDER_CID },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module::CategoryEntry kPresentationDeviceProviderCategories[] = {
|
||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 16
|
||||
{ PRESENTATION_DEVICE_PROVIDER_CATEGORY, "MulticastDNSDeviceProvider", MULTICAST_DNS_PROVIDER_CONTRACT_ID},
|
||||
#endif
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module kPresentationDeviceProviderModule = {
|
||||
mozilla::Module::kVersion,
|
||||
kPresentationDeviceProviderCIDs,
|
||||
kPresentationDeviceProviderContracts,
|
||||
kPresentationDeviceProviderCategories
|
||||
};
|
||||
|
||||
NSMODULE_DEFN(PresentationDeviceProviderModule) = &kPresentationDeviceProviderModule;
|
@ -8,3 +8,13 @@ EXTRA_COMPONENTS += [
|
||||
'BuiltinProviders.manifest',
|
||||
'TCPPresentationServer.js'
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'MulticastDNSDeviceProvider.cpp',
|
||||
'PresentationDeviceProviderModule.cpp',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
@ -0,0 +1,255 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, manager: Cm, results: Cr, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const INFO_CONTRACT_ID = "@mozilla.org/toolkit/components/mdnsresponder/dns-info;1";
|
||||
const PROVIDER_CONTRACT_ID = "@mozilla.org/presentation-device/multicastdns-provider;1";
|
||||
const SD_CONTRACT_ID = "@mozilla.org/toolkit/components/mdnsresponder/dns-sd;1";
|
||||
const UUID_CONTRACT_ID = "@mozilla.org/uuid-generator;1";
|
||||
|
||||
let registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
|
||||
function MockFactory(aClass) {
|
||||
this._cls = aClass;
|
||||
}
|
||||
MockFactory.prototype = {
|
||||
createInstance: function(aOuter, aIID) {
|
||||
if (aOuter) {
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
switch(typeof(this._cls)) {
|
||||
case "function":
|
||||
return new this._cls().QueryInterface(aIID);
|
||||
case "object":
|
||||
return this._cls.QueryInterface(aIID);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
lockFactory: function(aLock) {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory])
|
||||
};
|
||||
|
||||
function ContractHook(aContractID, aClass) {
|
||||
this._contractID = aContractID;
|
||||
this.classID = Cc[UUID_CONTRACT_ID].getService(Ci.nsIUUIDGenerator).generateUUID();
|
||||
this._newFactory = new MockFactory(aClass);
|
||||
|
||||
if (!this.hookedMap.has(this._contractID)) {
|
||||
this.hookedMap.set(this._contractID, new Array());
|
||||
}
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
ContractHook.prototype = {
|
||||
hookedMap: new Map(), // remember only the most original factory.
|
||||
|
||||
init: function() {
|
||||
this.reset();
|
||||
|
||||
let oldContract = this.unregister();
|
||||
this.hookedMap.get(this._contractID).push(oldContract);
|
||||
registrar.registerFactory(this.classID, "", this._contractID, this._newFactory);
|
||||
|
||||
do_register_cleanup(() => { this.cleanup.apply(this); });
|
||||
},
|
||||
|
||||
reset: function() {},
|
||||
|
||||
cleanup: function() {
|
||||
this.reset();
|
||||
|
||||
this.unregister();
|
||||
let prevContract = this.hookedMap.get(this._contractID).pop();
|
||||
|
||||
if (prevContract.factory) {
|
||||
registrar.registerFactory(prevContract.classID, "", this._contractID, prevContract.factory);
|
||||
}
|
||||
},
|
||||
|
||||
unregister: function() {
|
||||
var classID, factory;
|
||||
|
||||
try {
|
||||
classID = registrar.contractIDToCID(this._contractID);
|
||||
factory = Cm.getClassObject(Cc[this._contractID], Ci.nsIFactory);
|
||||
} catch (ex) {
|
||||
classID = "";
|
||||
factory = null;
|
||||
}
|
||||
|
||||
if (factory) {
|
||||
registrar.unregisterFactory(classID, factory);
|
||||
}
|
||||
|
||||
return { classID: classID, factory: factory };
|
||||
}
|
||||
};
|
||||
|
||||
function MockDNSServiceInfo() {}
|
||||
MockDNSServiceInfo.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDNSServiceInfo]),
|
||||
|
||||
set host(aHost) {
|
||||
this._host = aHost;
|
||||
},
|
||||
|
||||
get host() {
|
||||
return this._host;
|
||||
},
|
||||
|
||||
set port(aPort) {
|
||||
this._port = aPort;
|
||||
},
|
||||
|
||||
get port() {
|
||||
return this._port;
|
||||
},
|
||||
|
||||
set serviceName(aServiceName) {
|
||||
this._serviceName = aServiceName;
|
||||
},
|
||||
|
||||
get serviceName() {
|
||||
return this._serviceName;
|
||||
},
|
||||
|
||||
set serviceType(aServiceType) {
|
||||
this._serviceType = aServiceType;
|
||||
},
|
||||
|
||||
get serviceType() {
|
||||
return this._serviceType;
|
||||
},
|
||||
|
||||
set domainName(aDomainName) {
|
||||
this._domainName = aDomainName;
|
||||
},
|
||||
|
||||
get domainName() {
|
||||
return this._domainName;
|
||||
},
|
||||
|
||||
set attributes(aAttributes) {
|
||||
this._attributes = aAttributes;
|
||||
},
|
||||
|
||||
get attributes() {
|
||||
return this._attributes;
|
||||
}
|
||||
};
|
||||
|
||||
function TestPresentationDeviceListener() {}
|
||||
TestPresentationDeviceListener.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDeviceListener]),
|
||||
|
||||
addDevice: function(device) {},
|
||||
removeDevice: function(device) {},
|
||||
updateDevice: function(device) {}
|
||||
};
|
||||
|
||||
function createDevice(host, port, serviceName, serviceType, domainName, attributes) {
|
||||
let device = new MockDNSServiceInfo();
|
||||
device.host = host || "";
|
||||
device.port = port || 0;
|
||||
device.serviceName = serviceName || "";
|
||||
device.serviceType = serviceType || "";
|
||||
device.domainName = domainName || "";
|
||||
device.attributes = attributes || null;
|
||||
return device;
|
||||
}
|
||||
|
||||
function registerService() {
|
||||
let mockObj = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDNSServiceDiscovery]),
|
||||
startDiscovery: function(serviceType, listener) {},
|
||||
registerService: function(serviceInfo, listener) {
|
||||
this.serviceRegistered++;
|
||||
return {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICancelable]),
|
||||
cancel: function() {
|
||||
this.serviceUnregistered++;
|
||||
}.bind(this)
|
||||
}
|
||||
},
|
||||
resolveService: function(serviceInfo, listener) {},
|
||||
serviceRegistered: 0,
|
||||
serviceUnregistered: 0
|
||||
};
|
||||
let contractHook = new ContractHook(SD_CONTRACT_ID, mockObj);
|
||||
|
||||
Assert.equal(mockObj.serviceRegistered, 0);
|
||||
let provider = Cc[PROVIDER_CONTRACT_ID].createInstance(Ci.nsIPresentationDeviceProvider);
|
||||
Assert.equal(mockObj.serviceRegistered, 0);
|
||||
provider.listener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDeviceListener, Ci.nsISupportsWeakReference]),
|
||||
addDevice: function(device) {},
|
||||
removeDevice: function(device) {},
|
||||
updateDevice: function(device) {},
|
||||
};
|
||||
Assert.equal(mockObj.serviceRegistered, 1);
|
||||
|
||||
Assert.equal(mockObj.serviceUnregistered, 0);
|
||||
provider.listener = null;
|
||||
Assert.equal(mockObj.serviceUnregistered, 1);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function addDevice() {
|
||||
let mockDevice = createDevice("device.local", 12345, "service.name", "_mozilla_papi._tcp");
|
||||
let mockObj = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDNSServiceDiscovery]),
|
||||
startDiscovery: function(serviceType, listener) {
|
||||
listener.onDiscoveryStarted(serviceType);
|
||||
listener.onServiceFound(createDevice("", 0, mockDevice.serviceName, mockDevice.serviceType));
|
||||
return {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICancelable]),
|
||||
cancel: function() {}
|
||||
}
|
||||
},
|
||||
registerService: function(serviceInfo, listener) {},
|
||||
resolveService: function(serviceInfo, listener) {
|
||||
Assert.equal(serviceInfo.serviceName, mockDevice.serviceName);
|
||||
Assert.equal(serviceInfo.serviceType, mockDevice.serviceType);
|
||||
listener.onServiceResolved(createDevice(mockDevice.host, mockDevice.port, mockDevice.serviceName, mockDevice.serviceType));
|
||||
}
|
||||
};
|
||||
let contractHook = new ContractHook(SD_CONTRACT_ID, mockObj);
|
||||
|
||||
let provider = Cc[PROVIDER_CONTRACT_ID].createInstance(Ci.nsIPresentationDeviceProvider);
|
||||
let listener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDeviceListener, Ci.nsISupportsWeakReference]),
|
||||
addDevice: function(device) { this.devices.push(device); },
|
||||
removeDevice: function(device) {},
|
||||
updateDevice: function(device) {},
|
||||
devices: []
|
||||
};
|
||||
provider.listener = listener;
|
||||
|
||||
Assert.equal(listener.devices.length, 0);
|
||||
provider.forceDiscovery();
|
||||
Assert.equal(listener.devices.length, 1);
|
||||
|
||||
provider.listener = null;
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
let infoHook = new ContractHook(INFO_CONTRACT_ID, MockDNSServiceInfo);
|
||||
|
||||
add_test(registerService);
|
||||
add_test(addDevice);
|
||||
|
||||
run_next_test();
|
||||
}
|
@ -2,5 +2,6 @@
|
||||
head =
|
||||
tail =
|
||||
|
||||
[test_multicast_dns_device_provider.js]
|
||||
[test_presentation_device_manager.js]
|
||||
[test_tcp_control_channel.js]
|
||||
|
@ -368,7 +368,7 @@ nsVolumeService::FindVolumeByMountLockName(const nsAString& aMountLockName)
|
||||
}
|
||||
|
||||
already_AddRefed<nsVolume>
|
||||
nsVolumeService::FindVolumeByName(const nsAString& aName)
|
||||
nsVolumeService::FindVolumeByName(const nsAString& aName, nsVolume::Array::index_type* aIndex)
|
||||
{
|
||||
mArrayMonitor.AssertCurrentThreadOwns();
|
||||
|
||||
@ -377,52 +377,34 @@ nsVolumeService::FindVolumeByName(const nsAString& aName)
|
||||
for (volIndex = 0; volIndex < numVolumes; volIndex++) {
|
||||
nsRefPtr<nsVolume> vol = mVolumeArray[volIndex];
|
||||
if (vol->Name().Equals(aName)) {
|
||||
if (aIndex) {
|
||||
*aIndex = volIndex;
|
||||
}
|
||||
return vol.forget();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//static
|
||||
already_AddRefed<nsVolume>
|
||||
nsVolumeService::CreateOrFindVolumeByName(const nsAString& aName, bool aIsFake /*= false*/)
|
||||
{
|
||||
MonitorAutoLock autoLock(mArrayMonitor);
|
||||
|
||||
nsRefPtr<nsVolume> vol;
|
||||
vol = FindVolumeByName(aName);
|
||||
if (vol) {
|
||||
return vol.forget();
|
||||
}
|
||||
// Volume not found - add a new one
|
||||
vol = new nsVolume(aName);
|
||||
vol->SetIsFake(aIsFake);
|
||||
mVolumeArray.AppendElement(vol);
|
||||
return vol.forget();
|
||||
}
|
||||
|
||||
void
|
||||
nsVolumeService::UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers)
|
||||
nsVolumeService::UpdateVolume(nsVolume* aVolume, bool aNotifyObservers)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsString volName;
|
||||
aVolume->GetName(volName);
|
||||
bool aIsFake;
|
||||
aVolume->GetIsFake(&aIsFake);
|
||||
nsRefPtr<nsVolume> vol = CreateOrFindVolumeByName(volName, aIsFake);
|
||||
if (vol->Equals(aVolume)) {
|
||||
// Nothing has really changed. Don't bother telling anybody.
|
||||
return;
|
||||
{
|
||||
MonitorAutoLock autoLock(mArrayMonitor);
|
||||
nsVolume::Array::index_type volIndex;
|
||||
nsRefPtr<nsVolume> vol = FindVolumeByName(aVolume->Name(), &volIndex);
|
||||
if (!vol) {
|
||||
mVolumeArray.AppendElement(aVolume);
|
||||
} else if (vol->Equals(aVolume) || (!vol->IsFake() && aVolume->IsFake())) {
|
||||
// Ignore if nothing changed or if a fake tries to override a real volume.
|
||||
return;
|
||||
} else {
|
||||
mVolumeArray.ReplaceElementAt(volIndex, aVolume);
|
||||
}
|
||||
}
|
||||
|
||||
if (!vol->IsFake() && aIsFake) {
|
||||
// Prevent an incoming fake volume from overriding an existing real volume.
|
||||
return;
|
||||
}
|
||||
|
||||
vol->Set(aVolume);
|
||||
|
||||
if (!aNotifyObservers) {
|
||||
return;
|
||||
}
|
||||
@ -431,8 +413,8 @@ nsVolumeService::UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers)
|
||||
if (!obs) {
|
||||
return;
|
||||
}
|
||||
NS_ConvertUTF8toUTF16 stateStr(vol->StateStr());
|
||||
obs->NotifyObservers(vol, NS_VOLUME_STATE_CHANGED, stateStr.get());
|
||||
NS_ConvertUTF8toUTF16 stateStr(aVolume->StateStr());
|
||||
obs->NotifyObservers(aVolume, NS_VOLUME_STATE_CHANGED, stateStr.get());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -471,9 +453,7 @@ nsVolumeService::SetFakeVolumeState(const nsAString& name, int32_t state)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// UpdateVolume expects the volume passed in to NOT be the
|
||||
// same pointer as what CreateOrFindVolumeByName would return,
|
||||
// which is why we allocate a temporary volume here.
|
||||
// Clone the existing volume so we can replace it
|
||||
nsRefPtr<nsVolume> volume = new nsVolume(name);
|
||||
volume->Set(vol);
|
||||
volume->SetState(state);
|
||||
@ -502,15 +482,15 @@ nsVolumeService::RemoveFakeVolume(const nsAString& name)
|
||||
void
|
||||
nsVolumeService::RemoveVolumeByName(const nsAString& aName)
|
||||
{
|
||||
nsRefPtr<nsVolume> vol;
|
||||
{
|
||||
MonitorAutoLock autoLock(mArrayMonitor);
|
||||
vol = FindVolumeByName(aName);
|
||||
nsVolume::Array::index_type volIndex;
|
||||
nsRefPtr<nsVolume> vol = FindVolumeByName(aName, &volIndex);
|
||||
if (!vol) {
|
||||
return;
|
||||
}
|
||||
mVolumeArray.RemoveElementAt(volIndex);
|
||||
}
|
||||
if (!vol) {
|
||||
return;
|
||||
}
|
||||
mVolumeArray.RemoveElement(vol);
|
||||
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
nsCOMPtr<nsIObserverService> obs = GetObserverService();
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
void DumpNoLock(const char* aLabel);
|
||||
|
||||
// To use this function, you have to create a new volume and pass it in.
|
||||
void UpdateVolume(nsIVolume* aVolume, bool aNotifyObservers = true);
|
||||
void UpdateVolume(nsVolume* aVolume, bool aNotifyObservers = true);
|
||||
void UpdateVolumeIOThread(const Volume* aVolume);
|
||||
|
||||
void RecvVolumesFromParent(const nsTArray<dom::VolumeInfo>& aVolumes);
|
||||
@ -61,8 +61,9 @@ private:
|
||||
void CheckMountLock(const nsAString& aMountLockName,
|
||||
const nsAString& aMountLockState);
|
||||
already_AddRefed<nsVolume> FindVolumeByMountLockName(const nsAString& aMountLockName);
|
||||
already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName);
|
||||
already_AddRefed<nsVolume> CreateOrFindVolumeByName(const nsAString& aName, bool aIsFake = false);
|
||||
|
||||
already_AddRefed<nsVolume> FindVolumeByName(const nsAString& aName,
|
||||
nsVolume::Array::index_type* aIndex = nullptr);
|
||||
|
||||
Monitor mArrayMonitor;
|
||||
nsVolume::Array mVolumeArray;
|
||||
|
110
dom/telephony/gonk/TelephonyUtils.jsm
Normal file
110
dom/telephony/gonk/TelephonyUtils.jsm
Normal file
@ -0,0 +1,110 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["TelephonyUtils"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
|
||||
/* global TelephonyService */
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"TelephonyService",
|
||||
"@mozilla.org/telephony/telephonyservice;1",
|
||||
"nsITelephonyService");
|
||||
|
||||
function getCurrentCalls(aFilter) {
|
||||
if (aFilter === undefined) {
|
||||
aFilter = call => true;
|
||||
}
|
||||
|
||||
let calls = [];
|
||||
|
||||
// nsITelephonyService.enumerateCalls is synchronous.
|
||||
TelephonyService.enumerateCalls({
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]),
|
||||
enumerateCallStateComplete: function() {},
|
||||
enumerateCallState: function(call) {
|
||||
if (aFilter(call)) {
|
||||
calls.push(call);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return calls;
|
||||
}
|
||||
|
||||
this.TelephonyUtils = {
|
||||
/**
|
||||
* Check whether there are any calls.
|
||||
*
|
||||
* @param aClientId [optional] If provided, only check on aClientId
|
||||
* @return boolean
|
||||
*/
|
||||
hasAnyCalls: function(aClientId) {
|
||||
let calls = getCurrentCalls(call => {
|
||||
if (aClientId !== undefined && call.clientId !== aClientId) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return calls.length !== 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check whether there are any connected calls.
|
||||
*
|
||||
* @param aClientId [optional] If provided, only check on aClientId
|
||||
* @return boolean
|
||||
*/
|
||||
hasConnectedCalls: function(aClientId) {
|
||||
let calls = getCurrentCalls(call => {
|
||||
if (aClientId !== undefined && call.clientId !== aClientId) {
|
||||
return false;
|
||||
}
|
||||
return call.callState === Ci.nsITelephonyService.CALL_STATE_CONNECTED;
|
||||
});
|
||||
|
||||
return calls.length !== 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Return a promise which will be resolved when there are no calls.
|
||||
*
|
||||
* @param aClientId [optional] only check on aClientId if provided
|
||||
* @return Promise
|
||||
*/
|
||||
waitForNoCalls: function(aClientId) {
|
||||
if (!this.hasAnyCalls(aClientId)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
let self = this;
|
||||
return new Promise(resolve => {
|
||||
let listener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]),
|
||||
|
||||
enumerateCallStateComplete: function() {},
|
||||
enumerateCallState: function() {},
|
||||
callStateChanged: function() {
|
||||
if (!self.hasAnyCalls(aClientId)) {
|
||||
TelephonyService.unregisterListener(this);
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
conferenceCallStateChanged: function() {},
|
||||
supplementaryServiceNotification: function() {},
|
||||
notifyError: function() {},
|
||||
notifyCdmaCallWaiting: function() {},
|
||||
notifyConferenceError: function() {}
|
||||
};
|
||||
|
||||
TelephonyService.registerListener(listener);
|
||||
});
|
||||
}
|
||||
};
|
@ -72,7 +72,8 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
|
||||
'gonk/TelephonyService.manifest',
|
||||
]
|
||||
EXTRA_JS_MODULES += [
|
||||
'gonk/DialNumberUtils.jsm'
|
||||
'gonk/DialNumberUtils.jsm',
|
||||
'gonk/TelephonyUtils.jsm',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
@ -1107,12 +1107,19 @@ let emulator = (function() {
|
||||
|
||||
let promises = [];
|
||||
|
||||
let promise = gWaitForEvent(connection, "radiostatechange", event => {
|
||||
promises.push(gWaitForEvent(connection, "radiostatechange", event => {
|
||||
let state = connection.radioState;
|
||||
log("current radioState: " + state);
|
||||
return state == desiredRadioState;
|
||||
});
|
||||
promises.push(promise);
|
||||
}));
|
||||
|
||||
// Wait for icc status to finish updating. Please see bug 1169504 for the
|
||||
// reason why we need this.
|
||||
promises.push(gWaitForEvent(connection, "iccchange", event => {
|
||||
let iccId = connection.iccId;
|
||||
log("current iccId: " + iccId);
|
||||
return !!iccId === enabled;
|
||||
}));
|
||||
|
||||
promises.push(connection.setRadioEnabled(enabled));
|
||||
|
||||
|
@ -54,4 +54,5 @@ qemu = true
|
||||
[test_redundant_operations.js]
|
||||
[test_swap_held_and_active.js]
|
||||
[test_system_message_telephony_call_ended.js]
|
||||
[test_TelephonyUtils.js]
|
||||
[test_temporary_clir.js]
|
||||
|
91
dom/telephony/test/marionette/test_TelephonyUtils.js
Normal file
91
dom/telephony/test/marionette/test_TelephonyUtils.js
Normal file
@ -0,0 +1,91 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_CONTEXT = "chrome";
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this,
|
||||
"TelephonyService",
|
||||
"@mozilla.org/telephony/telephonyservice;1",
|
||||
"nsIGonkTelephonyService");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "TelephonyUtils",
|
||||
"resource://gre/modules/TelephonyUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "RIL", function () {
|
||||
let ns = {};
|
||||
Cu.import("resource://gre/modules/ril_consts.js", ns);
|
||||
return ns;
|
||||
});
|
||||
|
||||
const number = "0912345678";
|
||||
|
||||
function dial() {
|
||||
return new Promise(resolve => {
|
||||
TelephonyService.dial(0, number, false, {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyDialCallback]),
|
||||
notifyDialCallSuccess: function() { resolve(); }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function waitForStateChanged() {
|
||||
return new Promise(resolve => {
|
||||
let listener = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyListener]),
|
||||
|
||||
callStateChanged: function(length, allInfo) {
|
||||
resolve(allInfo);
|
||||
TelephonyService.unregisterListener(listener);
|
||||
},
|
||||
conferenceCallStateChanged: function() {},
|
||||
supplementaryServiceNotification: function() {},
|
||||
notifyError: function() {},
|
||||
notifyCdmaCallWaiting: function() {},
|
||||
notifyConferenceError: function() {}
|
||||
};
|
||||
|
||||
TelephonyService.registerListener(listener);
|
||||
});
|
||||
}
|
||||
|
||||
function test_noCall() {
|
||||
log("== test_noCall ==");
|
||||
is(TelephonyUtils.hasAnyCalls(), false, "hasAnyCalls");
|
||||
is(TelephonyUtils.hasConnectedCalls(), false, "hasConnectedCalls");
|
||||
return TelephonyUtils.waitForNoCalls();
|
||||
}
|
||||
|
||||
function test_oneCall() {
|
||||
log("== test_oneCall ==");
|
||||
|
||||
return dial()
|
||||
.then(() => {
|
||||
is(TelephonyUtils.hasAnyCalls(), true, "hasAnyCalls");
|
||||
is(TelephonyUtils.hasConnectedCalls(), false, "hasConnectedCalls");
|
||||
})
|
||||
.then(() => {
|
||||
let p = waitForStateChanged();
|
||||
emulator.runCmd("gsm accept " + number);
|
||||
return p;
|
||||
})
|
||||
.then(allInfo => {
|
||||
is(allInfo[0].callState, Ci.nsITelephonyService.CALL_STATE_CONNECTED);
|
||||
is(TelephonyUtils.hasAnyCalls(), true, "hasAnyCalls");
|
||||
is(TelephonyUtils.hasConnectedCalls(), true, "hasConnectedCalls");
|
||||
})
|
||||
.then(() => {
|
||||
let p = TelephonyUtils.waitForNoCalls();
|
||||
emulator.runCmd("gsm cancel " + number);
|
||||
return p;
|
||||
});
|
||||
}
|
||||
|
||||
test_noCall()
|
||||
.then(test_oneCall)
|
||||
.catch(error => ok(false, "Promise reject: " + error))
|
||||
.then(finish);
|
@ -416,7 +416,7 @@ var WifiManager = (function() {
|
||||
let currentNetwork = Object.create(null);
|
||||
currentNetwork.netId = manager.connectionInfo.id;
|
||||
|
||||
manager.getNetworkConfiguration(currentNetwork, function (){
|
||||
manager.getNetworkConfiguration(currentNetwork, function () {
|
||||
curNetworkKey = getNetworkKey(currentNetwork);
|
||||
|
||||
// Add additional information to static ip configuration
|
||||
@ -435,15 +435,19 @@ var WifiManager = (function() {
|
||||
// If the ssid of current connection is the same as configured ssid
|
||||
// It means we need update current connection to use static IP address.
|
||||
if (setNetworkKey == curNetworkKey) {
|
||||
// Use configureInterface directly doesn't work, the network iterface
|
||||
// Use configureInterface directly doesn't work, the network interface
|
||||
// and routing table is changed but still cannot connect to network
|
||||
// so the workaround here is disable interface the enable again to
|
||||
// trigger network reconnect with static ip.
|
||||
gNetworkService.disableInterface(manager.ifname, function (ok) {
|
||||
gNetworkService.enableInterface(manager.ifname, function (ok) {
|
||||
callback(ok);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
callback(true);
|
||||
});
|
||||
}
|
||||
|
||||
@ -3494,7 +3498,7 @@ WifiWorker.prototype = {
|
||||
},
|
||||
|
||||
setStaticIpMode: function(msg) {
|
||||
const message = "WifiManager:setStaticMode:Return";
|
||||
const message = "WifiManager:setStaticIpMode:Return";
|
||||
let self = this;
|
||||
let network = msg.data.network;
|
||||
let info = msg.data.info;
|
||||
|
@ -433,6 +433,23 @@ let gTestSuite = (function() {
|
||||
.then(event => event.target.result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given network to static ip mode.
|
||||
*
|
||||
* Resolve when we set static ip mode successfully; reject when any error
|
||||
* occurs.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
* Reject params: (none)
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function setStaticIpMode(aNetwork, aConfig) {
|
||||
let request = wifiManager.setStaticIpMode(aNetwork, aConfig);
|
||||
return wrapDomRequestAsPromise(request)
|
||||
.then(event => event.target.result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue a request to scan all wifi available networks.
|
||||
*
|
||||
@ -1025,6 +1042,117 @@ let gTestSuite = (function() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute 'netcfg' shell and parse the result.
|
||||
*
|
||||
* Resolve when the executing is successful and reject otherwise.
|
||||
*
|
||||
* Fulfill params: Command result object, each key of which is the interface
|
||||
* name and value is { ip(string), prefix(string) }.
|
||||
* Reject params: String that indicates the reason of rejection.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function exeAndParseNetcfg() {
|
||||
return runEmulatorShellSafe(['netcfg'])
|
||||
.then(function (aLines) {
|
||||
// Sample output:
|
||||
//
|
||||
// lo UP 127.0.0.1/8 0x00000049 00:00:00:00:00:00
|
||||
// eth0 UP 10.0.2.15/24 0x00001043 52:54:00:12:34:56
|
||||
// rmnet1 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:58
|
||||
// rmnet2 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:59
|
||||
// rmnet3 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:5a
|
||||
// wlan0 UP 192.168.1.1/24 0x00001043 52:54:00:12:34:5b
|
||||
// sit0 DOWN 0.0.0.0/0 0x00000080 00:00:00:00:00:00
|
||||
// rmnet0 UP 10.0.2.100/24 0x00001043 52:54:00:12:34:57
|
||||
//
|
||||
let netcfgResult = {};
|
||||
aLines.forEach(function (aLine) {
|
||||
let tokens = aLine.split(/\s+/);
|
||||
if (tokens.length < 5) {
|
||||
return;
|
||||
}
|
||||
let ifname = tokens[0];
|
||||
let [ip, prefix] = tokens[2].split('/');
|
||||
netcfgResult[ifname] = { ip: ip, prefix: prefix };
|
||||
});
|
||||
log("netcfg result:" + JSON.stringify(netcfgResult));
|
||||
|
||||
return netcfgResult;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute 'ip route' and parse the result.
|
||||
*
|
||||
* Resolve when the executing is successful and reject otherwise.
|
||||
*
|
||||
* Fulfill params: Command result object, each key of which is the interface
|
||||
* name and value is { src(string), gateway(string),
|
||||
* default(boolean) }.
|
||||
* Reject params: String that indicates the reason of rejection.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function exeAndParseIpRoute() {
|
||||
return runEmulatorShellSafe(['ip', 'route'])
|
||||
.then(function (aLines) {
|
||||
// Sample output:
|
||||
//
|
||||
// 10.0.2.4 via 10.0.2.2 dev rmnet0
|
||||
// 10.0.2.3 via 10.0.2.2 dev rmnet0
|
||||
// 192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.1
|
||||
// 10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
|
||||
// 10.0.2.0/24 dev rmnet0 proto kernel scope link src 10.0.2.100
|
||||
// default via 10.0.2.2 dev rmnet0
|
||||
// default via 10.0.2.2 dev eth0 metric 2
|
||||
//
|
||||
|
||||
let ipRouteResult = {};
|
||||
|
||||
// Parse source ip for each interface.
|
||||
aLines.forEach(function (aLine) {
|
||||
let tokens = aLine.trim().split(/\s+/);
|
||||
let srcIndex = tokens.indexOf('src');
|
||||
if (srcIndex < 0 || srcIndex + 1 >= tokens.length) {
|
||||
return;
|
||||
}
|
||||
let ifname = tokens[2];
|
||||
let src = tokens[srcIndex + 1];
|
||||
ipRouteResult[ifname] = { src: src, default: false, gateway: null };
|
||||
});
|
||||
|
||||
// Parse default interfaces.
|
||||
aLines.forEach(function (aLine) {
|
||||
let tokens = aLine.split(/\s+/);
|
||||
if (tokens.length < 2) {
|
||||
return;
|
||||
}
|
||||
if ('default' === tokens[0]) {
|
||||
let ifnameIndex = tokens.indexOf('dev');
|
||||
if (ifnameIndex < 0 || ifnameIndex + 1 >= tokens.length) {
|
||||
return;
|
||||
}
|
||||
let ifname = tokens[ifnameIndex + 1];
|
||||
if (!ipRouteResult[ifname]) {
|
||||
return;
|
||||
}
|
||||
ipRouteResult[ifname].default = true;
|
||||
let gwIndex = tokens.indexOf('via');
|
||||
if (gwIndex < 0 || gwIndex + 1 >= tokens.length) {
|
||||
return;
|
||||
}
|
||||
ipRouteResult[ifname].gateway = tokens[gwIndex + 1];
|
||||
return;
|
||||
}
|
||||
});
|
||||
log("ip route result:" + JSON.stringify(ipRouteResult));
|
||||
|
||||
return ipRouteResult;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify everything about routing when the wifi tethering is either on or off.
|
||||
*
|
||||
@ -1044,87 +1172,8 @@ let gTestSuite = (function() {
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function verifyTetheringRouting(aEnabled) {
|
||||
let netcfgResult = {};
|
||||
let ipRouteResult = {};
|
||||
|
||||
// Execute 'netcfg' and parse to |netcfgResult|, each key of which is the
|
||||
// interface name and value is { ip(string) }.
|
||||
function exeAndParseNetcfg() {
|
||||
return runEmulatorShellSafe(['netcfg'])
|
||||
.then(function (aLines) {
|
||||
// Sample output:
|
||||
//
|
||||
// lo UP 127.0.0.1/8 0x00000049 00:00:00:00:00:00
|
||||
// eth0 UP 10.0.2.15/24 0x00001043 52:54:00:12:34:56
|
||||
// rmnet1 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:58
|
||||
// rmnet2 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:59
|
||||
// rmnet3 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:5a
|
||||
// wlan0 UP 192.168.1.1/24 0x00001043 52:54:00:12:34:5b
|
||||
// sit0 DOWN 0.0.0.0/0 0x00000080 00:00:00:00:00:00
|
||||
// rmnet0 UP 10.0.2.100/24 0x00001043 52:54:00:12:34:57
|
||||
//
|
||||
aLines.forEach(function (aLine) {
|
||||
let tokens = aLine.split(/\s+/);
|
||||
if (tokens.length < 5) {
|
||||
return;
|
||||
}
|
||||
let ifname = tokens[0];
|
||||
let ip = (tokens[2].split('/'))[0];
|
||||
netcfgResult[ifname] = { ip: ip };
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Execute 'ip route' and parse to |ipRouteResult|, each key of which is the
|
||||
// interface name and value is { src(string), default(boolean) }.
|
||||
function exeAndParseIpRoute() {
|
||||
return runEmulatorShellSafe(['ip', 'route'])
|
||||
.then(function (aLines) {
|
||||
// Sample output:
|
||||
//
|
||||
// 10.0.2.4 via 10.0.2.2 dev rmnet0
|
||||
// 10.0.2.3 via 10.0.2.2 dev rmnet0
|
||||
// 192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.1
|
||||
// 10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
|
||||
// 10.0.2.0/24 dev rmnet0 proto kernel scope link src 10.0.2.100
|
||||
// default via 10.0.2.2 dev rmnet0
|
||||
// default via 10.0.2.2 dev eth0 metric 2
|
||||
//
|
||||
|
||||
// Parse source ip for each interface.
|
||||
aLines.forEach(function (aLine) {
|
||||
let tokens = aLine.trim().split(/\s+/);
|
||||
let srcIndex = tokens.indexOf('src');
|
||||
if (srcIndex < 0 || srcIndex + 1 >= tokens.length) {
|
||||
return;
|
||||
}
|
||||
let ifname = tokens[2];
|
||||
let src = tokens[srcIndex + 1];
|
||||
ipRouteResult[ifname] = { src: src, default: false };
|
||||
});
|
||||
|
||||
// Parse default interfaces.
|
||||
aLines.forEach(function (aLine) {
|
||||
let tokens = aLine.split(/\s+/);
|
||||
if (tokens.length < 2) {
|
||||
return;
|
||||
}
|
||||
if ('default' === tokens[0]) {
|
||||
let ifnameIndex = tokens.indexOf('dev');
|
||||
if (ifnameIndex < 0 || ifnameIndex + 1 >= tokens.length) {
|
||||
return;
|
||||
}
|
||||
let ifname = tokens[ifnameIndex + 1];
|
||||
if (ipRouteResult[ifname]) {
|
||||
ipRouteResult[ifname].default = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
let netcfgResult;
|
||||
let ipRouteResult;
|
||||
|
||||
// Find MASQUERADE in POSTROUTING section. 'MASQUERADE' should be found
|
||||
// when tethering is enabled. 'MASQUERADE' shouldn't be found when tethering
|
||||
@ -1158,9 +1207,6 @@ let gTestSuite = (function() {
|
||||
}
|
||||
|
||||
function verifyDefaultRouteAndIp(aExpectedWifiTetheringIp) {
|
||||
log(JSON.stringify(ipRouteResult));
|
||||
log(JSON.stringify(netcfgResult));
|
||||
|
||||
if (aEnabled) {
|
||||
isOrThrow(ipRouteResult['rmnet0'].src, netcfgResult['rmnet0'].ip, 'rmnet0.ip');
|
||||
isOrThrow(ipRouteResult['rmnet0'].default, true, 'rmnet0.default');
|
||||
@ -1173,7 +1219,9 @@ let gTestSuite = (function() {
|
||||
|
||||
return verifyIptables()
|
||||
.then(exeAndParseNetcfg)
|
||||
.then((aResult) => { netcfgResult = aResult; })
|
||||
.then(exeAndParseIpRoute)
|
||||
.then((aResult) => { ipRouteResult = aResult; })
|
||||
.then(() => getSettings(SETTINGS_TETHERING_WIFI_IP))
|
||||
.then(ip => verifyDefaultRouteAndIp(ip));
|
||||
}
|
||||
@ -1244,6 +1292,7 @@ let gTestSuite = (function() {
|
||||
suite.getFirstIndexBySsid = getFirstIndexBySsid;
|
||||
suite.testAssociate = testAssociate;
|
||||
suite.getKnownNetworks = getKnownNetworks;
|
||||
suite.setStaticIpMode = setStaticIpMode;
|
||||
suite.requestWifiScan = requestWifiScan;
|
||||
suite.waitForConnected = waitForConnected;
|
||||
suite.forgetNetwork = forgetNetwork;
|
||||
@ -1254,6 +1303,8 @@ let gTestSuite = (function() {
|
||||
suite.getImportedCerts = getImportedCerts;
|
||||
suite.deleteCert = deleteCert;
|
||||
suite.writeFile = writeFile;
|
||||
suite.exeAndParseNetcfg = exeAndParseNetcfg;
|
||||
suite.exeAndParseIpRoute = exeAndParseIpRoute;
|
||||
|
||||
/**
|
||||
* Common test routine.
|
||||
|
@ -8,6 +8,7 @@ qemu = true
|
||||
[test_wifi_associate.js]
|
||||
[test_wifi_associate_wo_connect.js]
|
||||
[test_wifi_auto_connect.js]
|
||||
[test_wifi_static_ip.js]
|
||||
[test_wifi_tethering_wifi_disabled.js]
|
||||
[test_wifi_tethering_wifi_inactive.js]
|
||||
[test_wifi_tethering_wifi_active.js]
|
||||
|
41
dom/wifi/test/marionette/test_wifi_static_ip.js
Normal file
41
dom/wifi/test/marionette/test_wifi_static_ip.js
Normal file
@ -0,0 +1,41 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
const STATIC_IP_CONFIG = {
|
||||
enabled: true,
|
||||
ipaddr: "192.168.111.222",
|
||||
proxy: "",
|
||||
maskLength: 24,
|
||||
gateway: "192.168.111.1",
|
||||
dns1: "8.8.8.8",
|
||||
dns2: "8.8.4.4",
|
||||
};
|
||||
|
||||
function testAssociateWithStaticIp(aNetwork, aStaticIpConfig) {
|
||||
return gTestSuite.setStaticIpMode(aNetwork, aStaticIpConfig)
|
||||
.then(() => gTestSuite.testAssociate(aNetwork))
|
||||
// Check ip address and prefix.
|
||||
.then(() => gTestSuite.exeAndParseNetcfg())
|
||||
.then((aResult) => {
|
||||
is(aResult["wlan0"].ip, aStaticIpConfig.ipaddr, "Check ip address");
|
||||
is(aResult["wlan0"].prefix, aStaticIpConfig.maskLength, "Check prefix");
|
||||
})
|
||||
// Check routing.
|
||||
.then(() => gTestSuite.exeAndParseIpRoute())
|
||||
.then((aResult) => {
|
||||
is(aResult["wlan0"].src, aStaticIpConfig.ipaddr, "Check ip address");
|
||||
is(aResult["wlan0"].default, true, "Check default route");
|
||||
is(aResult["wlan0"].gateway, aStaticIpConfig.gateway, "Check gateway");
|
||||
});
|
||||
}
|
||||
|
||||
// Start test.
|
||||
gTestSuite.doTest(function() {
|
||||
return gTestSuite.ensureWifiEnabled(true)
|
||||
.then(() => gTestSuite.requestWifiScan())
|
||||
.then((aNetworks) => testAssociateWithStaticIp(aNetworks[0],
|
||||
STATIC_IP_CONFIG));
|
||||
});
|
@ -12,8 +12,6 @@
|
||||
#include <unistd.h>
|
||||
#include "mozilla/ipc/BluetoothDaemonConnectionConsumer.h"
|
||||
#include "mozilla/ipc/DataSocket.h"
|
||||
#include "mozilla/ipc/UnixSocketConnector.h"
|
||||
#include "mozilla/ipc/UnixSocketWatcher.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
@ -201,35 +199,16 @@ BluetoothDaemonPDUConsumer::~BluetoothDaemonPDUConsumer()
|
||||
// BluetoothDaemonConnectionIO
|
||||
//
|
||||
|
||||
class BluetoothDaemonConnectionIO final
|
||||
: public UnixSocketWatcher
|
||||
, public ConnectionOrientedSocketIO
|
||||
class BluetoothDaemonConnectionIO final : public ConnectionOrientedSocketIO
|
||||
{
|
||||
public:
|
||||
BluetoothDaemonConnectionIO(nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
int aFd, ConnectionStatus aConnectionStatus,
|
||||
UnixSocketConnector* aConnector,
|
||||
BluetoothDaemonConnection* aConnection,
|
||||
BluetoothDaemonPDUConsumer* aConsumer);
|
||||
|
||||
// Task callback methods
|
||||
//
|
||||
|
||||
void Send(UnixSocketIOBuffer* aBuffer);
|
||||
|
||||
void OnSocketCanReceiveWithoutBlocking() override;
|
||||
void OnSocketCanSendWithoutBlocking() override;
|
||||
|
||||
void OnConnected() override;
|
||||
void OnError(const char* aFunction, int aErrno) override;
|
||||
|
||||
// Methods for |ConnectionOrientedSocketIO|
|
||||
//
|
||||
|
||||
nsresult Accept(int aFd,
|
||||
const struct sockaddr* aAddress,
|
||||
socklen_t aAddressLength) override;
|
||||
|
||||
// Methods for |DataSocketIO|
|
||||
//
|
||||
|
||||
@ -260,10 +239,14 @@ BluetoothDaemonConnectionIO::BluetoothDaemonConnectionIO(
|
||||
MessageLoop* aIOLoop,
|
||||
int aFd,
|
||||
ConnectionStatus aConnectionStatus,
|
||||
UnixSocketConnector* aConnector,
|
||||
BluetoothDaemonConnection* aConnection,
|
||||
BluetoothDaemonPDUConsumer* aConsumer)
|
||||
: UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus)
|
||||
, ConnectionOrientedSocketIO(aConsumerThread)
|
||||
: ConnectionOrientedSocketIO(aConsumerThread,
|
||||
aIOLoop,
|
||||
aFd,
|
||||
aConnectionStatus,
|
||||
aConnector)
|
||||
, mConnection(aConnection)
|
||||
, mConsumer(aConsumer)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
@ -272,98 +255,6 @@ BluetoothDaemonConnectionIO::BluetoothDaemonConnectionIO(
|
||||
MOZ_ASSERT(mConsumer);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonConnectionIO::Send(UnixSocketIOBuffer* aBuffer)
|
||||
{
|
||||
MOZ_ASSERT(aBuffer);
|
||||
|
||||
EnqueueData(aBuffer);
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonConnectionIO::OnSocketCanReceiveWithoutBlocking()
|
||||
{
|
||||
ssize_t res = ReceiveData(GetFd());
|
||||
if (res < 0) {
|
||||
/* I/O error */
|
||||
RemoveWatchers(READ_WATCHER|WRITE_WATCHER);
|
||||
} else if (!res) {
|
||||
/* EOF or peer shutdown */
|
||||
RemoveWatchers(READ_WATCHER);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonConnectionIO::OnSocketCanSendWithoutBlocking()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
|
||||
MOZ_ASSERT(!IsShutdownOnIOThread());
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(SendPendingData(GetFd())))) {
|
||||
RemoveWatchers(WRITE_WATCHER);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonConnectionIO::OnConnected()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
|
||||
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonConnectionIO::OnError(const char* aFunction, int aErrno)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
|
||||
UnixFdWatcher::OnError(aFunction, aErrno);
|
||||
|
||||
// Clean up watchers, status, fd
|
||||
Close();
|
||||
|
||||
// Tell the consumer thread we've errored
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
// |ConnectionOrientedSocketIO|
|
||||
|
||||
nsresult
|
||||
BluetoothDaemonConnectionIO::Accept(int aFd,
|
||||
const struct sockaddr* aAddress,
|
||||
socklen_t aAddressLength)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING);
|
||||
|
||||
// File-descriptor setup
|
||||
|
||||
if (TEMP_FAILURE_RETRY(fcntl(aFd, F_SETFL, O_NONBLOCK)) < 0) {
|
||||
OnError("fcntl", errno);
|
||||
ScopedClose cleanupFd(aFd);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
SetSocket(aFd, SOCKET_IS_CONNECTED);
|
||||
|
||||
// Signal success
|
||||
OnConnected();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// |DataSocketIO|
|
||||
|
||||
nsresult
|
||||
@ -464,16 +355,11 @@ BluetoothDaemonConnection::PrepareAccept(UnixSocketConnector* aConnector,
|
||||
{
|
||||
MOZ_ASSERT(!mIO);
|
||||
|
||||
// |BluetoothDaemonConnection| now owns the connector, but doesn't
|
||||
// actually use it. So the connector is stored in an auto pointer
|
||||
// to be deleted at the end of the method.
|
||||
nsAutoPtr<UnixSocketConnector> connector(aConnector);
|
||||
|
||||
SetConnectionStatus(SOCKET_CONNECTING);
|
||||
|
||||
mIO = new BluetoothDaemonConnectionIO(
|
||||
aConsumerThread, aIOLoop, -1, UnixSocketWatcher::SOCKET_IS_CONNECTING,
|
||||
this, mPDUConsumer);
|
||||
aConnector, this, mPDUConsumer);
|
||||
aIO = mIO;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -5,6 +5,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ConnectionOrientedSocket.h"
|
||||
#include "UnixSocketConnector.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
@ -14,13 +15,172 @@ namespace ipc {
|
||||
//
|
||||
|
||||
ConnectionOrientedSocketIO::ConnectionOrientedSocketIO(
|
||||
nsIThread* aConsumerThread)
|
||||
nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
int aFd,
|
||||
ConnectionStatus aConnectionStatus,
|
||||
UnixSocketConnector* aConnector)
|
||||
: DataSocketIO(aConsumerThread)
|
||||
{ }
|
||||
, UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus)
|
||||
, mConnector(aConnector)
|
||||
, mPeerAddressLength(0)
|
||||
{
|
||||
MOZ_ASSERT(mConnector);
|
||||
}
|
||||
|
||||
ConnectionOrientedSocketIO::ConnectionOrientedSocketIO(
|
||||
nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
UnixSocketConnector* aConnector)
|
||||
: DataSocketIO(aConsumerThread)
|
||||
, UnixSocketWatcher(aIOLoop)
|
||||
, mConnector(aConnector)
|
||||
, mPeerAddressLength(0)
|
||||
{
|
||||
MOZ_ASSERT(mConnector);
|
||||
}
|
||||
|
||||
ConnectionOrientedSocketIO::~ConnectionOrientedSocketIO()
|
||||
{ }
|
||||
|
||||
nsresult
|
||||
ConnectionOrientedSocketIO::Accept(int aFd,
|
||||
const struct sockaddr* aPeerAddress,
|
||||
socklen_t aPeerAddressLength)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING);
|
||||
|
||||
SetSocket(aFd, SOCKET_IS_CONNECTED);
|
||||
|
||||
// Address setup
|
||||
mPeerAddressLength = aPeerAddressLength;
|
||||
memcpy(&mPeerAddress, aPeerAddress, mPeerAddressLength);
|
||||
|
||||
// Signal success and start data transfer
|
||||
OnConnected();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ConnectionOrientedSocketIO::Connect()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(!IsOpen());
|
||||
|
||||
struct sockaddr* peerAddress =
|
||||
reinterpret_cast<struct sockaddr*>(&mPeerAddress);
|
||||
mPeerAddressLength = sizeof(mPeerAddress);
|
||||
|
||||
int fd;
|
||||
nsresult rv = mConnector->CreateStreamSocket(peerAddress,
|
||||
&mPeerAddressLength,
|
||||
fd);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Tell the consumer thread we've errored
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
SetFd(fd);
|
||||
|
||||
// calls OnConnected() on success, or OnError() otherwise
|
||||
rv = UnixSocketWatcher::Connect(peerAddress, mPeerAddressLength);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionOrientedSocketIO::Send(UnixSocketIOBuffer* aBuffer)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
|
||||
EnqueueData(aBuffer);
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
|
||||
// |UnixSocketWatcher|
|
||||
|
||||
void
|
||||
ConnectionOrientedSocketIO::OnSocketCanReceiveWithoutBlocking()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984
|
||||
|
||||
ssize_t res = ReceiveData(GetFd());
|
||||
if (res < 0) {
|
||||
/* I/O error */
|
||||
RemoveWatchers(READ_WATCHER|WRITE_WATCHER);
|
||||
} else if (!res) {
|
||||
/* EOF or peer shutdown */
|
||||
RemoveWatchers(READ_WATCHER);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionOrientedSocketIO::OnSocketCanSendWithoutBlocking()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984
|
||||
MOZ_ASSERT(!IsShutdownOnIOThread());
|
||||
|
||||
nsresult rv = SendPendingData(GetFd());
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasPendingData()) {
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionOrientedSocketIO::OnConnected()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
|
||||
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionOrientedSocketIO::OnListening()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
|
||||
NS_NOTREACHED("Invalid call to |ConnectionOrientedSocketIO::OnListening|");
|
||||
}
|
||||
|
||||
void
|
||||
ConnectionOrientedSocketIO::OnError(const char* aFunction, int aErrno)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
|
||||
UnixFdWatcher::OnError(aFunction, aErrno);
|
||||
|
||||
// Clean up watchers, status, fd
|
||||
Close();
|
||||
|
||||
// Tell the consumer thread we've errored
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
//
|
||||
// ConnectionOrientedSocket
|
||||
//
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include "DataSocket.h"
|
||||
#include "mozilla/ipc/UnixSocketWatcher.h"
|
||||
|
||||
class MessageLoop;
|
||||
|
||||
@ -23,15 +24,72 @@ class UnixSocketConnector;
|
||||
* |ListenSocket| uses these classes to handle accepted sockets.
|
||||
*/
|
||||
|
||||
class ConnectionOrientedSocketIO : public DataSocketIO
|
||||
class ConnectionOrientedSocketIO
|
||||
: public DataSocketIO
|
||||
, public UnixSocketWatcher
|
||||
{
|
||||
public:
|
||||
ConnectionOrientedSocketIO(nsIThread* aConsumerThread);
|
||||
virtual ~ConnectionOrientedSocketIO();
|
||||
|
||||
virtual nsresult Accept(int aFd,
|
||||
const struct sockaddr* aAddress,
|
||||
socklen_t aAddressLength) = 0;
|
||||
nsresult Accept(int aFd,
|
||||
const struct sockaddr* aAddress,
|
||||
socklen_t aAddressLength);
|
||||
|
||||
nsresult Connect();
|
||||
|
||||
void Send(UnixSocketIOBuffer* aBuffer);
|
||||
|
||||
// Methods for |UnixSocketWatcher|
|
||||
//
|
||||
|
||||
void OnSocketCanReceiveWithoutBlocking() final;
|
||||
void OnSocketCanSendWithoutBlocking() final;
|
||||
|
||||
void OnListening() final;
|
||||
void OnConnected() final;
|
||||
void OnError(const char* aFunction, int aErrno) final;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Constructs an instance of |ConnectionOrientedSocketIO|
|
||||
*
|
||||
* @param aConsumerThread The socket's consumer thread.
|
||||
* @param aIOLoop The socket's I/O loop.
|
||||
* @param aFd The socket file descriptor.
|
||||
* @param aConnectionStatus The connection status for |aFd|.
|
||||
* @param aConnector Connector object for socket-type-specific methods.
|
||||
*/
|
||||
ConnectionOrientedSocketIO(nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
int aFd, ConnectionStatus aConnectionStatus,
|
||||
UnixSocketConnector* aConnector);
|
||||
|
||||
/**
|
||||
* Constructs an instance of |ConnectionOrientedSocketIO|
|
||||
*
|
||||
* @param aConsumerThread The socket's consumer thread.
|
||||
* @param aIOLoop The socket's I/O loop.
|
||||
* @param aConnector Connector object for socket-type-specific methods.
|
||||
*/
|
||||
ConnectionOrientedSocketIO(nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
UnixSocketConnector* aConnector);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Connector object used to create the connection we are currently using.
|
||||
*/
|
||||
nsAutoPtr<UnixSocketConnector> mConnector;
|
||||
|
||||
/**
|
||||
* Number of valid bytes in |mPeerAddress|.
|
||||
*/
|
||||
socklen_t mPeerAddressLength;
|
||||
|
||||
/**
|
||||
* Address of the socket's current peer.
|
||||
*/
|
||||
struct sockaddr_storage mPeerAddress;
|
||||
};
|
||||
|
||||
class ConnectionOrientedSocket : public DataSocket
|
||||
|
@ -20,9 +20,7 @@ namespace ipc {
|
||||
// StreamSocketIO
|
||||
//
|
||||
|
||||
class StreamSocketIO final
|
||||
: public UnixSocketWatcher
|
||||
, public ConnectionOrientedSocketIO
|
||||
class StreamSocketIO final : public ConnectionOrientedSocketIO
|
||||
{
|
||||
public:
|
||||
class ConnectTask;
|
||||
@ -50,32 +48,6 @@ public:
|
||||
void ClearDelayedConnectTask();
|
||||
void CancelDelayedConnectTask();
|
||||
|
||||
// Task callback methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Connect to a socket
|
||||
*/
|
||||
void Connect();
|
||||
|
||||
void Send(UnixSocketIOBuffer* aBuffer);
|
||||
|
||||
// I/O callback methods
|
||||
//
|
||||
|
||||
void OnConnected() override;
|
||||
void OnError(const char* aFunction, int aErrno) override;
|
||||
void OnListening() override;
|
||||
void OnSocketCanReceiveWithoutBlocking() override;
|
||||
void OnSocketCanSendWithoutBlocking() override;
|
||||
|
||||
// Methods for |ConnectionOrientedSocketIO|
|
||||
//
|
||||
|
||||
nsresult Accept(int aFd,
|
||||
const struct sockaddr* aAddress,
|
||||
socklen_t aAddressLength) override;
|
||||
|
||||
// Methods for |DataSocket|
|
||||
//
|
||||
|
||||
@ -95,8 +67,6 @@ public:
|
||||
void ShutdownOnIOThread() override;
|
||||
|
||||
private:
|
||||
void FireSocketError();
|
||||
|
||||
/**
|
||||
* Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
|
||||
* directly from consumer thread. All non-consumer-thread accesses should
|
||||
@ -104,26 +74,11 @@ private:
|
||||
*/
|
||||
RefPtr<StreamSocket> mStreamSocket;
|
||||
|
||||
/**
|
||||
* Connector object used to create the connection we are currently using.
|
||||
*/
|
||||
nsAutoPtr<UnixSocketConnector> mConnector;
|
||||
|
||||
/**
|
||||
* If true, do not requeue whatever task we're running
|
||||
*/
|
||||
bool mShuttingDownOnIOThread;
|
||||
|
||||
/**
|
||||
* Number of valid bytes in |mAddress|
|
||||
*/
|
||||
socklen_t mAddressLength;
|
||||
|
||||
/**
|
||||
* Address structure of the socket currently in use
|
||||
*/
|
||||
struct sockaddr_storage mAddress;
|
||||
|
||||
/**
|
||||
* Task member for delayed connect task. Should only be access on consumer
|
||||
* thread.
|
||||
@ -140,16 +95,12 @@ StreamSocketIO::StreamSocketIO(nsIThread* aConsumerThread,
|
||||
MessageLoop* aIOLoop,
|
||||
StreamSocket* aStreamSocket,
|
||||
UnixSocketConnector* aConnector)
|
||||
: UnixSocketWatcher(aIOLoop)
|
||||
, ConnectionOrientedSocketIO(aConsumerThread)
|
||||
: ConnectionOrientedSocketIO(aConsumerThread, aIOLoop, aConnector)
|
||||
, mStreamSocket(aStreamSocket)
|
||||
, mConnector(aConnector)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
, mAddressLength(0)
|
||||
, mDelayedConnectTask(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(mStreamSocket);
|
||||
MOZ_ASSERT(mConnector);
|
||||
}
|
||||
|
||||
StreamSocketIO::StreamSocketIO(nsIThread* aConsumerThread,
|
||||
@ -157,16 +108,16 @@ StreamSocketIO::StreamSocketIO(nsIThread* aConsumerThread,
|
||||
int aFd, ConnectionStatus aConnectionStatus,
|
||||
StreamSocket* aStreamSocket,
|
||||
UnixSocketConnector* aConnector)
|
||||
: UnixSocketWatcher(aIOLoop, aFd, aConnectionStatus)
|
||||
, ConnectionOrientedSocketIO(aConsumerThread)
|
||||
: ConnectionOrientedSocketIO(aConsumerThread,
|
||||
aIOLoop,
|
||||
aFd,
|
||||
aConnectionStatus,
|
||||
aConnector)
|
||||
, mStreamSocket(aStreamSocket)
|
||||
, mConnector(aConnector)
|
||||
, mShuttingDownOnIOThread(false)
|
||||
, mAddressLength(0)
|
||||
, mDelayedConnectTask(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(mStreamSocket);
|
||||
MOZ_ASSERT(mConnector);
|
||||
}
|
||||
|
||||
StreamSocketIO::~StreamSocketIO()
|
||||
@ -216,145 +167,6 @@ StreamSocketIO::CancelDelayedConnectTask()
|
||||
ClearDelayedConnectTask();
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::Connect()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(mConnector);
|
||||
|
||||
MOZ_ASSERT(!IsOpen());
|
||||
|
||||
struct sockaddr* address = reinterpret_cast<struct sockaddr*>(&mAddress);
|
||||
mAddressLength = sizeof(mAddress);
|
||||
|
||||
int fd;
|
||||
nsresult rv = mConnector->CreateStreamSocket(address, &mAddressLength, fd);
|
||||
if (NS_FAILED(rv)) {
|
||||
FireSocketError();
|
||||
return;
|
||||
}
|
||||
SetFd(fd);
|
||||
|
||||
// calls OnConnected() on success, or OnError() otherwise
|
||||
rv = UnixSocketWatcher::Connect(address, mAddressLength);
|
||||
NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::Send(UnixSocketIOBuffer* aData)
|
||||
{
|
||||
EnqueueData(aData);
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::OnConnected()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED);
|
||||
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::OnListening()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
|
||||
NS_NOTREACHED("Invalid call to |StreamSocketIO::OnListening|");
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::OnError(const char* aFunction, int aErrno)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
|
||||
UnixFdWatcher::OnError(aFunction, aErrno);
|
||||
FireSocketError();
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::OnSocketCanReceiveWithoutBlocking()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984
|
||||
|
||||
ssize_t res = ReceiveData(GetFd());
|
||||
if (res < 0) {
|
||||
/* I/O error */
|
||||
RemoveWatchers(READ_WATCHER|WRITE_WATCHER);
|
||||
} else if (!res) {
|
||||
/* EOF or peer shutdown */
|
||||
RemoveWatchers(READ_WATCHER);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::OnSocketCanSendWithoutBlocking()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTED); // see bug 990984
|
||||
|
||||
nsresult rv = SendPendingData(GetFd());
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasPendingData()) {
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
StreamSocketIO::FireSocketError()
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
|
||||
// Clean up watchers, statuses, fds
|
||||
Close();
|
||||
|
||||
// Tell the consumer thread we've errored
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_ERROR),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
// |ConnectionOrientedSocketIO|
|
||||
|
||||
nsresult
|
||||
StreamSocketIO::Accept(int aFd,
|
||||
const struct sockaddr* aAddress,
|
||||
socklen_t aAddressLength)
|
||||
{
|
||||
MOZ_ASSERT(MessageLoopForIO::current() == GetIOLoop());
|
||||
MOZ_ASSERT(GetConnectionStatus() == SOCKET_IS_CONNECTING);
|
||||
|
||||
SetSocket(aFd, SOCKET_IS_CONNECTED);
|
||||
|
||||
// Address setup
|
||||
mAddressLength = aAddressLength;
|
||||
memcpy(&mAddress, aAddress, mAddressLength);
|
||||
|
||||
// Signal success
|
||||
GetConsumerThread()->Dispatch(
|
||||
new SocketIOEventRunnable(this, SocketIOEventRunnable::CONNECT_SUCCESS),
|
||||
NS_DISPATCH_NORMAL);
|
||||
|
||||
AddWatchers(READ_WATCHER, true);
|
||||
if (HasPendingData()) {
|
||||
AddWatchers(WRITE_WATCHER, false);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// |DataSocketIO|
|
||||
|
||||
nsresult
|
||||
|
@ -213,6 +213,7 @@
|
||||
@BINPATH@/components/necko_file.xpt
|
||||
@BINPATH@/components/necko_ftp.xpt
|
||||
@BINPATH@/components/necko_http.xpt
|
||||
@BINPATH@/components/necko_mdns.xpt
|
||||
@BINPATH@/components/necko_res.xpt
|
||||
@BINPATH@/components/necko_socket.xpt
|
||||
@BINPATH@/components/necko_strconv.xpt
|
||||
|
665
netwerk/dns/mdns/libmdns/MDNSResponderOperator.cpp
Normal file
665
netwerk/dns/mdns/libmdns/MDNSResponderOperator.cpp
Normal file
@ -0,0 +1,665 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MDNSResponderOperator.h"
|
||||
#include "MDNSResponderReply.h"
|
||||
#include "mozilla/Endian.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsDNSServiceInfo.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsIProperty.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIVariant.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsSocketTransportService2.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOMCID.h"
|
||||
#include "private/pprio.h"
|
||||
|
||||
#include "nsASocketHandler.h"
|
||||
|
||||
inline PRLogModuleInfo*
|
||||
GetOperatorLog()
|
||||
{
|
||||
static PRLogModuleInfo* log = PR_NewLogModule("MDNSResponderOperator");
|
||||
return log;
|
||||
}
|
||||
#undef LOG_I
|
||||
#define LOG_I(...) PR_LOG(GetOperatorLog(), PR_LOG_NOTICE, (__VA_ARGS__))
|
||||
#undef LOG_E
|
||||
#define LOG_E(...) PR_LOG(GetOperatorLog(), PR_LOG_ERROR, (__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class MDNSResponderOperator::ServiceWatcher final
|
||||
: public nsASocketHandler
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
// nsASocketHandler methods
|
||||
virtual void OnSocketReady(PRFileDesc* fd, int16_t outFlags) override
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
MOZ_ASSERT(fd == mFD);
|
||||
|
||||
if (outFlags & (PR_POLL_ERR | PR_POLL_HUP | PR_POLL_NVAL)) {
|
||||
LOG_E("error polling on listening socket (%p)", fd);
|
||||
mCondition = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!(outFlags & PR_POLL_READ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DNSServiceProcessResult(mService);
|
||||
}
|
||||
|
||||
virtual void OnSocketDetached(PRFileDesc *fd) override
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
MOZ_ASSERT(fd == mFD);
|
||||
|
||||
if (!mFD) {
|
||||
return;
|
||||
}
|
||||
|
||||
PR_Close(mFD);
|
||||
mFD = nullptr;
|
||||
}
|
||||
|
||||
virtual void IsLocal(bool *aIsLocal) override { *aIsLocal = true; }
|
||||
|
||||
virtual void KeepWhenOffline(bool *aKeepWhenOffline) override
|
||||
{
|
||||
*aKeepWhenOffline = true;
|
||||
}
|
||||
|
||||
virtual uint64_t ByteCountSent() override { return 0; }
|
||||
virtual uint64_t ByteCountReceived() override { return 0; }
|
||||
|
||||
explicit ServiceWatcher(DNSServiceRef aService)
|
||||
: mSts(nullptr)
|
||||
, mService(aService)
|
||||
, mFD(nullptr)
|
||||
, mAttached(false)
|
||||
{
|
||||
if (!gSocketTransportService)
|
||||
{
|
||||
nsCOMPtr<nsISocketTransportService> sts =
|
||||
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult Init()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() != gSocketThread);
|
||||
|
||||
if (!mService) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!gSocketTransportService) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mSts = gSocketTransportService;
|
||||
|
||||
int osfd = DNSServiceRefSockFD(mService);
|
||||
if (osfd == -1) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mFD = PR_ImportFile(osfd);
|
||||
return PostEvent(&ServiceWatcher::OnMsgAttach);
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() != gSocketThread);
|
||||
|
||||
if (mService) {
|
||||
DNSServiceRefDeallocate(mService);
|
||||
mService = nullptr;
|
||||
}
|
||||
|
||||
if (!gSocketTransportService) {
|
||||
return;
|
||||
}
|
||||
|
||||
PostEvent(&ServiceWatcher::OnMsgClose);
|
||||
}
|
||||
|
||||
private:
|
||||
~ServiceWatcher() = default;
|
||||
|
||||
nsresult PostEvent(void(ServiceWatcher::*func)(void))
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> ev = NS_NewRunnableMethod(this, func);
|
||||
return gSocketTransportService->Dispatch(ev, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void OnMsgClose()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
if (NS_FAILED(mCondition)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// tear down socket. this signals the STS to detach our socket handler.
|
||||
mCondition = NS_BINDING_ABORTED;
|
||||
|
||||
// if we are attached, then socket transport service will call our
|
||||
// OnSocketDetached method automatically. Otherwise, we have to call it
|
||||
// (and thus close the socket) manually.
|
||||
if (!mAttached) {
|
||||
OnSocketDetached(mFD);
|
||||
}
|
||||
}
|
||||
|
||||
void OnMsgAttach()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
if (NS_FAILED(mCondition)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mCondition = TryAttach();
|
||||
|
||||
// if we hit an error while trying to attach then bail...
|
||||
if (NS_FAILED(mCondition)) {
|
||||
NS_ASSERTION(!mAttached, "should not be attached already");
|
||||
OnSocketDetached(mFD);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
nsresult TryAttach()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (!gSocketTransportService) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//
|
||||
// find out if it is going to be ok to attach another socket to the STS.
|
||||
// if not then we have to wait for the STS to tell us that it is ok.
|
||||
// the notification is asynchronous, which means that when we could be
|
||||
// in a race to call AttachSocket once notified. for this reason, when
|
||||
// we get notified, we just re-enter this function. as a result, we are
|
||||
// sure to ask again before calling AttachSocket. in this way we deal
|
||||
// with the race condition. though it isn't the most elegant solution,
|
||||
// it is far simpler than trying to build a system that would guarantee
|
||||
// FIFO ordering (which wouldn't even be that valuable IMO). see bug
|
||||
// 194402 for more info.
|
||||
//
|
||||
if (!gSocketTransportService->CanAttachSocket()) {
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(this, &ServiceWatcher::OnMsgAttach);
|
||||
|
||||
nsresult rv = gSocketTransportService->NotifyWhenCanAttachSocket(event);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ok, we can now attach our socket to the STS for polling
|
||||
//
|
||||
rv = gSocketTransportService->AttachSocket(mFD, this);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mAttached = true;
|
||||
|
||||
//
|
||||
// now, configure our poll flags for listening...
|
||||
//
|
||||
mPollFlags = (PR_POLL_READ | PR_POLL_EXCEPT);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsSocketTransportService> mSts;
|
||||
DNSServiceRef mService;
|
||||
PRFileDesc* mFD;
|
||||
bool mAttached;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(MDNSResponderOperator::ServiceWatcher, nsISupports)
|
||||
|
||||
MDNSResponderOperator::MDNSResponderOperator()
|
||||
: mService(nullptr)
|
||||
, mWatcher(nullptr)
|
||||
, mThread(NS_GetCurrentThread())
|
||||
, mIsCancelled(false)
|
||||
{
|
||||
}
|
||||
|
||||
MDNSResponderOperator::~MDNSResponderOperator()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
nsresult
|
||||
MDNSResponderOperator::Start()
|
||||
{
|
||||
if (mIsCancelled) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (IsServing()) {
|
||||
Stop();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MDNSResponderOperator::Stop()
|
||||
{
|
||||
mThread = nullptr;
|
||||
return ResetService(nullptr);
|
||||
}
|
||||
|
||||
nsresult
|
||||
MDNSResponderOperator::ResetService(DNSServiceRef aService)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (aService != mService) {
|
||||
if (mWatcher) {
|
||||
mWatcher->Close();
|
||||
mWatcher = nullptr;
|
||||
}
|
||||
|
||||
if (aService) {
|
||||
nsRefPtr<ServiceWatcher> watcher = new ServiceWatcher(aService);
|
||||
if (NS_WARN_IF(NS_FAILED(watcher->Init()))) {
|
||||
return rv;
|
||||
}
|
||||
mWatcher = watcher;
|
||||
}
|
||||
|
||||
mService = aService;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
BrowseOperator::BrowseOperator(const nsACString& aServiceType,
|
||||
nsIDNSServiceDiscoveryListener* aListener)
|
||||
: MDNSResponderOperator()
|
||||
, mServiceType(aServiceType)
|
||||
, mListener(aListener)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
BrowseOperator::Start()
|
||||
{
|
||||
nsresult rv;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = MDNSResponderOperator::Start()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
DNSServiceRef service = nullptr;
|
||||
DNSServiceErrorType err = DNSServiceBrowse(&service,
|
||||
0,
|
||||
kDNSServiceInterfaceIndexAny,
|
||||
mServiceType.get(),
|
||||
nullptr,
|
||||
&BrowseReplyRunnable::Reply,
|
||||
this);
|
||||
NS_WARN_IF(kDNSServiceErr_NoError != err);
|
||||
|
||||
if (mListener) {
|
||||
if (kDNSServiceErr_NoError == err) {
|
||||
mListener->OnDiscoveryStarted(mServiceType);
|
||||
} else {
|
||||
mListener->OnStartDiscoveryFailed(mServiceType, err);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(kDNSServiceErr_NoError != err)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return ResetService(service);
|
||||
}
|
||||
|
||||
nsresult
|
||||
BrowseOperator::Stop()
|
||||
{
|
||||
bool isServing = IsServing();
|
||||
nsresult rv = MDNSResponderOperator::Stop();
|
||||
|
||||
if (isServing && mListener) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mListener->OnDiscoveryStopped(mServiceType);
|
||||
} else {
|
||||
mListener->OnStopDiscoveryFailed(mServiceType,
|
||||
static_cast<uint32_t>(rv));
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
BrowseOperator::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aServiceName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aReplyDomain)
|
||||
{
|
||||
MOZ_ASSERT(GetThread() == NS_GetCurrentThread());
|
||||
|
||||
if (NS_WARN_IF(kDNSServiceErr_NoError != aErrorCode)) {
|
||||
LOG_E("BrowseOperator::Reply (%d)", aErrorCode);
|
||||
if (mListener) {
|
||||
mListener->OnStartDiscoveryFailed(mServiceType, aErrorCode);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mListener) { return; }
|
||||
nsCOMPtr<nsIDNSServiceInfo> info = new nsDNSServiceInfo();
|
||||
|
||||
if (NS_WARN_IF(!info)) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetServiceName(aServiceName)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetServiceType(aRegType)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetDomainName(aReplyDomain)))) { return; }
|
||||
|
||||
if (aFlags & kDNSServiceFlagsAdd) {
|
||||
mListener->OnServiceFound(info);
|
||||
} else {
|
||||
mListener->OnServiceLost(info);
|
||||
}
|
||||
}
|
||||
|
||||
RegisterOperator::RegisterOperator(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSRegistrationListener* aListener)
|
||||
: MDNSResponderOperator()
|
||||
, mServiceInfo(aServiceInfo)
|
||||
, mListener(aListener)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
RegisterOperator::Start()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = MDNSResponderOperator::Start();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
uint16_t port;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mServiceInfo->GetPort(&port)))) {
|
||||
return rv;
|
||||
}
|
||||
nsAutoCString type;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mServiceInfo->GetServiceType(type)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
TXTRecordRef txtRecord;
|
||||
char buf[TXT_BUFFER_SIZE] = { 0 };
|
||||
TXTRecordCreate(&txtRecord, TXT_BUFFER_SIZE, buf);
|
||||
|
||||
nsCOMPtr<nsIPropertyBag2> attributes;
|
||||
if (NS_FAILED(rv = mServiceInfo->GetAttributes(getter_AddRefs(attributes)))) {
|
||||
LOG_I("register: no attributes");
|
||||
} else {
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
if (NS_WARN_IF(NS_FAILED(rv =
|
||||
attributes->GetEnumerator(getter_AddRefs(enumerator))))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool hasMoreElements;
|
||||
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements)) &&
|
||||
hasMoreElements) {
|
||||
nsCOMPtr<nsISupports> element;
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(element))));
|
||||
nsCOMPtr<nsIProperty> property = do_QueryInterface(element);
|
||||
MOZ_ASSERT(property);
|
||||
|
||||
nsAutoString name;
|
||||
nsCOMPtr<nsIVariant> value;
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(property->GetName(name)));
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(property->GetValue(getter_AddRefs(value))));
|
||||
|
||||
nsAutoCString str;
|
||||
if (NS_WARN_IF(NS_FAILED(value->GetAsACString(str)))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TXTRecordSetValue(&txtRecord,
|
||||
/* it's safe because key name is ASCII only. */
|
||||
NS_LossyConvertUTF16toASCII(name).get(),
|
||||
str.Length(),
|
||||
str.get());
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString host;
|
||||
nsAutoCString name;
|
||||
nsAutoCString domain;
|
||||
|
||||
DNSServiceRef service = nullptr;
|
||||
DNSServiceErrorType err =
|
||||
DNSServiceRegister(&service,
|
||||
0,
|
||||
0,
|
||||
NS_SUCCEEDED(mServiceInfo->GetServiceName(name)) ?
|
||||
name.get() : nullptr,
|
||||
type.get(),
|
||||
NS_SUCCEEDED(mServiceInfo->GetDomainName(domain)) ?
|
||||
domain.get() : nullptr,
|
||||
NS_SUCCEEDED(mServiceInfo->GetHost(host)) ?
|
||||
host.get() : nullptr,
|
||||
NativeEndian::swapToNetworkOrder(port),
|
||||
TXTRecordGetLength(&txtRecord),
|
||||
TXTRecordGetBytesPtr(&txtRecord),
|
||||
&RegisterReplyRunnable::Reply,
|
||||
this);
|
||||
NS_WARN_IF(kDNSServiceErr_NoError != err);
|
||||
|
||||
TXTRecordDeallocate(&txtRecord);
|
||||
|
||||
if (NS_WARN_IF(kDNSServiceErr_NoError != err)) {
|
||||
if (mListener) {
|
||||
mListener->OnRegistrationFailed(mServiceInfo, err);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return ResetService(service);
|
||||
}
|
||||
|
||||
nsresult
|
||||
RegisterOperator::Stop()
|
||||
{
|
||||
bool isServing = IsServing();
|
||||
nsresult rv = MDNSResponderOperator::Stop();
|
||||
|
||||
if (isServing && mListener) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mListener->OnServiceUnregistered(mServiceInfo);
|
||||
} else {
|
||||
mListener->OnUnregistrationFailed(mServiceInfo,
|
||||
static_cast<uint32_t>(rv));
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
RegisterOperator::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aDomain)
|
||||
{
|
||||
MOZ_ASSERT(GetThread() == NS_GetCurrentThread());
|
||||
|
||||
if (kDNSServiceErr_NoError != aErrorCode) {
|
||||
LOG_E("RegisterOperator::Reply (%d)", aErrorCode);
|
||||
}
|
||||
|
||||
if (!mListener) { return; }
|
||||
nsCOMPtr<nsIDNSServiceInfo> info = new nsDNSServiceInfo(mServiceInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetServiceName(aName)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetServiceType(aRegType)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetDomainName(aDomain)))) { return; }
|
||||
|
||||
if (kDNSServiceErr_NoError == aErrorCode) {
|
||||
mListener->OnServiceRegistered(info);
|
||||
} else {
|
||||
mListener->OnRegistrationFailed(info, aErrorCode);
|
||||
}
|
||||
}
|
||||
|
||||
ResolveOperator::ResolveOperator(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSServiceResolveListener* aListener)
|
||||
: MDNSResponderOperator()
|
||||
, mServiceInfo(aServiceInfo)
|
||||
, mListener(aListener)
|
||||
, mDeleteProtector()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
ResolveOperator::Start()
|
||||
{
|
||||
nsresult rv;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = MDNSResponderOperator::Start()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsAutoCString name;
|
||||
mServiceInfo->GetServiceName(name);
|
||||
nsAutoCString type;
|
||||
mServiceInfo->GetServiceType(type);
|
||||
nsAutoCString domain;
|
||||
mServiceInfo->GetDomainName(domain);
|
||||
|
||||
LOG_I("Resolve: (%s), (%s), (%s)", name.get(), type.get(), domain.get());
|
||||
|
||||
DNSServiceRef service = nullptr;
|
||||
DNSServiceErrorType err =
|
||||
DNSServiceResolve(&service,
|
||||
0,
|
||||
kDNSServiceInterfaceIndexAny,
|
||||
name.get(),
|
||||
type.get(),
|
||||
domain.get(),
|
||||
(DNSServiceResolveReply)&ResolveReplyRunnable::Reply,
|
||||
this);
|
||||
|
||||
if (NS_WARN_IF(kDNSServiceErr_NoError != err)) {
|
||||
if (mListener) {
|
||||
mListener->OnResolveFailed(mServiceInfo, err);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mDeleteProtector = this;
|
||||
return ResetService(service);
|
||||
}
|
||||
|
||||
nsresult
|
||||
ResolveOperator::Stop()
|
||||
{
|
||||
nsresult rv = MDNSResponderOperator::Stop();
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
ResolveOperator::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aFullName,
|
||||
const nsACString& aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord)
|
||||
{
|
||||
MOZ_ASSERT(GetThread() == NS_GetCurrentThread());
|
||||
|
||||
mDeleteProtector = nullptr;
|
||||
|
||||
if (NS_WARN_IF(kDNSServiceErr_NoError != aErrorCode)) {
|
||||
LOG_E("ResolveOperator::Reply (%d)", aErrorCode);
|
||||
return;
|
||||
}
|
||||
|
||||
// Resolve TXT record
|
||||
int count = TXTRecordGetCount(aTxtLen, aTxtRecord);
|
||||
LOG_I("resolve: txt count = %d, len = %d", count, aTxtLen);
|
||||
nsCOMPtr<nsIWritablePropertyBag2> attributes = nullptr;
|
||||
if (count) {
|
||||
attributes = new nsHashPropertyBag();
|
||||
if (NS_WARN_IF(!attributes)) { return; }
|
||||
for (int i = 0; i < count; ++i) {
|
||||
char key[TXT_BUFFER_SIZE] = { '\0' };
|
||||
uint8_t vSize = 0;
|
||||
const void* value = nullptr;
|
||||
if (kDNSServiceErr_NoError !=
|
||||
TXTRecordGetItemAtIndex(aTxtLen,
|
||||
aTxtRecord,
|
||||
i,
|
||||
TXT_BUFFER_SIZE,
|
||||
key,
|
||||
&vSize,
|
||||
&value)) {
|
||||
break;
|
||||
}
|
||||
|
||||
nsAutoCString str(reinterpret_cast<const char*>(value), vSize);
|
||||
LOG_I("resolve TXT: (%d) %s=%s", vSize, key, str.get());
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(attributes->SetPropertyAsACString(
|
||||
/* it's safe to convert because key name is ASCII only. */
|
||||
NS_ConvertASCIItoUTF16(key),
|
||||
str)))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mListener) { return; }
|
||||
nsCOMPtr<nsIDNSServiceInfo> info = new nsDNSServiceInfo(mServiceInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetHost(aHostTarget)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetPort(aPort)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetAttributes(attributes)))) { return; }
|
||||
|
||||
if (kDNSServiceErr_NoError == aErrorCode) {
|
||||
mListener->OnServiceResolved(info);
|
||||
} else {
|
||||
mListener->OnResolveFailed(info, aErrorCode);
|
||||
}
|
||||
|
||||
NS_WARN_IF(NS_FAILED(Stop()));
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
139
netwerk/dns/mdns/libmdns/MDNSResponderOperator.h
Normal file
139
netwerk/dns/mdns/libmdns/MDNSResponderOperator.h
Normal file
@ -0,0 +1,139 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_netwerk_dns_mdns_libmdns_MDNSResponderOperator_h
|
||||
#define mozilla_netwerk_dns_mdns_libmdns_MDNSResponderOperator_h
|
||||
|
||||
#include "dns_sd.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDNSServiceDiscovery.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsRefPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class MDNSResponderOperator
|
||||
{
|
||||
public:
|
||||
MDNSResponderOperator();
|
||||
|
||||
virtual nsresult Start();
|
||||
virtual nsresult Stop();
|
||||
void Cancel() { mIsCancelled = true; }
|
||||
nsIThread* GetThread() const { return mThread; }
|
||||
|
||||
protected:
|
||||
virtual ~MDNSResponderOperator();
|
||||
|
||||
bool IsServing() const { return mService; }
|
||||
nsresult ResetService(DNSServiceRef aService);
|
||||
|
||||
private:
|
||||
class ServiceWatcher;
|
||||
|
||||
DNSServiceRef mService;
|
||||
nsRefPtr<ServiceWatcher> mWatcher;
|
||||
nsCOMPtr<nsIThread> mThread; // remember caller thread for callback
|
||||
Atomic<bool> mIsCancelled;
|
||||
};
|
||||
|
||||
class BrowseOperator final : private MDNSResponderOperator
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BrowseOperator)
|
||||
|
||||
BrowseOperator(const nsACString& aServiceType,
|
||||
nsIDNSServiceDiscoveryListener* aListener);
|
||||
|
||||
nsresult Start() override;
|
||||
nsresult Stop() override;
|
||||
using MDNSResponderOperator::Cancel;
|
||||
using MDNSResponderOperator::GetThread;
|
||||
|
||||
void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aServiceName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aReplyDomain);
|
||||
|
||||
private:
|
||||
~BrowseOperator() = default;
|
||||
|
||||
nsCString mServiceType;
|
||||
nsCOMPtr<nsIDNSServiceDiscoveryListener> mListener;
|
||||
};
|
||||
|
||||
class RegisterOperator final : private MDNSResponderOperator
|
||||
{
|
||||
enum { TXT_BUFFER_SIZE = 256 };
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RegisterOperator)
|
||||
|
||||
RegisterOperator(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSRegistrationListener* aListener);
|
||||
|
||||
nsresult Start() override;
|
||||
nsresult Stop() override;
|
||||
using MDNSResponderOperator::Cancel;
|
||||
using MDNSResponderOperator::GetThread;
|
||||
|
||||
void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aDomain);
|
||||
|
||||
private:
|
||||
~RegisterOperator() = default;
|
||||
|
||||
nsCOMPtr<nsIDNSServiceInfo> mServiceInfo;
|
||||
nsCOMPtr<nsIDNSRegistrationListener> mListener;
|
||||
};
|
||||
|
||||
class ResolveOperator final : private MDNSResponderOperator
|
||||
{
|
||||
enum { TXT_BUFFER_SIZE = 256 };
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ResolveOperator)
|
||||
|
||||
ResolveOperator(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSServiceResolveListener* aListener);
|
||||
|
||||
nsresult Start() override;
|
||||
nsresult Stop() override;
|
||||
using MDNSResponderOperator::GetThread;
|
||||
|
||||
void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aFullName,
|
||||
const nsACString& aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord);
|
||||
|
||||
private:
|
||||
~ResolveOperator() = default;
|
||||
|
||||
nsCOMPtr<nsIDNSServiceInfo> mServiceInfo;
|
||||
nsCOMPtr<nsIDNSServiceResolveListener> mListener;
|
||||
|
||||
// hold self until callback is made.
|
||||
nsRefPtr<ResolveOperator> mDeleteProtector;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_netwerk_dns_mdns_libmdns_MDNSResponderOperator_h
|
225
netwerk/dns/mdns/libmdns/MDNSResponderReply.cpp
Normal file
225
netwerk/dns/mdns/libmdns/MDNSResponderReply.cpp
Normal file
@ -0,0 +1,225 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MDNSResponderReply.h"
|
||||
#include "mozilla/Endian.h"
|
||||
#include "private/pprio.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
BrowseReplyRunnable::BrowseReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aServiceName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aReplyDomain,
|
||||
BrowseOperator* aContext)
|
||||
: mSdRef(aSdRef)
|
||||
, mFlags(aFlags)
|
||||
, mInterfaceIndex(aInterfaceIndex)
|
||||
, mErrorCode(aErrorCode)
|
||||
, mServiceName(aServiceName)
|
||||
, mRegType(aRegType)
|
||||
, mReplyDomain(aReplyDomain)
|
||||
, mContext(aContext)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BrowseReplyRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(mContext);
|
||||
mContext->Reply(mSdRef,
|
||||
mFlags,
|
||||
mInterfaceIndex,
|
||||
mErrorCode,
|
||||
mServiceName,
|
||||
mRegType,
|
||||
mReplyDomain);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
BrowseReplyRunnable::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aServiceName,
|
||||
const char* aRegType,
|
||||
const char* aReplyDomain,
|
||||
void* aContext)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
BrowseOperator* obj(reinterpret_cast<BrowseOperator*>(aContext));
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> thread(obj->GetThread());
|
||||
if (!thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
thread->Dispatch(new BrowseReplyRunnable(aSdRef,
|
||||
aFlags,
|
||||
aInterfaceIndex,
|
||||
aErrorCode,
|
||||
nsCString(aServiceName),
|
||||
nsCString(aRegType),
|
||||
nsCString(aReplyDomain),
|
||||
obj),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
RegisterReplyRunnable::RegisterReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& domain,
|
||||
RegisterOperator* aContext)
|
||||
: mSdRef(aSdRef)
|
||||
, mFlags(aFlags)
|
||||
, mErrorCode(aErrorCode)
|
||||
, mName(aName)
|
||||
, mRegType(aRegType)
|
||||
, mDomain(domain)
|
||||
, mContext(aContext)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RegisterReplyRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(mContext);
|
||||
|
||||
mContext->Reply(mSdRef,
|
||||
mFlags,
|
||||
mErrorCode,
|
||||
mName,
|
||||
mRegType,
|
||||
mDomain);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
RegisterReplyRunnable::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aName,
|
||||
const char* aRegType,
|
||||
const char* domain,
|
||||
void* aContext)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
RegisterOperator* obj(reinterpret_cast<RegisterOperator*>(aContext));
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> thread(obj->GetThread());
|
||||
if (!thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
thread->Dispatch(new RegisterReplyRunnable(aSdRef,
|
||||
aFlags,
|
||||
aErrorCode,
|
||||
nsCString(aName),
|
||||
nsCString(aRegType),
|
||||
nsCString(domain),
|
||||
obj),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
ResolveReplyRunnable::ResolveReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aFullName,
|
||||
const nsACString& aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord,
|
||||
ResolveOperator* aContext)
|
||||
: mSdRef(aSdRef)
|
||||
, mFlags(aFlags)
|
||||
, mInterfaceIndex(aInterfaceIndex)
|
||||
, mErrorCode(aErrorCode)
|
||||
, mFullname(aFullName)
|
||||
, mHosttarget(aHostTarget)
|
||||
, mPort(aPort)
|
||||
, mTxtLen(aTxtLen)
|
||||
, mTxtRecord(new unsigned char[aTxtLen])
|
||||
, mContext(aContext)
|
||||
{
|
||||
if (mTxtRecord) {
|
||||
memcpy(mTxtRecord.get(), aTxtRecord, aTxtLen);
|
||||
}
|
||||
}
|
||||
|
||||
ResolveReplyRunnable::~ResolveReplyRunnable()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ResolveReplyRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(mContext);
|
||||
mContext->Reply(mSdRef,
|
||||
mFlags,
|
||||
mInterfaceIndex,
|
||||
mErrorCode,
|
||||
mFullname,
|
||||
mHosttarget,
|
||||
mPort,
|
||||
mTxtLen,
|
||||
mTxtRecord.get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ResolveReplyRunnable::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aFullName,
|
||||
const char* aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord,
|
||||
void* aContext)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
ResolveOperator* obj(reinterpret_cast<ResolveOperator*>(aContext));
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> thread(obj->GetThread());
|
||||
if (!thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
thread->Dispatch(new ResolveReplyRunnable(aSdRef,
|
||||
aFlags,
|
||||
aInterfaceIndex,
|
||||
aErrorCode,
|
||||
nsCString(aFullName),
|
||||
nsCString(aHostTarget),
|
||||
NativeEndian::swapFromNetworkOrder(aPort),
|
||||
aTxtLen,
|
||||
aTxtRecord,
|
||||
obj),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
128
netwerk/dns/mdns/libmdns/MDNSResponderReply.h
Normal file
128
netwerk/dns/mdns/libmdns/MDNSResponderReply.h
Normal file
@ -0,0 +1,128 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_netwerk_dns_mdns_libmdns_MDNSResponderReply_h
|
||||
#define mozilla_netwerk_dns_mdns_libmdns_MDNSResponderReply_h
|
||||
|
||||
#include "dns_sd.h"
|
||||
#include "MDNSResponderOperator.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsRefPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class BrowseReplyRunnable final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
BrowseReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aServiceName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aReplyDomain,
|
||||
BrowseOperator* aContext);
|
||||
|
||||
NS_IMETHODIMP Run() override;
|
||||
|
||||
static void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aServiceName,
|
||||
const char* aRegType,
|
||||
const char* aReplyDomain,
|
||||
void* aContext);
|
||||
|
||||
private:
|
||||
DNSServiceRef mSdRef;
|
||||
DNSServiceFlags mFlags;
|
||||
uint32_t mInterfaceIndex;
|
||||
DNSServiceErrorType mErrorCode;
|
||||
nsCString mServiceName;
|
||||
nsCString mRegType;
|
||||
nsCString mReplyDomain;
|
||||
BrowseOperator* mContext;
|
||||
};
|
||||
|
||||
class RegisterReplyRunnable final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
RegisterReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aDomain,
|
||||
RegisterOperator* aContext);
|
||||
|
||||
NS_IMETHODIMP Run() override;
|
||||
|
||||
static void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aName,
|
||||
const char* aRegType,
|
||||
const char* aDomain,
|
||||
void* aContext);
|
||||
|
||||
private:
|
||||
DNSServiceRef mSdRef;
|
||||
DNSServiceFlags mFlags;
|
||||
DNSServiceErrorType mErrorCode;
|
||||
nsCString mName;
|
||||
nsCString mRegType;
|
||||
nsCString mDomain;
|
||||
RegisterOperator* mContext;
|
||||
};
|
||||
|
||||
class ResolveReplyRunnable final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ResolveReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aFullName,
|
||||
const nsACString& aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord,
|
||||
ResolveOperator* aContext);
|
||||
~ResolveReplyRunnable();
|
||||
|
||||
NS_IMETHODIMP Run() override;
|
||||
|
||||
static void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aFullName,
|
||||
const char* aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord,
|
||||
void* aContext);
|
||||
|
||||
private:
|
||||
DNSServiceRef mSdRef;
|
||||
DNSServiceFlags mFlags;
|
||||
uint32_t mInterfaceIndex;
|
||||
DNSServiceErrorType mErrorCode;
|
||||
nsCString mFullname;
|
||||
nsCString mHosttarget;
|
||||
uint16_t mPort;
|
||||
uint16_t mTxtLen;
|
||||
UniquePtr<unsigned char> mTxtRecord;
|
||||
nsRefPtr<ResolveOperator> mContext;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_netwerk_dns_mdns_libmdns_MDNSResponderReply_h
|
33
netwerk/dns/mdns/libmdns/moz.build
Normal file
33
netwerk/dns/mdns/libmdns/moz.build
Normal file
@ -0,0 +1,33 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['ANDROID_VERSION'] >= '16':
|
||||
UNIFIED_SOURCES += [
|
||||
'MDNSResponderOperator.cpp',
|
||||
'MDNSResponderReply.cpp',
|
||||
'nsDNSServiceDiscovery.cpp',
|
||||
]
|
||||
|
||||
CXXFLAGS += [
|
||||
'-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
|
||||
'external/mdnsresponder/mDNSShared',
|
||||
]
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/netwerk/base',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'nsDNSServiceInfo.cpp',
|
||||
'nsMulticastDNSModule.cpp',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
FINAL_LIBRARY = 'xul'
|
230
netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.cpp
Normal file
230
netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsDNSServiceDiscovery.h"
|
||||
#include <cutils/properties.h>
|
||||
#include "MDNSResponderOperator.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "private/pprio.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
StartService()
|
||||
{
|
||||
char value[PROPERTY_VALUE_MAX] = { '\0' };
|
||||
property_get("init.svc.mdnsd", value, "");
|
||||
|
||||
if (strcmp(value, "running") == 0) {
|
||||
return;
|
||||
}
|
||||
property_set("ctl.start", "mdnsd");
|
||||
}
|
||||
|
||||
void
|
||||
StopService()
|
||||
{
|
||||
char value[PROPERTY_VALUE_MAX] = { '\0' };
|
||||
property_get("init.svc.mdnsd", value, "");
|
||||
|
||||
if (strcmp(value, "stopped") == 0) {
|
||||
return;
|
||||
}
|
||||
property_set("ctl.stop", "mdnsd");
|
||||
}
|
||||
|
||||
class DiscoveryRequest final : public nsICancelable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICANCELABLE
|
||||
|
||||
explicit DiscoveryRequest(nsDNSServiceDiscovery* aService,
|
||||
nsIDNSServiceDiscoveryListener* aListener);
|
||||
|
||||
private:
|
||||
virtual ~DiscoveryRequest() { Cancel(NS_OK); }
|
||||
|
||||
nsRefPtr<nsDNSServiceDiscovery> mService;
|
||||
nsIDNSServiceDiscoveryListener* mListener;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(DiscoveryRequest, nsICancelable)
|
||||
|
||||
DiscoveryRequest::DiscoveryRequest(nsDNSServiceDiscovery* aService,
|
||||
nsIDNSServiceDiscoveryListener* aListener)
|
||||
: mService(aService)
|
||||
, mListener(aListener)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DiscoveryRequest::Cancel(nsresult aReason)
|
||||
{
|
||||
if (mService) {
|
||||
mService->StopDiscovery(mListener);
|
||||
}
|
||||
|
||||
mService = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class RegisterRequest final : public nsICancelable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICANCELABLE
|
||||
|
||||
explicit RegisterRequest(nsDNSServiceDiscovery* aService,
|
||||
nsIDNSRegistrationListener* aListener);
|
||||
|
||||
private:
|
||||
virtual ~RegisterRequest() { Cancel(NS_OK); }
|
||||
|
||||
nsRefPtr<nsDNSServiceDiscovery> mService;
|
||||
nsIDNSRegistrationListener* mListener;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(RegisterRequest, nsICancelable)
|
||||
|
||||
RegisterRequest::RegisterRequest(nsDNSServiceDiscovery* aService,
|
||||
nsIDNSRegistrationListener* aListener)
|
||||
: mService(aService)
|
||||
, mListener(aListener)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RegisterRequest::Cancel(nsresult aReason)
|
||||
{
|
||||
if (mService) {
|
||||
mService->UnregisterService(mListener);
|
||||
}
|
||||
|
||||
mService = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsDNSServiceDiscovery, nsIDNSServiceDiscovery)
|
||||
|
||||
nsresult
|
||||
nsDNSServiceDiscovery::Init()
|
||||
{
|
||||
StartService();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceDiscovery::StartDiscovery(const nsACString& aServiceType,
|
||||
nsIDNSServiceDiscoveryListener* aListener,
|
||||
nsICancelable** aRetVal)
|
||||
{
|
||||
MOZ_ASSERT(aRetVal);
|
||||
|
||||
nsresult rv;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = StopDiscovery(aListener)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsRefPtr<BrowseOperator> browserOp = new BrowseOperator(aServiceType,
|
||||
aListener);
|
||||
if (NS_WARN_IF(NS_FAILED(rv = browserOp->Start()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mDiscoveryMap.Put(aListener, browserOp);
|
||||
|
||||
nsCOMPtr<nsICancelable> req = new DiscoveryRequest(this, aListener);
|
||||
req.forget(aRetVal);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceDiscovery::StopDiscovery(nsIDNSServiceDiscoveryListener* aListener)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsRefPtr<BrowseOperator> browserOp;
|
||||
if (!mDiscoveryMap.Get(aListener, getter_AddRefs(browserOp))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
browserOp->Cancel(); // cancel non-started operation
|
||||
if (NS_WARN_IF(NS_FAILED(rv = browserOp->Stop()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mDiscoveryMap.Remove(aListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceDiscovery::RegisterService(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSRegistrationListener* aListener,
|
||||
nsICancelable** aRetVal)
|
||||
{
|
||||
MOZ_ASSERT(aRetVal);
|
||||
|
||||
nsresult rv;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = UnregisterService(aListener)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsRefPtr<RegisterOperator> registerOp = new RegisterOperator(aServiceInfo,
|
||||
aListener);
|
||||
if (NS_WARN_IF(NS_FAILED(rv = registerOp->Start()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mRegisterMap.Put(aListener, registerOp);
|
||||
|
||||
nsCOMPtr<nsICancelable> req = new RegisterRequest(this, aListener);
|
||||
req.forget(aRetVal);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceDiscovery::UnregisterService(nsIDNSRegistrationListener* aListener)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsRefPtr<RegisterOperator> registerOp;
|
||||
if (!mRegisterMap.Get(aListener, getter_AddRefs(registerOp))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
registerOp->Cancel(); // cancel non-started operation
|
||||
if (NS_WARN_IF(NS_FAILED(rv = registerOp->Stop()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mRegisterMap.Remove(aListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceDiscovery::ResolveService(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSServiceResolveListener* aListener)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsRefPtr<ResolveOperator> resolveOp = new ResolveOperator(aServiceInfo,
|
||||
aListener);
|
||||
if (NS_WARN_IF(NS_FAILED(rv = resolveOp->Start()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
48
netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.h
Normal file
48
netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceDiscovery_h
|
||||
#define mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceDiscovery_h
|
||||
|
||||
#include "nsIDNSServiceDiscovery.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsRefPtr.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class BrowseOperator;
|
||||
class RegisterOperator;
|
||||
|
||||
class nsDNSServiceDiscovery final : public nsIDNSServiceDiscovery
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIDNSSERVICEDISCOVERY
|
||||
|
||||
explicit nsDNSServiceDiscovery() = default;
|
||||
|
||||
/*
|
||||
** The mDNS service is started in this function. However, the function returns
|
||||
** without waiting. Therefore, all operations before service started will fail
|
||||
** and get error code |kDNSServiceErr_ServiceNotRunning| defined in dns_sd.h.
|
||||
**/
|
||||
nsresult Init();
|
||||
|
||||
nsresult StopDiscovery(nsIDNSServiceDiscoveryListener* aListener);
|
||||
nsresult UnregisterService(nsIDNSRegistrationListener* aListener);
|
||||
|
||||
private:
|
||||
virtual ~nsDNSServiceDiscovery() = default;
|
||||
|
||||
nsRefPtrHashtable<nsISupportsHashKey, BrowseOperator> mDiscoveryMap;
|
||||
nsRefPtrHashtable<nsISupportsHashKey, RegisterOperator> mRegisterMap;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceDiscovery_h
|
183
netwerk/dns/mdns/libmdns/nsDNSServiceInfo.cpp
Normal file
183
netwerk/dns/mdns/libmdns/nsDNSServiceInfo.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsDNSServiceInfo.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsIProperty.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsDNSServiceInfo, nsIDNSServiceInfo)
|
||||
|
||||
nsDNSServiceInfo::nsDNSServiceInfo(nsIDNSServiceInfo* aServiceInfo)
|
||||
{
|
||||
if (NS_WARN_IF(!aServiceInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString str;
|
||||
uint16_t value;
|
||||
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetHost(str))) {
|
||||
NS_WARN_IF(NS_FAILED(SetHost(str)));
|
||||
}
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetPort(&value))) {
|
||||
NS_WARN_IF(NS_FAILED(SetPort(value)));
|
||||
}
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetServiceName(str))) {
|
||||
NS_WARN_IF(NS_FAILED(SetServiceName(str)));
|
||||
}
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetServiceType(str))) {
|
||||
NS_WARN_IF(NS_FAILED(SetServiceType(str)));
|
||||
}
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetDomainName(str))) {
|
||||
NS_WARN_IF(NS_FAILED(SetDomainName(str)));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPropertyBag2> attributes; // deep copy
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetAttributes(getter_AddRefs(attributes)))) {
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
if (NS_WARN_IF(NS_FAILED(attributes->GetEnumerator(getter_AddRefs(enumerator))))) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWritablePropertyBag2> newAttributes = new nsHashPropertyBag();
|
||||
|
||||
bool hasMoreElements;
|
||||
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements)) &&
|
||||
hasMoreElements) {
|
||||
nsCOMPtr<nsISupports> element;
|
||||
NS_WARN_IF(NS_FAILED(enumerator->GetNext(getter_AddRefs(element))));
|
||||
nsCOMPtr<nsIProperty> property = do_QueryInterface(element);
|
||||
MOZ_ASSERT(property);
|
||||
|
||||
nsAutoString name;
|
||||
nsCOMPtr<nsIVariant> value;
|
||||
NS_WARN_IF(NS_FAILED(property->GetName(name)));
|
||||
NS_WARN_IF(NS_FAILED(property->GetValue(getter_AddRefs(value))));
|
||||
NS_WARN_IF(NS_FAILED(newAttributes->SetPropertyAsInterface(name, value)));
|
||||
}
|
||||
|
||||
NS_WARN_IF(NS_FAILED(SetAttributes(newAttributes)));
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetHost(nsACString& aHost)
|
||||
{
|
||||
if (!mIsHostSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
aHost = mHost;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetHost(const nsACString& aHost)
|
||||
{
|
||||
mHost = aHost;
|
||||
mIsHostSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetPort(uint16_t* aPort)
|
||||
{
|
||||
if (NS_WARN_IF(!aPort)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
if (!mIsPortSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
*aPort = mPort;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetPort(uint16_t aPort)
|
||||
{
|
||||
mPort = aPort;
|
||||
mIsPortSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetServiceName(nsACString& aServiceName)
|
||||
{
|
||||
if (!mIsServiceNameSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
aServiceName = mServiceName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetServiceName(const nsACString& aServiceName)
|
||||
{
|
||||
mServiceName = aServiceName;
|
||||
mIsServiceNameSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetServiceType(nsACString& aServiceType)
|
||||
{
|
||||
if (!mIsServiceTypeSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
aServiceType = mServiceType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetServiceType(const nsACString& aServiceType)
|
||||
{
|
||||
mServiceType = aServiceType;
|
||||
mIsServiceTypeSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetDomainName(nsACString& aDomainName)
|
||||
{
|
||||
if (!mIsDomainNameSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
aDomainName = mDomainName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetDomainName(const nsACString& aDomainName)
|
||||
{
|
||||
mDomainName = aDomainName;
|
||||
mIsDomainNameSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetAttributes(nsIPropertyBag2** aAttributes)
|
||||
{
|
||||
if (!mIsAttributesSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
nsCOMPtr<nsIPropertyBag2> attributes(mAttributes);
|
||||
attributes.forget(aAttributes);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetAttributes(nsIPropertyBag2* aAttributes)
|
||||
{
|
||||
mAttributes = aAttributes;
|
||||
mIsAttributesSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
48
netwerk/dns/mdns/libmdns/nsDNSServiceInfo.h
Normal file
48
netwerk/dns/mdns/libmdns/nsDNSServiceInfo.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceInfo_h
|
||||
#define mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceInfo_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDNSServiceDiscovery.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class nsDNSServiceInfo final : public nsIDNSServiceInfo
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDNSSERVICEINFO
|
||||
|
||||
explicit nsDNSServiceInfo() = default;
|
||||
explicit nsDNSServiceInfo(nsIDNSServiceInfo* aServiceInfo);
|
||||
|
||||
private:
|
||||
virtual ~nsDNSServiceInfo() = default;
|
||||
|
||||
private:
|
||||
nsCString mHost;
|
||||
uint16_t mPort = 0;
|
||||
nsCString mServiceName;
|
||||
nsCString mServiceType;
|
||||
nsCString mDomainName;
|
||||
nsCOMPtr<nsIPropertyBag2> mAttributes;
|
||||
|
||||
bool mIsHostSet = false;
|
||||
bool mIsPortSet = false;
|
||||
bool mIsServiceNameSet = false;
|
||||
bool mIsServiceTypeSet = false;
|
||||
bool mIsDomainNameSet = false;
|
||||
bool mIsAttributesSet = false;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceInfo_h
|
61
netwerk/dns/mdns/libmdns/nsMulticastDNSModule.cpp
Normal file
61
netwerk/dns/mdns/libmdns/nsMulticastDNSModule.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 16
|
||||
#define ENABLE_DNS_SERVICE_DISCOVERY
|
||||
#endif
|
||||
|
||||
#include "mozilla/ModuleUtils.h"
|
||||
|
||||
#ifdef ENABLE_DNS_SERVICE_DISCOVERY
|
||||
#include "nsDNSServiceDiscovery.h"
|
||||
#endif
|
||||
|
||||
#include "nsDNSServiceInfo.h"
|
||||
|
||||
#ifdef ENABLE_DNS_SERVICE_DISCOVERY
|
||||
using mozilla::net::nsDNSServiceDiscovery;
|
||||
#define DNSSERVICEDISCOVERY_CID \
|
||||
{0x8df43d23, 0xd3f9, 0x4dd5, \
|
||||
{ 0xb9, 0x65, 0xde, 0x2c, 0xa3, 0xf6, 0xa4, 0x2c }}
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDNSServiceDiscovery, Init)
|
||||
NS_DEFINE_NAMED_CID(DNSSERVICEDISCOVERY_CID);
|
||||
#endif // ENABLE_DNS_SERVICE_DISCOVERY
|
||||
|
||||
using mozilla::net::nsDNSServiceInfo;
|
||||
#define DNSSERVICEINFO_CID \
|
||||
{0x14a50f2b, 0x7ff6, 0x48a5, \
|
||||
{ 0x88, 0xe3, 0x61, 0x5f, 0xd1, 0x11, 0xf5, 0xd3 }}
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDNSServiceInfo)
|
||||
NS_DEFINE_NAMED_CID(DNSSERVICEINFO_CID);
|
||||
|
||||
static const mozilla::Module::CIDEntry knsDNSServiceDiscoveryCIDs[] = {
|
||||
#ifdef ENABLE_DNS_SERVICE_DISCOVERY
|
||||
{ &kDNSSERVICEDISCOVERY_CID, false, nullptr, nsDNSServiceDiscoveryConstructor },
|
||||
#endif
|
||||
{ &kDNSSERVICEINFO_CID, false, nullptr, nsDNSServiceInfoConstructor },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module::ContractIDEntry knsDNSServiceDiscoveryContracts[] = {
|
||||
#ifdef ENABLE_DNS_SERVICE_DISCOVERY
|
||||
{ DNSSERVICEDISCOVERY_CONTRACT_ID, &kDNSSERVICEDISCOVERY_CID },
|
||||
#endif
|
||||
{ DNSSERVICEINFO_CONTRACT_ID, &kDNSSERVICEINFO_CID },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module::CategoryEntry knsDNSServiceDiscoveryCategories[] = {
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module knsDNSServiceDiscoveryModule = {
|
||||
mozilla::Module::kVersion,
|
||||
knsDNSServiceDiscoveryCIDs,
|
||||
knsDNSServiceDiscoveryContracts,
|
||||
knsDNSServiceDiscoveryCategories
|
||||
};
|
||||
|
||||
NSMODULE_DEFN(nsDNSServiceDiscoveryModule) = &knsDNSServiceDiscoveryModule;
|
13
netwerk/dns/mdns/moz.build
Normal file
13
netwerk/dns/mdns/moz.build
Normal file
@ -0,0 +1,13 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += ['libmdns']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDNSServiceDiscovery.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'necko_mdns'
|
213
netwerk/dns/mdns/nsIDNSServiceDiscovery.idl
Normal file
213
netwerk/dns/mdns/nsIDNSServiceDiscovery.idl
Normal file
@ -0,0 +1,213 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsICancelable;
|
||||
interface nsIPropertyBag2;
|
||||
|
||||
/**
|
||||
* Service information
|
||||
*/
|
||||
[scriptable, uuid(112bfa89-1b57-4acf-8287-48e5466c1b39)]
|
||||
interface nsIDNSServiceInfo : nsISupports
|
||||
{
|
||||
/**
|
||||
* The host name of the service. (E.g. "Android.local.")
|
||||
* @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
|
||||
*/
|
||||
attribute AUTF8String host;
|
||||
|
||||
/**
|
||||
* The port number of the service. (E.g. 80)
|
||||
* @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
|
||||
*/
|
||||
attribute unsigned short port;
|
||||
|
||||
/**
|
||||
* The service name of the service for display. (E.g. "My TV")
|
||||
* @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
|
||||
*/
|
||||
attribute AUTF8String serviceName;
|
||||
|
||||
/**
|
||||
* The type of the service. (E.g. "_http._tcp")
|
||||
* @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
|
||||
*/
|
||||
attribute AUTF8String serviceType;
|
||||
|
||||
/**
|
||||
* The domain name of the service. (E.g. "local.")
|
||||
* @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
|
||||
*/
|
||||
attribute AUTF8String domainName;
|
||||
|
||||
/**
|
||||
* The attributes of the service.
|
||||
*/
|
||||
attribute nsIPropertyBag2 attributes;
|
||||
};
|
||||
|
||||
/**
|
||||
* The callback interface for service discovery
|
||||
*/
|
||||
[scriptable, uuid(3025b7f2-97bb-435b-b43d-26731b3f5fc4)]
|
||||
interface nsIDNSServiceDiscoveryListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* Callback when the discovery begins.
|
||||
* @param aServiceType
|
||||
* the service type of |startDiscovery|.
|
||||
*/
|
||||
void onDiscoveryStarted(in AUTF8String aServiceType);
|
||||
|
||||
/**
|
||||
* Callback when the discovery ends.
|
||||
* @param aServiceType
|
||||
* the service type of |startDiscovery|.
|
||||
*/
|
||||
void onDiscoveryStopped(in AUTF8String aServiceType);
|
||||
|
||||
/**
|
||||
* Callback when the a service is found.
|
||||
* @param aServiceInfo
|
||||
* the info about the found service, where |serviceName|, |aServiceType|, and |domainName| are set.
|
||||
*/
|
||||
void onServiceFound(in nsIDNSServiceInfo aServiceInfo);
|
||||
|
||||
/**
|
||||
* Callback when the a service is lost.
|
||||
* @param aServiceInfo
|
||||
* the info about the lost service, where |serviceName|, |aServiceType|, and |domainName| are set.
|
||||
*/
|
||||
void onServiceLost(in nsIDNSServiceInfo aServiceInfo);
|
||||
|
||||
/**
|
||||
* Callback when the discovery cannot start.
|
||||
* @param aServiceType
|
||||
* the service type of |startDiscovery|.
|
||||
* @param aErrorCode
|
||||
* the error code.
|
||||
*/
|
||||
void onStartDiscoveryFailed(in AUTF8String aServiceType, in long aErrorCode);
|
||||
|
||||
/**
|
||||
* Callback when the discovery cannot stop.
|
||||
* @param aServiceType
|
||||
* the service type of |startDiscovery|.
|
||||
* @param aErrorCode
|
||||
* the error code.
|
||||
*/
|
||||
void onStopDiscoveryFailed(in AUTF8String aServiceType, in long aErrorCode);
|
||||
};
|
||||
|
||||
/**
|
||||
* The callback interface for service registration
|
||||
*/
|
||||
[scriptable, uuid(e165e4be-abf4-4963-a66d-ed3ca116e5e4)]
|
||||
interface nsIDNSRegistrationListener : nsISupports
|
||||
{
|
||||
const long ERROR_SERVICE_NOT_RUNNING = -65563;
|
||||
|
||||
/**
|
||||
* Callback when the service is registered successfully.
|
||||
* @param aServiceInfo
|
||||
* the info about the registered service,
|
||||
* where |serviceName|, |aServiceType|, and |domainName| are set.
|
||||
*/
|
||||
void onServiceRegistered(in nsIDNSServiceInfo aServiceInfo);
|
||||
|
||||
/**
|
||||
* Callback when the service is unregistered successfully.
|
||||
* @param aServiceInfo
|
||||
* the info about the unregistered service.
|
||||
*/
|
||||
void onServiceUnregistered(in nsIDNSServiceInfo aServiceInfo);
|
||||
|
||||
/**
|
||||
* Callback when the service cannot be registered.
|
||||
* @param aServiceInfo
|
||||
* the info about the service to be registered.
|
||||
* @param aErrorCode
|
||||
* the error code.
|
||||
*/
|
||||
void onRegistrationFailed(in nsIDNSServiceInfo aServiceInfo, in long aErrorCode);
|
||||
|
||||
/**
|
||||
* Callback when the service cannot be unregistered.
|
||||
* @param aServiceInfo
|
||||
* the info about the registered service.
|
||||
* @param aErrorCode
|
||||
* the error code.
|
||||
*/
|
||||
void onUnregistrationFailed(in nsIDNSServiceInfo aServiceInfo, in long aErrorCode);
|
||||
};
|
||||
|
||||
/**
|
||||
* The callback interface for service resolve
|
||||
*/
|
||||
[scriptable, uuid(24ee6408-648e-421d-accf-c6e5adeccf97)]
|
||||
interface nsIDNSServiceResolveListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* Callback when the service is resolved successfully.
|
||||
* @param aServiceInfo
|
||||
* the info about the resolved service, where |host| and |port| are set.
|
||||
*/
|
||||
void onServiceResolved(in nsIDNSServiceInfo aServiceInfo);
|
||||
|
||||
/**
|
||||
* Callback when the service cannot be resolved.
|
||||
* @param aServiceInfo
|
||||
* the info about the service to be resolved.
|
||||
* @param aErrorCode
|
||||
* the error code.
|
||||
*/
|
||||
void onResolveFailed(in nsIDNSServiceInfo aServiceInfo, in long aErrorCode);
|
||||
};
|
||||
|
||||
/**
|
||||
* The interface for DNS service discovery/registration/resolve
|
||||
*/
|
||||
[scriptable, uuid(6487899b-beb1-455a-ba65-e4fd465066d7)]
|
||||
interface nsIDNSServiceDiscovery : nsISupports
|
||||
{
|
||||
/**
|
||||
* Browse for instances of a service.
|
||||
* @param aServiceType
|
||||
* the service type to be discovered, E.g. "_http._tcp".
|
||||
* @param aListener
|
||||
* callback interface for discovery notifications.
|
||||
* @return An object that can be used to cancel the service discovery.
|
||||
*/
|
||||
nsICancelable startDiscovery(in AUTF8String aServiceType, in nsIDNSServiceDiscoveryListener aListener);
|
||||
|
||||
/**
|
||||
* Register a service that is discovered via |startDiscovery| and |resolveService| calls.
|
||||
* @param aServiceInfo
|
||||
* the service information to be registered.
|
||||
* |port| and |aServiceType| are required attributes.
|
||||
* @param aListener
|
||||
* callback interface for registration notifications.
|
||||
* @return An object that can be used to cancel the service registration.
|
||||
*/
|
||||
nsICancelable registerService(in nsIDNSServiceInfo aServiceInfo, in nsIDNSRegistrationListener aListener);
|
||||
|
||||
/**
|
||||
* Resolve a service name discovered via |startDiscovery| to a target host name, port number.
|
||||
* @param aServiceInfo
|
||||
* the service information to be registered.
|
||||
* |serviceName|, |aServiceType|, and |domainName| are required attributes as reported to the |onServiceFound| callback.
|
||||
* @param aListener
|
||||
* callback interface for registration notifications.
|
||||
*/
|
||||
void resolveService(in nsIDNSServiceInfo aServiceInfo, in nsIDNSServiceResolveListener aListener);
|
||||
};
|
||||
|
||||
%{ C++
|
||||
#define DNSSERVICEDISCOVERY_CONTRACT_ID \
|
||||
"@mozilla.org/toolkit/components/mdnsresponder/dns-sd;1"
|
||||
#define DNSSERVICEINFO_CONTRACT_ID \
|
||||
"@mozilla.org/toolkit/components/mdnsresponder/dns-info;1"
|
||||
%}
|
@ -4,6 +4,10 @@
|
||||
# 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/.
|
||||
|
||||
DIRS += [
|
||||
'mdns',
|
||||
]
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDNSListener.idl',
|
||||
'nsIDNSRecord.idl',
|
||||
|
@ -154,7 +154,7 @@ class DecisionTask(object):
|
||||
'owner': params['owner'],
|
||||
'as_slugid': SlugidJar(),
|
||||
'from_now': json_time_from_now,
|
||||
'now': datetime.datetime.now().isoformat()
|
||||
'now': current_json_time()
|
||||
}.items())
|
||||
task = templates.load(params['task'], parameters)
|
||||
print(json.dumps(task, indent=4))
|
||||
@ -225,7 +225,7 @@ class Graph(object):
|
||||
'head_rev': params['head_rev'],
|
||||
'owner': params['owner'],
|
||||
'from_now': json_time_from_now,
|
||||
'now': datetime.datetime.now().isoformat(),
|
||||
'now': current_json_time(),
|
||||
'mozharness_repository': mozharness['repo'],
|
||||
'mozharness_rev': mozharness['revision'],
|
||||
'mozharness_ref':mozharness.get('reference', mozharness['revision']),
|
||||
|
@ -258,6 +258,11 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
'sync',
|
||||
]
|
||||
|
||||
if CONFIG['ANDROID_VERSION'] >= '16':
|
||||
OS_LIBS += [
|
||||
'mdnssd',
|
||||
]
|
||||
|
||||
if 'rtsp' in CONFIG['NECKO_PROTOCOLS']:
|
||||
OS_LIBS += [
|
||||
'stagefright_foundation',
|
||||
|
@ -50,15 +50,23 @@ def MergeProfiles(files):
|
||||
pidStr = pid + ":"
|
||||
|
||||
thread['startTime'] = fileData['profileJSON']['meta']['startTime']
|
||||
samples = thread['samples']
|
||||
for sample in thread['samples']:
|
||||
for frame in sample['frames']:
|
||||
if "location" in frame and frame['location'][0:2] == '0x':
|
||||
oldLoc = frame['location']
|
||||
newLoc = pidStr + oldLoc
|
||||
frame['location'] = newLoc
|
||||
# Default to the unprefixed symbol if no translation is available
|
||||
symTable[newLoc] = oldLoc
|
||||
if meta['version'] >= 3:
|
||||
stringTable = thread['stringTable']
|
||||
for i, str in enumerate(stringTable):
|
||||
if str[:2] == '0x':
|
||||
newLoc = pidStr + str
|
||||
stringTable[i] = newLoc
|
||||
symTable[newLoc] = str
|
||||
else:
|
||||
samples = thread['samples']
|
||||
for sample in thread['samples']:
|
||||
for frame in sample['frames']:
|
||||
if "location" in frame and frame['location'][0:2] == '0x':
|
||||
oldLoc = frame['location']
|
||||
newLoc = pidStr + oldLoc
|
||||
frame['location'] = newLoc
|
||||
# Default to the unprefixed symbol if no translation is
|
||||
symTable[newLoc] = oldLoc
|
||||
|
||||
filesyms = fileData['symbolicationTable']
|
||||
for sym in filesyms.keys():
|
||||
@ -68,11 +76,19 @@ def MergeProfiles(files):
|
||||
# earliest start
|
||||
for thread in threads:
|
||||
delta = thread['startTime'] - minStartTime
|
||||
for sample in thread['samples']:
|
||||
if "time" in sample:
|
||||
sample['time'] += delta
|
||||
for marker in thread['markers']:
|
||||
marker['time'] += delta
|
||||
if meta['version'] >= 3:
|
||||
idxTime = thread['samples']['schema']['time']
|
||||
for sample in thread['samples']['data']:
|
||||
sample[idxTime] += delta
|
||||
idxTime = thread['markers']['schema']['time']
|
||||
for marker in thread['markers']['data']:
|
||||
marker[idxTime] += delta
|
||||
else:
|
||||
for sample in thread['samples']:
|
||||
if "time" in sample:
|
||||
sample['time'] += delta
|
||||
for marker in thread['markers']:
|
||||
marker['time'] += delta
|
||||
|
||||
result = dict()
|
||||
result['profileJSON'] = dict()
|
||||
|
@ -149,6 +149,40 @@ status_t KeyLayoutMap::mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const {
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t KeyLayoutMap::findScanCodeForLed(int32_t ledCode, int32_t* outScanCode) const {
|
||||
const size_t N = mLedsByScanCode.size();
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
if (mLedsByScanCode.valueAt(i).ledCode == ledCode) {
|
||||
*outScanCode = mLedsByScanCode.keyAt(i);
|
||||
#if DEBUG_MAPPING
|
||||
ALOGD("findScanCodeForLed: ledCode=%d, scanCode=%d.", ledCode, *outScanCode);
|
||||
#endif
|
||||
return NO_ERROR;
|
||||
}
|
||||
}
|
||||
#if DEBUG_MAPPING
|
||||
ALOGD("findScanCodeForLed: ledCode=%d ~ Not found.", ledCode);
|
||||
#endif
|
||||
return NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
status_t KeyLayoutMap::findUsageCodeForLed(int32_t ledCode, int32_t* outUsageCode) const {
|
||||
const size_t N = mLedsByUsageCode.size();
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
if (mLedsByUsageCode.valueAt(i).ledCode == ledCode) {
|
||||
*outUsageCode = mLedsByUsageCode.keyAt(i);
|
||||
#if DEBUG_MAPPING
|
||||
ALOGD("findUsageForLed: ledCode=%d, usage=%x.", ledCode, *outUsageCode);
|
||||
#endif
|
||||
return NO_ERROR;
|
||||
}
|
||||
}
|
||||
#if DEBUG_MAPPING
|
||||
ALOGD("findUsageForLed: ledCode=%d ~ Not found.", ledCode);
|
||||
#endif
|
||||
return NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
// --- KeyLayoutMap::Parser ---
|
||||
|
||||
@ -178,6 +212,10 @@ status_t KeyLayoutMap::Parser::parse() {
|
||||
mTokenizer->skipDelimiters(WHITESPACE);
|
||||
status_t status = parseAxis();
|
||||
if (status) return status;
|
||||
} else if (keywordToken == "led") {
|
||||
mTokenizer->skipDelimiters(WHITESPACE);
|
||||
status_t status = parseLed();
|
||||
if (status) return status;
|
||||
} else {
|
||||
ALOGE("%s: Expected keyword, got '%s'.", mTokenizer->getLocation().string(),
|
||||
keywordToken.string());
|
||||
@ -363,4 +401,46 @@ status_t KeyLayoutMap::Parser::parseAxis() {
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
status_t KeyLayoutMap::Parser::parseLed() {
|
||||
String8 codeToken = mTokenizer->nextToken(WHITESPACE);
|
||||
bool mapUsage = false;
|
||||
if (codeToken == "usage") {
|
||||
mapUsage = true;
|
||||
mTokenizer->skipDelimiters(WHITESPACE);
|
||||
codeToken = mTokenizer->nextToken(WHITESPACE);
|
||||
}
|
||||
char* end;
|
||||
int32_t code = int32_t(strtol(codeToken.string(), &end, 0));
|
||||
if (*end) {
|
||||
ALOGE("%s: Expected led %s number, got '%s'.", mTokenizer->getLocation().string(),
|
||||
mapUsage ? "usage" : "scan code", codeToken.string());
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
KeyedVector<int32_t, Led>& map = mapUsage ? mMap->mLedsByUsageCode : mMap->mLedsByScanCode;
|
||||
if (map.indexOfKey(code) >= 0) {
|
||||
ALOGE("%s: Duplicate entry for led %s '%s'.", mTokenizer->getLocation().string(),
|
||||
mapUsage ? "usage" : "scan code", codeToken.string());
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
mTokenizer->skipDelimiters(WHITESPACE);
|
||||
String8 ledCodeToken = mTokenizer->nextToken(WHITESPACE);
|
||||
int32_t ledCode = getLedByLabel(ledCodeToken.string());
|
||||
if (ledCode < 0) {
|
||||
ALOGE("%s: Expected LED code label, got '%s'.", mTokenizer->getLocation().string(),
|
||||
ledCodeToken.string());
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
#if DEBUG_PARSER
|
||||
ALOGD("Parsed led %s: code=%d, ledCode=%d.",
|
||||
mapUsage ? "usage" : "scan code", code, ledCode);
|
||||
#endif
|
||||
|
||||
Led led;
|
||||
led.ledCode = ledCode;
|
||||
map.add(code, led);
|
||||
return NO_ERROR;
|
||||
}
|
||||
};
|
||||
|
@ -67,6 +67,8 @@ public:
|
||||
status_t mapKey(int32_t scanCode, int32_t usageCode,
|
||||
int32_t* outKeyCode, uint32_t* outFlags) const;
|
||||
status_t findScanCodesForKey(int32_t keyCode, Vector<int32_t>* outScanCodes) const;
|
||||
status_t findScanCodeForLed(int32_t ledCode, int32_t* outScanCode) const;
|
||||
status_t findUsageCodeForLed(int32_t ledCode, int32_t* outUsageCode) const;
|
||||
|
||||
status_t mapAxis(int32_t scanCode, AxisInfo* outAxisInfo) const;
|
||||
|
||||
@ -79,9 +81,16 @@ private:
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct Led {
|
||||
int32_t ledCode;
|
||||
};
|
||||
|
||||
|
||||
KeyedVector<int32_t, Key> mKeysByScanCode;
|
||||
KeyedVector<int32_t, Key> mKeysByUsageCode;
|
||||
KeyedVector<int32_t, AxisInfo> mAxes;
|
||||
KeyedVector<int32_t, Led> mLedsByScanCode;
|
||||
KeyedVector<int32_t, Led> mLedsByUsageCode;
|
||||
|
||||
KeyLayoutMap();
|
||||
|
||||
@ -99,6 +108,7 @@ private:
|
||||
private:
|
||||
status_t parseKey();
|
||||
status_t parseAxis();
|
||||
status_t parseLed();
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -204,6 +204,9 @@ const char* getAxisLabel(int32_t axisId) {
|
||||
return lookupLabelByValue(axisId, AXES);
|
||||
}
|
||||
|
||||
int32_t getLedByLabel(const char* label) {
|
||||
return int32_t(lookupValueByLabel(label, LEDS));
|
||||
}
|
||||
static int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) {
|
||||
int32_t newMetaState;
|
||||
if (down) {
|
||||
|
@ -105,6 +105,8 @@ extern int32_t getAxisByLabel(const char* label);
|
||||
*/
|
||||
extern const char* getAxisLabel(int32_t axisId);
|
||||
|
||||
extern int32_t getLedByLabel(const char* label);
|
||||
|
||||
/**
|
||||
* Updates a meta state field when a key is pressed or released.
|
||||
*/
|
||||
|
@ -356,4 +356,25 @@ static const KeycodeLabel AXES[] = {
|
||||
{ NULL, -1 }
|
||||
};
|
||||
|
||||
static const KeycodeLabel LEDS[] = {
|
||||
{ "NUM_LOCK", 1},
|
||||
{ "CAPS_LOCK", 2},
|
||||
{ "SCROLL_LOCK", 3},
|
||||
{ "COMPOSE", 4},
|
||||
{ "KANA", 5},
|
||||
{ "SLEEP", 6},
|
||||
{ "SUSPEND", 7},
|
||||
{ "MUTE", 8},
|
||||
{ "MISC", 9},
|
||||
{ "MAIL", 10},
|
||||
{ "CHARGING", 11},
|
||||
{ "CONTROLLER_1", 12},
|
||||
{ "CONTROLLER_2", 13},
|
||||
{ "CONTROLLER_3", 14},
|
||||
{ "CONTROLLER_4", 15},
|
||||
|
||||
// NOTE: If you add new LEDs here, you must also add them to Input.h
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
#endif // _ANDROIDFW_KEYCODE_LABELS_H
|
||||
|
Loading…
Reference in New Issue
Block a user