mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to fx-team. a=merge
This commit is contained in:
commit
175f356f03
@ -585,7 +585,7 @@ var shell = {
|
||||
// TODO: We should get the `isActive` state from evt.isActive.
|
||||
// Then we don't need to do `channel.isActive()` here.
|
||||
channel.isActive().onsuccess = function(evt) {
|
||||
this.sendChromeEvent({
|
||||
SystemAppProxy._sendCustomEvent('mozSystemWindowChromeEvent', {
|
||||
type: 'system-audiochannel-state-changed',
|
||||
name: channel.name,
|
||||
isActive: evt.target.result
|
||||
|
@ -15,7 +15,7 @@
|
||||
<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="1d3595836bd55b70478923d771051268a5dabf91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7e7e92fbeea90cad8bf6f494b1a73712f79178e8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<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="1d3595836bd55b70478923d771051268a5dabf91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7e7e92fbeea90cad8bf6f494b1a73712f79178e8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d3595836bd55b70478923d771051268a5dabf91"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7e7e92fbeea90cad8bf6f494b1a73712f79178e8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</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="1d3595836bd55b70478923d771051268a5dabf91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7e7e92fbeea90cad8bf6f494b1a73712f79178e8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<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="1d3595836bd55b70478923d771051268a5dabf91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7e7e92fbeea90cad8bf6f494b1a73712f79178e8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
@ -132,7 +132,7 @@
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="4bebbe8d92368befc31e8b4a99da2d29cc26bfbc"/>
|
||||
<project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/>
|
||||
<project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="0c6a6547cd1fd302fa2b0f6e375654df36bf0ec4"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="2b62676f02abb7633aac619e0f92c7fd70216860"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd4fc430da93fad3123f0775791a919568aa0ca2"/>
|
||||
<project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="5f4b68c799927b6e078f987b12722c3a6ccd4a45"/>
|
||||
<project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
|
||||
<project name="android-sdk" path="sdk" remote="b2g" revision="0951179277915335251c5e11d242e4e1a8c2236f"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="07c383a786f188904311a37f6062c2cb84c9b61d">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d3595836bd55b70478923d771051268a5dabf91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7e7e92fbeea90cad8bf6f494b1a73712f79178e8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
@ -142,11 +142,9 @@
|
||||
<!-- Emulator specific things -->
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="fe7df1bc8dd0fd71571505d7be1c31a4ad1e40fb"/>
|
||||
<project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="48132ec0b0dfe9fc29c7c3f0e799066be8999198"/>
|
||||
<!-- external/qemu for emulator-l need to be updated in bug-1121378 -->
|
||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="59e434cbecc02653f44cedeb2ef5cc88dc8bb61b"/>
|
||||
<project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="cbda29a58abc4ea1f7f4611fe354ab67b606219d"/>
|
||||
<project name="platform/development" path="development" revision="0c51f6e0aa2ee57fcb75ec3b2ff6bf754cece63e"/>
|
||||
<project name="android-sdk" path="sdk" remote="b2g" revision="ff4190dc603f62a7caa48342aa268acf99863c5c"/>
|
||||
<!-- hardware-ril for emulator-l need to be updated in bug-1113054 -->
|
||||
<project name="platform/hardware/ril" path="hardware/ril" revision="e00d716e7e3d31729f75399855b6921e90cb0b66"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="2210a0276fa000ef7224f26b24f00cb34a372e8d"/>
|
||||
</manifest>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d3595836bd55b70478923d771051268a5dabf91"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="7e7e92fbeea90cad8bf6f494b1a73712f79178e8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<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="1d3595836bd55b70478923d771051268a5dabf91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7e7e92fbeea90cad8bf6f494b1a73712f79178e8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "1d3595836bd55b70478923d771051268a5dabf91",
|
||||
"git_revision": "7e7e92fbeea90cad8bf6f494b1a73712f79178e8",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "552e56f79bba1e2f7cd392361dfb0a8552176be8",
|
||||
"revision": "ad038c34edaef294c0b92f4c5f665c81c98c052a",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
</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="1d3595836bd55b70478923d771051268a5dabf91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7e7e92fbeea90cad8bf6f494b1a73712f79178e8"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="07c383a786f188904311a37f6062c2cb84c9b61d">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1d3595836bd55b70478923d771051268a5dabf91"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="7e7e92fbeea90cad8bf6f494b1a73712f79178e8"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
20
configure.in
20
configure.in
@ -74,7 +74,7 @@ GNOMEUI_VERSION=2.2.0
|
||||
GCONF_VERSION=1.2.1
|
||||
STARTUP_NOTIFICATION_VERSION=0.8
|
||||
DBUS_VERSION=0.60
|
||||
SQLITE_VERSION=3.8.10.1
|
||||
SQLITE_VERSION=3.8.11.1
|
||||
|
||||
MSMANIFEST_TOOL=
|
||||
|
||||
@ -230,15 +230,12 @@ if test -n "$gonkdir" ; then
|
||||
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 -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"
|
||||
GONK_INCLUDES="$GONK_INCLUDES -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib"
|
||||
MOZ_B2G_BT=1
|
||||
MOZ_B2G_BT_BLUEZ=1
|
||||
elif test -d "$gonkdir/external/bluetooth/bluedroid"; then
|
||||
elif test -d "$gonkdir/system/bluetoothd"; then
|
||||
MOZ_B2G_BT=1
|
||||
MOZ_B2G_BT_BLUEDROID=1
|
||||
if test -d "$gonkdir/system/bluetoothd"; then
|
||||
MOZ_B2G_BT_DAEMON=1
|
||||
fi
|
||||
MOZ_B2G_BT_DAEMON=1
|
||||
fi
|
||||
|
||||
MOZ_RTSP=1
|
||||
@ -249,15 +246,14 @@ if test -n "$gonkdir" ; then
|
||||
MOZ_OMX_ENCODER=1
|
||||
AC_SUBST(MOZ_OMX_ENCODER)
|
||||
AC_DEFINE(MOZ_OMX_ENCODER)
|
||||
MOZ_FMP4=1
|
||||
MOZ_FMP4=1
|
||||
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 -I$gonkdir/external/mdnsresponder/mDNSShared"
|
||||
MOZ_B2G_CAMERA=1
|
||||
MOZ_B2G_BT=1
|
||||
MOZ_B2G_BT_BLUEDROID=1
|
||||
if test -d "$gonkdir/system/bluetoothd"; then
|
||||
MOZ_B2G_BT=1
|
||||
MOZ_B2G_BT_DAEMON=1
|
||||
fi
|
||||
MOZ_NFC=1
|
||||
@ -281,9 +277,8 @@ if test -n "$gonkdir" ; then
|
||||
AC_DEFINE(MOZ_AUDIO_OFFLOAD)
|
||||
MOZ_FMP4=
|
||||
MOZ_B2G_CAMERA=1
|
||||
MOZ_B2G_BT=1
|
||||
MOZ_B2G_BT_BLUEDROID=1
|
||||
if test -d "$gonkdir/system/bluetoothd"; then
|
||||
MOZ_B2G_BT=1
|
||||
MOZ_B2G_BT_DAEMON=1
|
||||
fi
|
||||
MOZ_NFC=1
|
||||
@ -7605,7 +7600,6 @@ if test -n "$MOZ_B2G_BT"; then
|
||||
fi
|
||||
AC_SUBST(MOZ_B2G_BT)
|
||||
AC_SUBST(MOZ_B2G_BT_BLUEZ)
|
||||
AC_SUBST(MOZ_B2G_BT_BLUEDROID)
|
||||
AC_SUBST(MOZ_B2G_BT_DAEMON)
|
||||
|
||||
dnl ========================================================
|
||||
|
14550
db/sqlite3/src/sqlite3.c
14550
db/sqlite3/src/sqlite3.c
File diff suppressed because it is too large
Load Diff
@ -23,7 +23,7 @@
|
||||
**
|
||||
** The official C-language API documentation for SQLite is derived
|
||||
** from comments in this file. This file is the authoritative source
|
||||
** on how SQLite interfaces are suppose to operate.
|
||||
** on how SQLite interfaces are supposed to operate.
|
||||
**
|
||||
** The name of this file under configuration management is "sqlite.h.in".
|
||||
** The makefile makes some minor changes to this file (such as inserting
|
||||
@ -111,9 +111,9 @@ extern "C" {
|
||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||
** [sqlite_version()] and [sqlite_source_id()].
|
||||
*/
|
||||
#define SQLITE_VERSION "3.8.10.1"
|
||||
#define SQLITE_VERSION_NUMBER 3008010
|
||||
#define SQLITE_SOURCE_ID "2015-05-09 12:14:55 05b4b1f2a937c06c90db70c09890038f6c98ec40"
|
||||
#define SQLITE_VERSION "3.8.11.1"
|
||||
#define SQLITE_VERSION_NUMBER 3008011
|
||||
#define SQLITE_SOURCE_ID "2015-07-29 20:00:57 cf538e2783e468bbc25e7cb2a9ee64d3e0e80b2f"
|
||||
|
||||
/*
|
||||
** CAPI3REF: Run-Time Library Version Numbers
|
||||
@ -963,6 +963,14 @@ struct sqlite3_io_methods {
|
||||
** circumstances in order to fix a problem with priority inversion.
|
||||
** Applications should <em>not</em> use this file-control.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_ZIPVFS]]
|
||||
** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other
|
||||
** VFS should return SQLITE_NOTFOUND for this opcode.
|
||||
**
|
||||
** <li>[[SQLITE_FCNTL_RBU]]
|
||||
** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by
|
||||
** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for
|
||||
** this opcode.
|
||||
** </ul>
|
||||
*/
|
||||
#define SQLITE_FCNTL_LOCKSTATE 1
|
||||
@ -988,6 +996,8 @@ struct sqlite3_io_methods {
|
||||
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
|
||||
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
|
||||
#define SQLITE_FCNTL_WAL_BLOCK 24
|
||||
#define SQLITE_FCNTL_ZIPVFS 25
|
||||
#define SQLITE_FCNTL_RBU 26
|
||||
|
||||
/* deprecated names */
|
||||
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
||||
@ -3390,7 +3400,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt*);
|
||||
** Some interfaces require a protected sqlite3_value. Other interfaces
|
||||
** will accept either a protected or an unprotected sqlite3_value.
|
||||
** Every interface that accepts sqlite3_value arguments specifies
|
||||
** whether or not it requires a protected sqlite3_value.
|
||||
** whether or not it requires a protected sqlite3_value. The
|
||||
** [sqlite3_value_dup()] interface can be used to construct a new
|
||||
** protected sqlite3_value from an unprotected sqlite3_value.
|
||||
**
|
||||
** The terms "protected" and "unprotected" refer to whether or not
|
||||
** a mutex is held. An internal mutex is held for a protected
|
||||
@ -3550,6 +3562,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char
|
||||
void(*)(void*), unsigned char encoding);
|
||||
SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
|
||||
SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
|
||||
SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Number Of SQL Parameters
|
||||
@ -3893,8 +3906,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt);
|
||||
** KEYWORDS: {column access functions}
|
||||
** METHOD: sqlite3_stmt
|
||||
**
|
||||
** These routines form the "result set" interface.
|
||||
**
|
||||
** ^These routines return information about a single column of the current
|
||||
** result row of a query. ^In every case the first argument is a pointer
|
||||
** to the [prepared statement] that is being evaluated (the [sqlite3_stmt*]
|
||||
@ -3954,13 +3965,14 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt);
|
||||
** even empty strings, are always zero-terminated. ^The return
|
||||
** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
|
||||
**
|
||||
** ^The object returned by [sqlite3_column_value()] is an
|
||||
** [unprotected sqlite3_value] object. An unprotected sqlite3_value object
|
||||
** may only be used with [sqlite3_bind_value()] and [sqlite3_result_value()].
|
||||
** <b>Warning:</b> ^The object returned by [sqlite3_column_value()] is an
|
||||
** [unprotected sqlite3_value] object. In a multithreaded environment,
|
||||
** an unprotected sqlite3_value object may only be used safely with
|
||||
** [sqlite3_bind_value()] and [sqlite3_result_value()].
|
||||
** If the [unprotected sqlite3_value] object returned by
|
||||
** [sqlite3_column_value()] is used in any other way, including calls
|
||||
** to routines like [sqlite3_value_int()], [sqlite3_value_text()],
|
||||
** or [sqlite3_value_bytes()], then the behavior is undefined.
|
||||
** or [sqlite3_value_bytes()], the behavior is not threadsafe.
|
||||
**
|
||||
** These routines attempt to convert the value where appropriate. ^For
|
||||
** example, if the internal representation is FLOAT and a text result
|
||||
@ -3991,12 +4003,6 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt);
|
||||
** </table>
|
||||
** </blockquote>)^
|
||||
**
|
||||
** The table above makes reference to standard C library functions atoi()
|
||||
** and atof(). SQLite does not really use these functions. It has its
|
||||
** own equivalent internal routines. The atoi() and atof() names are
|
||||
** used in the table for brevity and because they are familiar to most
|
||||
** C programmers.
|
||||
**
|
||||
** Note that when type conversions occur, pointers returned by prior
|
||||
** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or
|
||||
** sqlite3_column_text16() may be invalidated.
|
||||
@ -4021,7 +4027,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt);
|
||||
** of conversion are done in place when it is possible, but sometimes they
|
||||
** are not possible and in those cases prior pointers are invalidated.
|
||||
**
|
||||
** The safest and easiest to remember policy is to invoke these routines
|
||||
** The safest policy is to invoke these routines
|
||||
** in one of the following ways:
|
||||
**
|
||||
** <ul>
|
||||
@ -4041,7 +4047,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt);
|
||||
** ^The pointers returned are valid until a type conversion occurs as
|
||||
** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
|
||||
** [sqlite3_finalize()] is called. ^The memory space used to hold strings
|
||||
** and BLOBs is freed automatically. Do <b>not</b> pass the pointers returned
|
||||
** and BLOBs is freed automatically. Do <em>not</em> pass the pointers returned
|
||||
** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
|
||||
** [sqlite3_free()].
|
||||
**
|
||||
@ -4291,12 +4297,12 @@ SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(voi
|
||||
#endif
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtaining SQL Function Parameter Values
|
||||
** CAPI3REF: Obtaining SQL Values
|
||||
** METHOD: sqlite3_value
|
||||
**
|
||||
** The C-language implementation of SQL functions and aggregates uses
|
||||
** this set of interface routines to access the parameter values on
|
||||
** the function or aggregate.
|
||||
** the function or aggregate.
|
||||
**
|
||||
** The xFunc (for scalar functions) or xStep (for aggregates) parameters
|
||||
** to [sqlite3_create_function()] and [sqlite3_create_function16()]
|
||||
@ -4349,6 +4355,23 @@ SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value*);
|
||||
SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value*);
|
||||
SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Copy And Free SQL Values
|
||||
** METHOD: sqlite3_value
|
||||
**
|
||||
** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value]
|
||||
** object D and returns a pointer to that copy. ^The [sqlite3_value] returned
|
||||
** is a [protected sqlite3_value] object even if the input is not.
|
||||
** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a
|
||||
** memory allocation fails.
|
||||
**
|
||||
** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object
|
||||
** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer
|
||||
** then sqlite3_value_free(V) is a harmless no-op.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL sqlite3_value *SQLITE_STDCALL sqlite3_value_dup(const sqlite3_value*);
|
||||
SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_value_free(sqlite3_value*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Obtain Aggregate Function Context
|
||||
** METHOD: sqlite3_context
|
||||
@ -4512,9 +4535,9 @@ typedef void (*sqlite3_destructor_type)(void*);
|
||||
** to by the second parameter and which is N bytes long where N is the
|
||||
** third parameter.
|
||||
**
|
||||
** ^The sqlite3_result_zeroblob() interfaces set the result of
|
||||
** the application-defined function to be a BLOB containing all zero
|
||||
** bytes and N bytes in size, where N is the value of the 2nd parameter.
|
||||
** ^The sqlite3_result_zeroblob(C,N) and sqlite3_result_zeroblob64(C,N)
|
||||
** interfaces set the result of the application-defined function to be
|
||||
** a BLOB containing all zero bytes and N bytes in size.
|
||||
**
|
||||
** ^The sqlite3_result_double() interface sets the result from
|
||||
** an application-defined function to be a floating point value specified
|
||||
@ -4596,7 +4619,7 @@ typedef void (*sqlite3_destructor_type)(void*);
|
||||
** from [sqlite3_malloc()] before it returns.
|
||||
**
|
||||
** ^The sqlite3_result_value() interface sets the result of
|
||||
** the application-defined function to be a copy the
|
||||
** the application-defined function to be a copy of the
|
||||
** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The
|
||||
** sqlite3_result_value() interface makes a copy of the [sqlite3_value]
|
||||
** so that the [sqlite3_value] specified in the parameter may change or
|
||||
@ -4629,6 +4652,7 @@ SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const v
|
||||
SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
|
||||
SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*);
|
||||
SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n);
|
||||
SQLITE_API int SQLITE_STDCALL sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Define New Collating Sequences
|
||||
@ -5872,7 +5896,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_blob_open(
|
||||
**
|
||||
** ^This function sets the database handle error code and message.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
|
||||
SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Close A BLOB Handle
|
||||
@ -6269,6 +6293,9 @@ SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*);
|
||||
#define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */
|
||||
#define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */
|
||||
#define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */
|
||||
#define SQLITE_MUTEX_STATIC_VFS1 11 /* For use by built-in VFS */
|
||||
#define SQLITE_MUTEX_STATIC_VFS2 12 /* For use by extension VFS */
|
||||
#define SQLITE_MUTEX_STATIC_VFS3 13 /* For use by application VFS */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Retrieve the mutex for a database connection
|
||||
@ -7682,7 +7709,7 @@ SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *);
|
||||
**
|
||||
** See also: [sqlite3_stmt_scanstatus_reset()]
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_stmt_scanstatus(
|
||||
SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus(
|
||||
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
|
||||
int idx, /* Index of loop to report on */
|
||||
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
|
||||
@ -7698,7 +7725,7 @@ SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_stmt_scanstatus(
|
||||
** This API is only available if the library is built with pre-processor
|
||||
** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
|
||||
*/
|
||||
SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
|
||||
SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
|
||||
|
||||
|
||||
/*
|
||||
@ -7813,6 +7840,8 @@ struct sqlite3_rtree_query_info {
|
||||
int eParentWithin; /* Visibility of parent node */
|
||||
int eWithin; /* OUT: Visiblity */
|
||||
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
|
||||
/* The following fields are only available in 3.8.11 and later */
|
||||
sqlite3_value **apSqlParam; /* Original SQL values of parameters */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "nsIDOMStorage.h"
|
||||
#include "nsIContentViewer.h"
|
||||
#include "nsIDocumentLoaderFactory.h"
|
||||
#include "nsIMozBrowserFrame.h"
|
||||
#include "nsCURILoader.h"
|
||||
#include "nsDocShellCID.h"
|
||||
#include "nsDOMCID.h"
|
||||
@ -10402,6 +10403,36 @@ nsDocShell::DoURILoad(nsIURI* aURI,
|
||||
}
|
||||
}
|
||||
|
||||
// For mozWidget, display a load error if we navigate to a page which is not
|
||||
// claimed in |widgetPages|.
|
||||
if (mScriptGlobal) {
|
||||
// When we go to display a load error for an invalid mozWidget page, we will
|
||||
// try to load an about:neterror page, which is also an invalid mozWidget
|
||||
// page. To avoid recursion, we skip this check if aURI's scheme is "about".
|
||||
|
||||
// The goal is to prevent leaking sensitive information of an invalid page of
|
||||
// an app, so allowing about:blank would not be conflict to the goal.
|
||||
bool isAbout = false;
|
||||
rv = aURI->SchemeIs("about", &isAbout);
|
||||
if (NS_SUCCEEDED(rv) && !isAbout &&
|
||||
nsIDocShell::GetIsApp()) {
|
||||
nsCOMPtr<Element> frameElement = mScriptGlobal->GetFrameElementInternal();
|
||||
if (frameElement) {
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(frameElement);
|
||||
// |GetReallyIsApp| indicates the browser frame is a valid app or widget.
|
||||
// Here we prevent navigating to an app or widget which loses its validity
|
||||
// by loading invalid page or other way.
|
||||
if (browserFrame && !browserFrame->GetReallyIsApp()) {
|
||||
nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
|
||||
if (serv) {
|
||||
serv->NotifyObservers(GetDocument(), "invalid-widget", nullptr);
|
||||
}
|
||||
return NS_ERROR_MALFORMED_URI;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// open a channel for the url
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "nsIDocument.h" // For nsIDocument
|
||||
#include "nsIPresShell.h" // For nsIPresShell
|
||||
#include "nsLayoutUtils.h" // For PostRestyleEvent (remove after bug 1073336)
|
||||
#include "nsThreadUtils.h" // For nsRunnableMethod and nsRevocableEventPtr
|
||||
#include "PendingAnimationTracker.h" // For PendingAnimationTracker
|
||||
|
||||
namespace mozilla {
|
||||
@ -70,7 +71,7 @@ Animation::SetTimeline(AnimationTimeline* aTimeline)
|
||||
|
||||
// FIXME(spec): Once we implement the seeking defined in the spec
|
||||
// surely this should be SeekFlag::DidSeek but the spec says otherwise.
|
||||
UpdateTiming(SeekFlag::NoSeek);
|
||||
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
|
||||
|
||||
// FIXME: When we expose this method to script we'll need to call PostUpdate
|
||||
// (but *not* when this method gets called from style).
|
||||
@ -107,7 +108,7 @@ Animation::SetStartTime(const Nullable<TimeDuration>& aNewStartTime)
|
||||
mReady->MaybeResolve(this);
|
||||
}
|
||||
|
||||
UpdateTiming(SeekFlag::NoSeek);
|
||||
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
|
||||
PostUpdate();
|
||||
}
|
||||
|
||||
@ -148,7 +149,7 @@ Animation::SetCurrentTime(const TimeDuration& aSeekTime)
|
||||
CancelPendingTasks();
|
||||
}
|
||||
|
||||
UpdateTiming(SeekFlag::DidSeek);
|
||||
UpdateTiming(SeekFlag::DidSeek, SyncNotifyFlag::Async);
|
||||
PostUpdate();
|
||||
}
|
||||
|
||||
@ -208,8 +209,8 @@ Animation::GetFinished(ErrorResult& aRv)
|
||||
}
|
||||
if (!mFinished) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
} else if (PlayState() == AnimationPlayState::Finished) {
|
||||
mFinished->MaybeResolve(this);
|
||||
} else if (mFinishedIsResolved) {
|
||||
MaybeResolveFinishedPromise();
|
||||
}
|
||||
return mFinished;
|
||||
}
|
||||
@ -234,7 +235,7 @@ Animation::Finish(ErrorResult& aRv)
|
||||
TimeDuration limit =
|
||||
mPlaybackRate > 0 ? TimeDuration(EffectEnd()) : TimeDuration(0);
|
||||
|
||||
SetCurrentTime(limit);
|
||||
SilentlySetCurrentTime(limit);
|
||||
|
||||
// If we are paused or play-pending we need to fill in the start time in
|
||||
// order to transition to the finished state.
|
||||
@ -250,18 +251,22 @@ Animation::Finish(ErrorResult& aRv)
|
||||
limit.MultDouble(1.0 / mPlaybackRate));
|
||||
}
|
||||
|
||||
// If we just resolved the start time for a pause-pending animation, we need
|
||||
// to clear the task. We don't do this as a branch of the above however since
|
||||
// we can have a play-pending animation with a resolved start time if we
|
||||
// aborted a pause operation.
|
||||
if (mPendingState == PendingState::PlayPending &&
|
||||
!mStartTime.IsNull()) {
|
||||
// If we just resolved the start time for a pause or play-pending
|
||||
// animation, we need to clear the task. We don't do this as a branch of
|
||||
// the above however since we can have a play-pending animation with a
|
||||
// resolved start time if we aborted a pause operation.
|
||||
if (!mStartTime.IsNull() &&
|
||||
(mPendingState == PendingState::PlayPending ||
|
||||
mPendingState == PendingState::PausePending)) {
|
||||
if (mPendingState == PendingState::PausePending) {
|
||||
mHoldTime.SetNull();
|
||||
}
|
||||
CancelPendingTasks();
|
||||
if (mReady) {
|
||||
mReady->MaybeResolve(this);
|
||||
}
|
||||
}
|
||||
UpdateTiming(SeekFlag::DidSeek);
|
||||
UpdateTiming(SeekFlag::DidSeek, SyncNotifyFlag::Sync);
|
||||
PostUpdate();
|
||||
}
|
||||
|
||||
@ -357,7 +362,7 @@ Animation::Tick()
|
||||
FinishPendingAt(mTimeline->GetCurrentTime().Value());
|
||||
}
|
||||
|
||||
UpdateTiming(SeekFlag::NoSeek);
|
||||
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
|
||||
}
|
||||
|
||||
void
|
||||
@ -464,13 +469,12 @@ Animation::DoCancel()
|
||||
if (mFinished) {
|
||||
mFinished->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
|
||||
}
|
||||
// Clear finished promise. We'll create a new one lazily.
|
||||
mFinished = nullptr;
|
||||
ResetFinishedPromise();
|
||||
|
||||
mHoldTime.SetNull();
|
||||
mStartTime.SetNull();
|
||||
|
||||
UpdateTiming(SeekFlag::NoSeek);
|
||||
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
|
||||
}
|
||||
|
||||
void
|
||||
@ -602,7 +606,7 @@ Animation::ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
|
||||
mEffect->ComposeStyle(aStyleRule, aSetProperties);
|
||||
|
||||
if (updatedHoldTime) {
|
||||
UpdateTiming(SeekFlag::NoSeek);
|
||||
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
|
||||
}
|
||||
|
||||
mFinishedAtLastComposeStyle = (playState == AnimationPlayState::Finished);
|
||||
@ -681,7 +685,7 @@ Animation::DoPlay(ErrorResult& aRv, LimitBehavior aLimitBehavior)
|
||||
TriggerOnNextTick(Nullable<TimeDuration>());
|
||||
}
|
||||
|
||||
UpdateTiming(SeekFlag::NoSeek);
|
||||
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
|
||||
}
|
||||
|
||||
// http://w3c.github.io/web-animations/#pause-an-animation
|
||||
@ -732,7 +736,7 @@ Animation::DoPause(ErrorResult& aRv)
|
||||
TriggerOnNextTick(Nullable<TimeDuration>());
|
||||
}
|
||||
|
||||
UpdateTiming(SeekFlag::NoSeek);
|
||||
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
|
||||
}
|
||||
|
||||
void
|
||||
@ -760,7 +764,7 @@ Animation::ResumeAt(const TimeDuration& aReadyTime)
|
||||
}
|
||||
mPendingState = PendingState::NotPending;
|
||||
|
||||
UpdateTiming(SeekFlag::NoSeek);
|
||||
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
|
||||
|
||||
if (mReady) {
|
||||
mReady->MaybeResolve(this);
|
||||
@ -780,7 +784,7 @@ Animation::PauseAt(const TimeDuration& aReadyTime)
|
||||
mStartTime.SetNull();
|
||||
mPendingState = PendingState::NotPending;
|
||||
|
||||
UpdateTiming(SeekFlag::NoSeek);
|
||||
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
|
||||
|
||||
if (mReady) {
|
||||
mReady->MaybeResolve(this);
|
||||
@ -788,7 +792,7 @@ Animation::PauseAt(const TimeDuration& aReadyTime)
|
||||
}
|
||||
|
||||
void
|
||||
Animation::UpdateTiming(SeekFlag aSeekFlag)
|
||||
Animation::UpdateTiming(SeekFlag aSeekFlag, SyncNotifyFlag aSyncNotifyFlag)
|
||||
{
|
||||
// Update the sequence number each time we transition in or out of the
|
||||
// idle state
|
||||
@ -802,7 +806,7 @@ Animation::UpdateTiming(SeekFlag aSeekFlag)
|
||||
|
||||
// We call UpdateFinishedState before UpdateEffect because the former
|
||||
// can change the current time, which is used by the latter.
|
||||
UpdateFinishedState(aSeekFlag);
|
||||
UpdateFinishedState(aSeekFlag, aSyncNotifyFlag);
|
||||
UpdateEffect();
|
||||
|
||||
// Unconditionally Add/Remove from the timeline. This is ok because if the
|
||||
@ -842,7 +846,8 @@ Animation::UpdateTiming(SeekFlag aSeekFlag)
|
||||
}
|
||||
|
||||
void
|
||||
Animation::UpdateFinishedState(SeekFlag aSeekFlag)
|
||||
Animation::UpdateFinishedState(SeekFlag aSeekFlag,
|
||||
SyncNotifyFlag aSyncNotifyFlag)
|
||||
{
|
||||
Nullable<TimeDuration> currentTime = GetCurrentTime();
|
||||
TimeDuration effectEnd = TimeDuration(EffectEnd());
|
||||
@ -880,18 +885,14 @@ Animation::UpdateFinishedState(SeekFlag aSeekFlag)
|
||||
}
|
||||
|
||||
bool currentFinishedState = PlayState() == AnimationPlayState::Finished;
|
||||
if (currentFinishedState && !mIsPreviousStateFinished) {
|
||||
if (mFinished) {
|
||||
mFinished->MaybeResolve(this);
|
||||
}
|
||||
} else if (!currentFinishedState && mIsPreviousStateFinished) {
|
||||
// Clear finished promise. We'll create a new one lazily.
|
||||
mFinished = nullptr;
|
||||
if (currentFinishedState && !mFinishedIsResolved) {
|
||||
DoFinishNotification(aSyncNotifyFlag);
|
||||
} else if (!currentFinishedState && mFinishedIsResolved) {
|
||||
ResetFinishedPromise();
|
||||
if (mEffect->AsTransition()) {
|
||||
mEffect->SetIsFinishedTransition(false);
|
||||
}
|
||||
}
|
||||
mIsPreviousStateFinished = currentFinishedState;
|
||||
// We must recalculate the current time to take account of any mHoldTime
|
||||
// changes the code above made.
|
||||
mPreviousCurrentTime = GetCurrentTime();
|
||||
@ -1062,5 +1063,40 @@ Animation::GetCollection() const
|
||||
return manager->GetAnimations(targetElement, targetPseudoType, false);
|
||||
}
|
||||
|
||||
void
|
||||
Animation::DoFinishNotification(SyncNotifyFlag aSyncNotifyFlag)
|
||||
{
|
||||
if (aSyncNotifyFlag == SyncNotifyFlag::Sync) {
|
||||
MaybeResolveFinishedPromise();
|
||||
} else if (!mFinishNotificationTask.IsPending()) {
|
||||
nsRefPtr<nsRunnableMethod<Animation>> runnable =
|
||||
NS_NewRunnableMethod(this, &Animation::MaybeResolveFinishedPromise);
|
||||
Promise::DispatchToMicroTask(runnable);
|
||||
mFinishNotificationTask = runnable;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Animation::ResetFinishedPromise()
|
||||
{
|
||||
mFinishedIsResolved = false;
|
||||
mFinished = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Animation::MaybeResolveFinishedPromise()
|
||||
{
|
||||
mFinishNotificationTask.Revoke();
|
||||
|
||||
if (PlayState() != AnimationPlayState::Finished) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mFinished) {
|
||||
mFinished->MaybeResolve(this);
|
||||
}
|
||||
mFinishedIsResolved = true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -60,9 +60,9 @@ public:
|
||||
, mPendingState(PendingState::NotPending)
|
||||
, mSequenceNum(kUnsequenced)
|
||||
, mIsRunningOnCompositor(false)
|
||||
, mIsPreviousStateFinished(false)
|
||||
, mFinishedAtLastComposeStyle(false)
|
||||
, mIsRelevant(false)
|
||||
, mFinishedIsResolved(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -323,11 +323,21 @@ protected:
|
||||
DidSeek
|
||||
};
|
||||
|
||||
void UpdateTiming(SeekFlag aSeekFlag);
|
||||
void UpdateFinishedState(SeekFlag aSeekFlag);
|
||||
enum class SyncNotifyFlag {
|
||||
Sync,
|
||||
Async
|
||||
};
|
||||
|
||||
void UpdateTiming(SeekFlag aSeekFlag,
|
||||
SyncNotifyFlag aSyncNotifyFlag);
|
||||
void UpdateFinishedState(SeekFlag aSeekFlag,
|
||||
SyncNotifyFlag aSyncNotifyFlag);
|
||||
void UpdateEffect();
|
||||
void FlushStyle() const;
|
||||
void PostUpdate();
|
||||
void ResetFinishedPromise();
|
||||
void MaybeResolveFinishedPromise();
|
||||
void DoFinishNotification(SyncNotifyFlag aSyncNotifyFlag);
|
||||
|
||||
/**
|
||||
* Remove this animation from the pending animation tracker and reset
|
||||
@ -385,13 +395,17 @@ protected:
|
||||
uint64_t mSequenceNum;
|
||||
|
||||
bool mIsRunningOnCompositor;
|
||||
// Indicates whether we were in the finished state during our
|
||||
// most recent unthrottled sample (our last ComposeStyle call).
|
||||
bool mIsPreviousStateFinished; // Spec calls this "previous finished state"
|
||||
bool mFinishedAtLastComposeStyle;
|
||||
// Indicates that the animation should be exposed in an element's
|
||||
// getAnimations() list.
|
||||
bool mIsRelevant;
|
||||
|
||||
nsRevocableEventPtr<nsRunnableMethod<Animation>> mFinishNotificationTask;
|
||||
// True if mFinished is resolved or would be resolved if mFinished has
|
||||
// yet to be created. This is not set when mFinished is rejected since
|
||||
// in that case mFinished is immediately reset to represent a new current
|
||||
// finished promise.
|
||||
bool mFinishedIsResolved;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -239,6 +239,27 @@ async_test(function(t) {
|
||||
}));
|
||||
}, 'Test resetting of computed style');
|
||||
|
||||
async_test(function(t) {
|
||||
var div = addDiv(t, {'class': 'animated-div'});
|
||||
div.style.animation = ANIM_PROP_VAL;
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
var resolvedFinished = false;
|
||||
animation.finished.then(function() {
|
||||
resolvedFinished = true;
|
||||
});
|
||||
|
||||
animation.ready.then(function() {
|
||||
animation.finish();
|
||||
}).then(t.step_func(function() {
|
||||
assert_true(resolvedFinished,
|
||||
'Animation.finished should be resolved soon after ' +
|
||||
'Animation.finish()');
|
||||
t.done();
|
||||
}));
|
||||
|
||||
}, 'Test finish() resolves finished promise synchronously');
|
||||
|
||||
done();
|
||||
</script>
|
||||
</body>
|
||||
|
@ -405,6 +405,142 @@ async_test(function(t) {
|
||||
}));
|
||||
}, 'Test finished promise changes when animationPlayState set to running');
|
||||
|
||||
async_test(function(t) {
|
||||
var div = addDiv(t);
|
||||
div.style.animation = ANIM_PROP_VAL;
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
var previousFinishedPromise = animation.finished;
|
||||
|
||||
animation.currentTime = ANIM_DURATION;
|
||||
|
||||
animation.finished.then(t.step_func(function() {
|
||||
animation.currentTime = 0;
|
||||
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||
'Finished promise should change once a prior ' +
|
||||
'finished promise resolved and the animation ' +
|
||||
'falls out finished state');
|
||||
t.done();
|
||||
}));
|
||||
}, 'Test finished promise changes when a prior finished promise resolved ' +
|
||||
'and the animation falls out finished state');
|
||||
|
||||
async_test(function(t) {
|
||||
var div = addDiv(t);
|
||||
div.style.animation = ANIM_PROP_VAL;
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
var previousFinishedPromise = animation.finished;
|
||||
|
||||
animation.currentTime = ANIM_DURATION;
|
||||
animation.currentTime = ANIM_DURATION / 2;
|
||||
|
||||
assert_equals(animation.finished, previousFinishedPromise,
|
||||
'No new finished promise generated when finished state ' +
|
||||
'is checked asynchronously');
|
||||
t.done();
|
||||
}, 'Test no new finished promise generated when finished state ' +
|
||||
'is checked asynchronously');
|
||||
|
||||
async_test(function(t) {
|
||||
var div = addDiv(t);
|
||||
div.style.animation = ANIM_PROP_VAL;
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
var previousFinishedPromise = animation.finished;
|
||||
|
||||
animation.finish();
|
||||
animation.currentTime = ANIM_DURATION / 2;
|
||||
|
||||
assert_not_equals(animation.finished, previousFinishedPromise,
|
||||
'New finished promise generated when finished state ' +
|
||||
'is checked synchronously');
|
||||
t.done();
|
||||
}, 'Test new finished promise generated when finished state ' +
|
||||
'is checked synchronously');
|
||||
|
||||
async_test(function(t) {
|
||||
var div = addDiv(t);
|
||||
div.style.animation = ANIM_PROP_VAL;
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
var resolvedFinished = false;
|
||||
animation.finished.then(function() {
|
||||
resolvedFinished = true;
|
||||
});
|
||||
|
||||
animation.ready.then(function() {
|
||||
animation.finish();
|
||||
animation.currentTime = ANIM_DURATION / 2;
|
||||
}).then(t.step_func(function() {
|
||||
assert_true(resolvedFinished,
|
||||
'Animation.finished should be resolved even if ' +
|
||||
'the finished state is changed soon');
|
||||
t.done();
|
||||
}));
|
||||
|
||||
}, 'Test synchronous finished promise resolved even if finished state ' +
|
||||
'is changed soon');
|
||||
|
||||
async_test(function(t) {
|
||||
var div = addDiv(t);
|
||||
div.style.animation = ANIM_PROP_VAL;
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
var resolvedFinished = false;
|
||||
animation.finished.then(function() {
|
||||
resolvedFinished = true;
|
||||
});
|
||||
|
||||
animation.ready.then(t.step_func(function() {
|
||||
animation.currentTime = ANIM_DURATION;
|
||||
animation.finish();
|
||||
})).then(t.step_func(function() {
|
||||
assert_true(resolvedFinished,
|
||||
'Animation.finished should be resolved soon after finish() is ' +
|
||||
'called even if there are other asynchronous promises just before it');
|
||||
t.done();
|
||||
}));
|
||||
}, 'Test synchronous finished promise resolved even if asynchronous ' +
|
||||
'finished promise happens just before synchronous promise');
|
||||
|
||||
async_test(function(t) {
|
||||
var div = addDiv(t);
|
||||
div.style.animation = ANIM_PROP_VAL;
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
animation.finished.then(t.step_func(function() {
|
||||
assert_unreached('Animation.finished should not be resolved');
|
||||
}));
|
||||
|
||||
animation.ready.then(function() {
|
||||
animation.currentTime = ANIM_DURATION;
|
||||
animation.currentTime = ANIM_DURATION / 2;
|
||||
}).then(t.step_func(function() {
|
||||
t.done();
|
||||
}));
|
||||
}, 'Test finished promise is not resolved when the animation ' +
|
||||
'falls out finished state immediately');
|
||||
|
||||
async_test(function(t) {
|
||||
var div = addDiv(t);
|
||||
div.style.animation = ANIM_PROP_VAL;
|
||||
var animation = div.getAnimations()[0];
|
||||
|
||||
animation.ready.then(function() {
|
||||
animation.currentTime = ANIM_DURATION;
|
||||
animation.finished.then(t.step_func(function() {
|
||||
assert_unreached('Animation.finished should not be resolved');
|
||||
}));
|
||||
animation.currentTime = 0;
|
||||
}).then(t.step_func(function() {
|
||||
t.done();
|
||||
}));
|
||||
|
||||
}, 'Test finished promise is not resolved once the animation ' +
|
||||
'falls out finished state even though the current finished ' +
|
||||
'promise is generated soon after animation state became finished');
|
||||
|
||||
done();
|
||||
</script>
|
||||
</body>
|
||||
|
@ -1,10 +1,10 @@
|
||||
var gWidgetManifestURL = 'http://test/tests/dom/apps/tests/file_app.sjs?apptype=widget&getmanifest=true';
|
||||
var gInvalidWidgetManifestURL = 'http://test/tests/dom/apps/tests/file_app.sjs?apptype=invalidWidget&getmanifest=true';
|
||||
var gWidgetManifestURL = "http://test/tests/dom/apps/tests/file_app.sjs?apptype=widget&getmanifest=true";
|
||||
var gInvalidWidgetManifestURL = "http://test/tests/dom/apps/tests/file_app.sjs?apptype=invalidWidget&getmanifest=true";
|
||||
var gApp;
|
||||
var gHasBrowserPermission;
|
||||
|
||||
function onError() {
|
||||
ok(false, "Error callback invoked");
|
||||
function onError(msg) {
|
||||
ok(false, "Error callback invoked: " + msg);
|
||||
finish();
|
||||
}
|
||||
|
||||
@ -33,47 +33,63 @@ function uninstallApp() {
|
||||
function testApp(isValidWidget) {
|
||||
info("Test widget feature. IsValidWidget: " + isValidWidget);
|
||||
|
||||
var ifr = document.createElement('iframe');
|
||||
ifr.setAttribute('mozbrowser', 'true');
|
||||
ifr.setAttribute('mozwidget', gApp.manifestURL);
|
||||
ifr.setAttribute('src', gApp.origin+gApp.manifest.launch_path);
|
||||
var ifr = document.createElement("iframe");
|
||||
ifr.setAttribute("mozbrowser", "true");
|
||||
ifr.setAttribute("mozwidget", gApp.manifestURL);
|
||||
ifr.setAttribute("src", gApp.origin + gApp.manifest.launch_path);
|
||||
|
||||
var domParent = document.getElementById('container');
|
||||
var domParent = document.getElementById("container");
|
||||
domParent.appendChild(ifr);
|
||||
|
||||
var mm = SpecialPowers.getBrowserFrameMessageManager(ifr);
|
||||
mm.addMessageListener('OK', function(msg) {
|
||||
ok(isValidWidget, "Message from widget: " + SpecialPowers.wrap(msg).json);
|
||||
});
|
||||
mm.addMessageListener('KO', function(msg) {
|
||||
ok(!isValidWidget, "Message from widget: " + SpecialPowers.wrap(msg).json);
|
||||
});
|
||||
mm.addMessageListener('DONE', function(msg) {
|
||||
ok(true, "Message from widget complete: "+SpecialPowers.wrap(msg).json);
|
||||
domParent.removeChild(ifr);
|
||||
runTest();
|
||||
});
|
||||
|
||||
ifr.addEventListener('mozbrowserloadend', function() {
|
||||
ifr.addEventListener("mozbrowserloadend", function _onloadend() {
|
||||
ok(true, "receive mozbrowserloadend");
|
||||
|
||||
// Test limited browser API feature only for valid widget case
|
||||
if (isValidWidget) {
|
||||
testLimitedBrowserAPI(ifr);
|
||||
}
|
||||
SimpleTest.executeSoon(()=>loadFrameScript(mm));
|
||||
SimpleTest.executeSoon(() => loadFrameScript(mm,
|
||||
checkIsWidgetScript,
|
||||
true));
|
||||
}, false);
|
||||
|
||||
ifr.addEventListener("mozbrowsererror", (event) => {
|
||||
ok(!isValidWidget, "receive mozbrowsererror: " + JSON.stringify(event.detail));
|
||||
domParent.removeChild(ifr);
|
||||
runTest();
|
||||
});
|
||||
|
||||
// Callback of frameScript
|
||||
var mm = SpecialPowers.getBrowserFrameMessageManager(ifr);
|
||||
mm.addMessageListener("OK", function(msg) {
|
||||
ok(isValidWidget, "Message from widget: " + SpecialPowers.wrap(msg).json);
|
||||
});
|
||||
mm.addMessageListener("KO", function(msg) {
|
||||
ok(!isValidWidget, "Message from widget: " + SpecialPowers.wrap(msg).json);
|
||||
});
|
||||
mm.addMessageListener("DONE", function _done(msg) {
|
||||
ok(true, "Message from widget complete: " + SpecialPowers.wrap(msg).json);
|
||||
|
||||
mm.removeMessageListener("DONE", _done);
|
||||
mm.addMessageListener("DONE", function _done(msg) {
|
||||
ok(true, "Message from widget complete: " + SpecialPowers.wrap(msg).json);
|
||||
runTest();
|
||||
});
|
||||
|
||||
info("set src to a invalid page");
|
||||
ifr.setAttribute("src", gApp.origin);
|
||||
isValidWidget = false;
|
||||
});
|
||||
|
||||
// Test limited browser API feature only for valid widget case
|
||||
if (!isValidWidget) {
|
||||
return;
|
||||
}
|
||||
|
||||
[
|
||||
'mozbrowsertitlechange',
|
||||
'mozbrowseropenwindow',
|
||||
'mozbrowserscroll',
|
||||
'mozbrowserasyncscroll'
|
||||
"mozbrowsertitlechange",
|
||||
"mozbrowseropenwindow",
|
||||
"mozbrowserscroll",
|
||||
"mozbrowserasyncscroll"
|
||||
].forEach( function(topic) {
|
||||
ifr.addEventListener(topic, function() {
|
||||
ok(false, topic + " should be hidden");
|
||||
@ -83,19 +99,19 @@ function testApp(isValidWidget) {
|
||||
|
||||
function testLimitedBrowserAPI(ifr) {
|
||||
var securitySensitiveCalls = [
|
||||
{ api: 'sendMouseEvent' , args: ['mousedown', 0, 0, 0, 0, 0] },
|
||||
{ api: 'sendTouchEvent' , args: ['touchstart', [0], [0], [0], [1], [1], [0], [1], 1, 0] },
|
||||
{ api: 'goBack' , args: [] },
|
||||
{ api: 'goForward' , args: [] },
|
||||
{ api: 'reload' , args: [] },
|
||||
{ api: 'stop' , args: [] },
|
||||
{ api: 'download' , args: ['http://example.org'] },
|
||||
{ api: 'purgeHistory' , args: [] },
|
||||
{ api: 'getScreenshot' , args: [0, 0] },
|
||||
{ api: 'zoom' , args: [0.1] },
|
||||
{ api: 'getCanGoBack' , args: [] },
|
||||
{ api: 'getCanGoForward' , args: [] },
|
||||
{ api: 'getContentDimensions', args: [] }
|
||||
{ api: "sendMouseEvent" , args: ["mousedown", 0, 0, 0, 0, 0] },
|
||||
{ api: "sendTouchEvent" , args: ["touchstart", [0], [0], [0], [1], [1], [0], [1], 1, 0] },
|
||||
{ api: "goBack" , args: [] },
|
||||
{ api: "goForward" , args: [] },
|
||||
{ api: "reload" , args: [] },
|
||||
{ api: "stop" , args: [] },
|
||||
{ api: "download" , args: ["http://example.org"] },
|
||||
{ api: "purgeHistory" , args: [] },
|
||||
{ api: "getScreenshot" , args: [0, 0] },
|
||||
{ api: "zoom" , args: [0.1] },
|
||||
{ api: "getCanGoBack" , args: [] },
|
||||
{ api: "getCanGoForward" , args: [] },
|
||||
{ api: "getContentDimensions", args: [] }
|
||||
];
|
||||
securitySensitiveCalls.forEach( function(call) {
|
||||
if (gHasBrowserPermission) {
|
||||
@ -114,56 +130,51 @@ function testLimitedBrowserAPI(ifr) {
|
||||
});
|
||||
}
|
||||
|
||||
function loadFrameScript(mm) {
|
||||
var script = 'data:,\
|
||||
function ok(p, msg) { \
|
||||
if (p) { \
|
||||
sendAsyncMessage("OK", msg); \
|
||||
} else { \
|
||||
sendAsyncMessage("KO", msg); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
function is(a, b, msg) { \
|
||||
if (a == b) { \
|
||||
sendAsyncMessage("OK", a + " == " + b + " - " + msg); \
|
||||
} else { \
|
||||
sendAsyncMessage("KO", a + " != " + b + " - " + msg); \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
function finish() { \
|
||||
sendAsyncMessage("DONE",""); \
|
||||
} \
|
||||
\
|
||||
function onError() { \
|
||||
ok(false, "Error callback invoked"); \
|
||||
finish(); \
|
||||
} \
|
||||
\
|
||||
function checkWidget(widget) { \
|
||||
/*For invalid widget case, ignore the following check*/\
|
||||
if (widget) { \
|
||||
var widgetName = "Really Rapid Release (APPTYPETOKEN)"; \
|
||||
is(widget.origin, "http://test", "Widget origin should be correct"); \
|
||||
is(widget.installOrigin, "http://mochi.test:8888", "Install origin should be correct"); \
|
||||
} \
|
||||
finish(); \
|
||||
} \
|
||||
\
|
||||
var request = content.window.navigator.mozApps.getSelf(); \
|
||||
request.onsuccess = function() { \
|
||||
var widget = request.result; \
|
||||
ok(widget,"Should be a widget"); \
|
||||
checkWidget(widget); \
|
||||
}; \
|
||||
request.onerror = onError; \
|
||||
content.window.open("about:blank"); /*test mozbrowseropenwindow*/ \
|
||||
content.window.scrollTo(4000, 4000); /*test mozbrowser(async)scroll*/ \
|
||||
';
|
||||
function loadFrameScript(mm, frameScript, testMozbrowserEvent) {
|
||||
var script = "data:,(" + frameScript.toString() + ")(" + testMozbrowserEvent + ");";
|
||||
mm.loadFrameScript(script, /* allowDelayedLoad = */ false);
|
||||
}
|
||||
|
||||
function checkIsWidgetScript(testMozbrowserEvent) {
|
||||
function ok(p, msg) {
|
||||
if (p) {
|
||||
sendAsyncMessage("OK", msg);
|
||||
} else {
|
||||
sendAsyncMessage("KO", msg);
|
||||
}
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
if (a == b) {
|
||||
sendAsyncMessage("OK", a + " == " + b + " - " + msg);
|
||||
} else {
|
||||
sendAsyncMessage("KO", a + " != " + b + " - " + msg);
|
||||
}
|
||||
}
|
||||
|
||||
function finish() {
|
||||
sendAsyncMessage("DONE", "");
|
||||
}
|
||||
|
||||
function onError() {
|
||||
ok(false, "Error callback invoked");
|
||||
finish();
|
||||
}
|
||||
|
||||
var request = content.window.navigator.mozApps.getSelf();
|
||||
request.onsuccess = function() {
|
||||
var widget = request.result;
|
||||
ok(widget, "Should" + (widget ? "" : " not") + " be a widget");
|
||||
finish();
|
||||
};
|
||||
request.onerror = onError;
|
||||
|
||||
if (testMozbrowserEvent) {
|
||||
content.window.open("about:blank"); /* test mozbrowseropenwindow */
|
||||
content.window.scrollTo(4000, 4000); /* test mozbrowser(async)scroll */
|
||||
}
|
||||
}
|
||||
|
||||
var tests = [
|
||||
// Permissions
|
||||
function() {
|
||||
@ -176,22 +187,12 @@ var tests = [
|
||||
// Preferences
|
||||
function() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.mozBrowserFramesEnabled", true],
|
||||
["dom.enable_widgets", true],
|
||||
["dom.datastore.sysMsgOnChangeShortTimeoutSec", 1],
|
||||
["dom.datastore.sysMsgOnChangeLongTimeoutSec", 3]]}, runTest);
|
||||
},
|
||||
|
||||
function() {
|
||||
if (SpecialPowers.isMainProcess()) {
|
||||
SpecialPowers.Cu.import("resource://gre/modules/DataStoreChangeNotifier.jsm");
|
||||
}
|
||||
|
||||
SpecialPowers.setAllAppsLaunchable(true);
|
||||
runTest();
|
||||
["dom.enable_widgets", true]]}, runTest);
|
||||
},
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.setAllAppsLaunchable(true);
|
||||
SpecialPowers.autoConfirmAppInstall(() => {
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest);
|
||||
});
|
||||
|
@ -1928,7 +1928,7 @@ nsAttrValue::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
//n += container->mCSSStyleRule->SizeOfIncludingThis(aMallocSizeOf);
|
||||
} else if (Type() == eAtomArray && container->mValue.mAtomArray) {
|
||||
// Don't measure each nsIAtom, they are measured separatly.
|
||||
n += container->mValue.mAtomArray->SizeOfIncludingThis(aMallocSizeOf);
|
||||
n += container->mValue.mAtomArray->ShallowSizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -112,9 +112,9 @@ const size_t gStackSize = 8192;
|
||||
|
||||
#define NS_FULL_GC_DELAY 60000 // ms
|
||||
|
||||
// The amount of time to wait from the user being idle to starting a shrinking
|
||||
// GC.
|
||||
#define NS_SHRINKING_GC_DELAY 15000 // ms
|
||||
// The default amount of time to wait from the user being idle to starting a
|
||||
// shrinking GC.
|
||||
#define NS_DEAULT_INACTIVE_GC_DELAY 300000 // ms
|
||||
|
||||
// Maximum amount of time that should elapse between incremental GC slices
|
||||
#define NS_INTERSLICE_GC_DELAY 100 // ms
|
||||
@ -221,6 +221,7 @@ static bool sGCOnMemoryPressure;
|
||||
// after NS_SHRINKING_GC_DELAY ms later, if the appropriate pref is set.
|
||||
|
||||
static bool sCompactOnUserInactive;
|
||||
static uint32_t sCompactOnUserInactiveDelay = NS_DEAULT_INACTIVE_GC_DELAY;
|
||||
static bool sIsCompactingOnUserInactive = false;
|
||||
|
||||
// In testing, we call RunNextCollectorTimer() to ensure that the collectors are run more
|
||||
@ -2097,7 +2098,7 @@ nsJSContext::PokeShrinkingGC()
|
||||
}
|
||||
|
||||
sShrinkingGCTimer->InitWithFuncCallback(ShrinkingGCTimerFired, nullptr,
|
||||
NS_SHRINKING_GC_DELAY,
|
||||
sCompactOnUserInactiveDelay,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
}
|
||||
|
||||
@ -2855,6 +2856,10 @@ nsJSContext::EnsureStatics()
|
||||
"javascript.options.compact_on_user_inactive",
|
||||
true);
|
||||
|
||||
Preferences::AddUintVarCache(&sCompactOnUserInactiveDelay,
|
||||
"javascript.options.compact_on_user_inactive_delay",
|
||||
NS_DEAULT_INACTIVE_GC_DELAY);
|
||||
|
||||
nsIObserver* observer = new nsJSEnvironmentObserver();
|
||||
obs->AddObserver(observer, "memory-pressure", false);
|
||||
obs->AddObserver(observer, "user-interaction-inactive", false);
|
||||
|
@ -2952,14 +2952,6 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
|
||||
if (scheme.LowerCaseEqualsLiteral("app") ||
|
||||
scheme.LowerCaseEqualsLiteral("jar")) {
|
||||
mIsMappedArrayBuffer = true;
|
||||
if (!XRE_IsParentProcess()) {
|
||||
nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(mChannel);
|
||||
// For memory mapping from child process, we need to get file
|
||||
// descriptor of the JAR file opened remotely on the parent proess.
|
||||
// Set this to make sure that file descriptor can be obtained by
|
||||
// child process.
|
||||
jarChannel->EnsureChildFd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,6 @@
|
||||
#if ANDROID_VERSION >= 17
|
||||
#include <cutils/properties.h>
|
||||
#endif
|
||||
#ifdef MOZ_B2G_BT_BLUEDROID
|
||||
#include "BluetoothHALInterface.h"
|
||||
#endif
|
||||
#ifdef MOZ_B2G_BT_DAEMON
|
||||
#include "BluetoothDaemonInterface.h"
|
||||
#endif
|
||||
@ -146,9 +143,6 @@ BluetoothInterface::GetInstance()
|
||||
static const char* const sDefaultBackend[] = {
|
||||
#ifdef MOZ_B2G_BT_DAEMON
|
||||
"bluetoothd",
|
||||
#endif
|
||||
#ifdef MOZ_B2G_BT_BLUEDROID
|
||||
"bluedroid",
|
||||
#endif
|
||||
nullptr // no default backend; must be final element in array
|
||||
};
|
||||
@ -186,11 +180,6 @@ BluetoothInterface::GetInstance()
|
||||
* correct one at runtime is also an option.
|
||||
*/
|
||||
|
||||
#ifdef MOZ_B2G_BT_BLUEDROID
|
||||
if (backend.LowerCaseEqualsLiteral("bluedroid")) {
|
||||
return BluetoothHALInterface::GetInstance();
|
||||
} else
|
||||
#endif
|
||||
#ifdef MOZ_B2G_BT_DAEMON
|
||||
if (backend.LowerCaseEqualsLiteral("bluetoothd")) {
|
||||
return BluetoothDaemonInterface::GetInstance();
|
||||
|
@ -1,28 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BluetoothInterfaceHelpers.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
//
|
||||
// Conversion
|
||||
//
|
||||
|
||||
nsresult
|
||||
Convert(nsresult aIn, BluetoothStatus& aOut)
|
||||
{
|
||||
if (NS_SUCCEEDED(aIn)) {
|
||||
aOut = STATUS_SUCCESS;
|
||||
} else if (aIn == NS_ERROR_OUT_OF_MEMORY) {
|
||||
aOut = STATUS_NOMEM;
|
||||
} else {
|
||||
aOut = STATUS_FAIL;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
@ -1,98 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_bluetooth_bluetoothinterfacehelpers_h
|
||||
#define mozilla_dom_bluetooth_bluetoothinterfacehelpers_h
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
//
|
||||
// Conversion
|
||||
//
|
||||
|
||||
nsresult
|
||||
Convert(nsresult aIn, BluetoothStatus& aOut);
|
||||
|
||||
//
|
||||
// Init operators
|
||||
//
|
||||
// Below are general-purpose init operators for Bluetooth. The classes
|
||||
// of type |ConstantInitOp[1..3]| initialize results or notifications
|
||||
// with constant values.
|
||||
//
|
||||
|
||||
template <typename T1>
|
||||
class ConstantInitOp1 final
|
||||
{
|
||||
public:
|
||||
ConstantInitOp1(const T1& aArg1)
|
||||
: mArg1(aArg1)
|
||||
{ }
|
||||
|
||||
nsresult operator () (T1& aArg1) const
|
||||
{
|
||||
aArg1 = mArg1;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
const T1& mArg1;
|
||||
};
|
||||
|
||||
template <typename T1, typename T2>
|
||||
class ConstantInitOp2 final
|
||||
{
|
||||
public:
|
||||
ConstantInitOp2(const T1& aArg1, const T2& aArg2)
|
||||
: mArg1(aArg1)
|
||||
, mArg2(aArg2)
|
||||
{ }
|
||||
|
||||
nsresult operator () (T1& aArg1, T2& aArg2) const
|
||||
{
|
||||
aArg1 = mArg1;
|
||||
aArg2 = mArg2;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
const T1& mArg1;
|
||||
const T2& mArg2;
|
||||
};
|
||||
|
||||
template <typename T1, typename T2, typename T3>
|
||||
class ConstantInitOp3 final
|
||||
{
|
||||
public:
|
||||
ConstantInitOp3(const T1& aArg1, const T2& aArg2, const T3& aArg3)
|
||||
: mArg1(aArg1)
|
||||
, mArg2(aArg2)
|
||||
, mArg3(aArg3)
|
||||
{ }
|
||||
|
||||
nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3) const
|
||||
{
|
||||
aArg1 = mArg1;
|
||||
aArg2 = mArg2;
|
||||
aArg3 = mArg3;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
const T1& mArg1;
|
||||
const T2& mArg2;
|
||||
const T3& mArg3;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,203 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BluetoothA2dpHALInterface.h"
|
||||
#include "BluetoothHALHelpers.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
typedef
|
||||
BluetoothHALInterfaceRunnable0<BluetoothA2dpResultHandler, void>
|
||||
BluetoothA2dpHALResultRunnable;
|
||||
|
||||
typedef
|
||||
BluetoothHALInterfaceRunnable1<BluetoothA2dpResultHandler, void,
|
||||
BluetoothStatus, BluetoothStatus>
|
||||
BluetoothA2dpHALErrorRunnable;
|
||||
|
||||
static nsresult
|
||||
DispatchBluetoothA2dpHALResult(
|
||||
BluetoothA2dpResultHandler* aRes,
|
||||
void (BluetoothA2dpResultHandler::*aMethod)(),
|
||||
BluetoothStatus aStatus)
|
||||
{
|
||||
MOZ_ASSERT(aRes);
|
||||
|
||||
nsRefPtr<nsRunnable> runnable;
|
||||
|
||||
if (aStatus == STATUS_SUCCESS) {
|
||||
runnable = new BluetoothA2dpHALResultRunnable(aRes, aMethod);
|
||||
} else {
|
||||
runnable = new BluetoothA2dpHALErrorRunnable(aRes,
|
||||
&BluetoothA2dpResultHandler::OnError, aStatus);
|
||||
}
|
||||
nsresult rv = NS_DispatchToMainThread(runnable);
|
||||
if (NS_FAILED(rv)) {
|
||||
BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Notification handling
|
||||
//
|
||||
|
||||
static BluetoothA2dpNotificationHandler* sA2dpNotificationHandler;
|
||||
|
||||
struct BluetoothA2dpHALCallback
|
||||
{
|
||||
class A2dpNotificationHandlerWrapper
|
||||
{
|
||||
public:
|
||||
typedef BluetoothA2dpNotificationHandler ObjectType;
|
||||
|
||||
static ObjectType* GetInstance()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
return sA2dpNotificationHandler;
|
||||
}
|
||||
};
|
||||
|
||||
// Notifications
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<
|
||||
A2dpNotificationHandlerWrapper, void,
|
||||
BluetoothA2dpConnectionState, nsString,
|
||||
BluetoothA2dpConnectionState, const nsAString&>
|
||||
ConnectionStateNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<
|
||||
A2dpNotificationHandlerWrapper, void,
|
||||
BluetoothA2dpAudioState, nsString,
|
||||
BluetoothA2dpAudioState, const nsAString&>
|
||||
AudioStateNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable3<
|
||||
A2dpNotificationHandlerWrapper, void,
|
||||
nsString, uint32_t, uint8_t,
|
||||
const nsAString&, uint32_t, uint8_t>
|
||||
AudioConfigNotification;
|
||||
|
||||
// Bluedroid A2DP callbacks
|
||||
|
||||
static void
|
||||
ConnectionState(btav_connection_state_t aState, bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
ConnectionStateNotification::Dispatch(
|
||||
&BluetoothA2dpNotificationHandler::ConnectionStateNotification,
|
||||
aState, aBdAddr);
|
||||
}
|
||||
|
||||
static void
|
||||
AudioState(btav_audio_state_t aState, bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
AudioStateNotification::Dispatch(
|
||||
&BluetoothA2dpNotificationHandler::AudioStateNotification,
|
||||
aState, aBdAddr);
|
||||
}
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
AudioConfig(bt_bdaddr_t *aBdAddr, uint32_t aSampleRate, uint8_t aChannelCount)
|
||||
{
|
||||
AudioConfigNotification::Dispatch(
|
||||
&BluetoothA2dpNotificationHandler::AudioConfigNotification,
|
||||
aBdAddr, aSampleRate, aChannelCount);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
// Interface
|
||||
//
|
||||
|
||||
BluetoothA2dpHALInterface::BluetoothA2dpHALInterface(
|
||||
const btav_interface_t* aInterface)
|
||||
: mInterface(aInterface)
|
||||
{
|
||||
MOZ_ASSERT(mInterface);
|
||||
}
|
||||
|
||||
BluetoothA2dpHALInterface::~BluetoothA2dpHALInterface()
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothA2dpHALInterface::Init(
|
||||
BluetoothA2dpNotificationHandler* aNotificationHandler,
|
||||
BluetoothA2dpResultHandler* aRes)
|
||||
{
|
||||
static btav_callbacks_t sCallbacks = {
|
||||
sizeof(sCallbacks),
|
||||
BluetoothA2dpHALCallback::ConnectionState,
|
||||
BluetoothA2dpHALCallback::AudioState,
|
||||
#if ANDROID_VERSION >= 21
|
||||
BluetoothA2dpHALCallback::AudioConfig
|
||||
#endif
|
||||
};
|
||||
|
||||
sA2dpNotificationHandler = aNotificationHandler;
|
||||
|
||||
bt_status_t status = mInterface->init(&sCallbacks);
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothA2dpHALResult(aRes,
|
||||
&BluetoothA2dpResultHandler::Init,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothA2dpHALInterface::Cleanup(BluetoothA2dpResultHandler* aRes)
|
||||
{
|
||||
mInterface->cleanup();
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothA2dpHALResult(aRes,
|
||||
&BluetoothA2dpResultHandler::Cleanup,
|
||||
STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothA2dpHALInterface::Connect(const nsAString& aBdAddr,
|
||||
BluetoothA2dpResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
bt_bdaddr_t bdAddr;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
|
||||
status = mInterface->connect(&bdAddr);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothA2dpHALResult(
|
||||
aRes, &BluetoothA2dpResultHandler::Connect,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothA2dpHALInterface::Disconnect(const nsAString& aBdAddr,
|
||||
BluetoothA2dpResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
bt_bdaddr_t bdAddr;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
|
||||
status = mInterface->disconnect(&bdAddr);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothA2dpHALResult(
|
||||
aRes, &BluetoothA2dpResultHandler::Disconnect,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
@ -1,44 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_bluetooth_bluedroid_bluetootha2dphalinterface_h__
|
||||
#define mozilla_dom_bluetooth_bluedroid_bluetootha2dphalinterface_h__
|
||||
|
||||
#include <hardware/bluetooth.h>
|
||||
#include <hardware/bt_av.h>
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothInterface.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothHALInterface;
|
||||
|
||||
class BluetoothA2dpHALInterface final
|
||||
: public BluetoothA2dpInterface
|
||||
{
|
||||
public:
|
||||
friend class BluetoothHALInterface;
|
||||
|
||||
void Init(BluetoothA2dpNotificationHandler* aNotificationHandler,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
void Cleanup(BluetoothA2dpResultHandler* aRes);
|
||||
|
||||
void Connect(const nsAString& aBdAddr,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
void Disconnect(const nsAString& aBdAddr,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
BluetoothA2dpHALInterface(const btav_interface_t* aInterface);
|
||||
~BluetoothA2dpHALInterface();
|
||||
|
||||
private:
|
||||
const btav_interface_t* mInterface;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,593 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BluetoothAvrcpHALInterface.h"
|
||||
#include "BluetoothHALHelpers.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
typedef
|
||||
BluetoothHALInterfaceRunnable0<BluetoothAvrcpResultHandler, void>
|
||||
BluetoothAvrcpHALResultRunnable;
|
||||
|
||||
typedef
|
||||
BluetoothHALInterfaceRunnable1<BluetoothAvrcpResultHandler, void,
|
||||
BluetoothStatus, BluetoothStatus>
|
||||
BluetoothAvrcpHALErrorRunnable;
|
||||
|
||||
static nsresult
|
||||
DispatchBluetoothAvrcpHALResult(
|
||||
BluetoothAvrcpResultHandler* aRes,
|
||||
void (BluetoothAvrcpResultHandler::*aMethod)(),
|
||||
BluetoothStatus aStatus)
|
||||
{
|
||||
MOZ_ASSERT(aRes);
|
||||
|
||||
nsRefPtr<nsRunnable> runnable;
|
||||
|
||||
if (aStatus == STATUS_SUCCESS) {
|
||||
runnable = new BluetoothAvrcpHALResultRunnable(aRes, aMethod);
|
||||
} else {
|
||||
runnable = new BluetoothAvrcpHALErrorRunnable(aRes,
|
||||
&BluetoothAvrcpResultHandler::OnError, aStatus);
|
||||
}
|
||||
nsresult rv = NS_DispatchToMainThread(runnable);
|
||||
if (NS_FAILED(rv)) {
|
||||
BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Notification handling
|
||||
//
|
||||
|
||||
static BluetoothAvrcpNotificationHandler* sAvrcpNotificationHandler;
|
||||
|
||||
struct BluetoothAvrcpCallback
|
||||
{
|
||||
class AvrcpNotificationHandlerWrapper
|
||||
{
|
||||
public:
|
||||
typedef BluetoothAvrcpNotificationHandler ObjectType;
|
||||
|
||||
static ObjectType* GetInstance()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
return sAvrcpNotificationHandler;
|
||||
}
|
||||
};
|
||||
|
||||
// Notifications
|
||||
|
||||
typedef BluetoothNotificationHALRunnable0<AvrcpNotificationHandlerWrapper,
|
||||
void>
|
||||
GetPlayStatusNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable0<AvrcpNotificationHandlerWrapper,
|
||||
void>
|
||||
ListPlayerAppAttrNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable1<AvrcpNotificationHandlerWrapper,
|
||||
void,
|
||||
BluetoothAvrcpPlayerAttribute>
|
||||
ListPlayerAppValuesNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<AvrcpNotificationHandlerWrapper, void,
|
||||
uint8_t, nsAutoArrayPtr<BluetoothAvrcpPlayerAttribute>,
|
||||
uint8_t, const BluetoothAvrcpPlayerAttribute*>
|
||||
GetPlayerAppValueNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<AvrcpNotificationHandlerWrapper, void,
|
||||
uint8_t, nsAutoArrayPtr<BluetoothAvrcpPlayerAttribute>,
|
||||
uint8_t, const BluetoothAvrcpPlayerAttribute*>
|
||||
GetPlayerAppAttrsTextNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable3<AvrcpNotificationHandlerWrapper,
|
||||
void,
|
||||
uint8_t, uint8_t,
|
||||
nsAutoArrayPtr<uint8_t>,
|
||||
uint8_t, uint8_t, const uint8_t*>
|
||||
GetPlayerAppValuesTextNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable1<AvrcpNotificationHandlerWrapper,
|
||||
void,
|
||||
BluetoothAvrcpPlayerSettings,
|
||||
const BluetoothAvrcpPlayerSettings&>
|
||||
SetPlayerAppValueNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<AvrcpNotificationHandlerWrapper, void,
|
||||
uint8_t, nsAutoArrayPtr<BluetoothAvrcpMediaAttribute>,
|
||||
uint8_t, const BluetoothAvrcpMediaAttribute*>
|
||||
GetElementAttrNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<AvrcpNotificationHandlerWrapper,
|
||||
void,
|
||||
BluetoothAvrcpEvent, uint32_t>
|
||||
RegisterNotificationNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<AvrcpNotificationHandlerWrapper,
|
||||
void,
|
||||
nsString, unsigned long,
|
||||
const nsAString&>
|
||||
RemoteFeatureNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<AvrcpNotificationHandlerWrapper,
|
||||
void,
|
||||
uint8_t, uint8_t>
|
||||
VolumeChangeNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<AvrcpNotificationHandlerWrapper,
|
||||
void,
|
||||
int, int>
|
||||
PassthroughCmdNotification;
|
||||
|
||||
// Bluedroid AVRCP callbacks
|
||||
|
||||
#if ANDROID_VERSION >= 18
|
||||
static void
|
||||
GetPlayStatus()
|
||||
{
|
||||
GetPlayStatusNotification::Dispatch(
|
||||
&BluetoothAvrcpNotificationHandler::GetPlayStatusNotification);
|
||||
}
|
||||
|
||||
static void
|
||||
ListPlayerAppAttr()
|
||||
{
|
||||
ListPlayerAppAttrNotification::Dispatch(
|
||||
&BluetoothAvrcpNotificationHandler::ListPlayerAppAttrNotification);
|
||||
}
|
||||
|
||||
static void
|
||||
ListPlayerAppValues(btrc_player_attr_t aAttrId)
|
||||
{
|
||||
ListPlayerAppValuesNotification::Dispatch(
|
||||
&BluetoothAvrcpNotificationHandler::ListPlayerAppValuesNotification,
|
||||
aAttrId);
|
||||
}
|
||||
|
||||
static void
|
||||
GetPlayerAppValue(uint8_t aNumAttrs, btrc_player_attr_t* aAttrs)
|
||||
{
|
||||
GetPlayerAppValueNotification::Dispatch(
|
||||
&BluetoothAvrcpNotificationHandler::GetPlayerAppValueNotification,
|
||||
aNumAttrs, ConvertArray<btrc_player_attr_t>(aAttrs, aNumAttrs));
|
||||
}
|
||||
|
||||
static void
|
||||
GetPlayerAppAttrsText(uint8_t aNumAttrs, btrc_player_attr_t* aAttrs)
|
||||
{
|
||||
GetPlayerAppAttrsTextNotification::Dispatch(
|
||||
&BluetoothAvrcpNotificationHandler::GetPlayerAppAttrsTextNotification,
|
||||
aNumAttrs, ConvertArray<btrc_player_attr_t>(aAttrs, aNumAttrs));
|
||||
}
|
||||
|
||||
static void
|
||||
GetPlayerAppValuesText(uint8_t aAttrId, uint8_t aNumVals, uint8_t* aVals)
|
||||
{
|
||||
GetPlayerAppValuesTextNotification::Dispatch(
|
||||
&BluetoothAvrcpNotificationHandler::GetPlayerAppValuesTextNotification,
|
||||
aAttrId, aNumVals, ConvertArray<uint8_t>(aVals, aNumVals));
|
||||
}
|
||||
|
||||
static void
|
||||
SetPlayerAppValue(btrc_player_settings_t* aVals)
|
||||
{
|
||||
SetPlayerAppValueNotification::Dispatch(
|
||||
&BluetoothAvrcpNotificationHandler::SetPlayerAppValueNotification,
|
||||
*aVals);
|
||||
}
|
||||
|
||||
static void
|
||||
GetElementAttr(uint8_t aNumAttrs, btrc_media_attr_t* aAttrs)
|
||||
{
|
||||
GetElementAttrNotification::Dispatch(
|
||||
&BluetoothAvrcpNotificationHandler::GetElementAttrNotification,
|
||||
aNumAttrs, ConvertArray<btrc_media_attr_t>(aAttrs, aNumAttrs));
|
||||
}
|
||||
|
||||
static void
|
||||
RegisterNotification(btrc_event_id_t aEvent, uint32_t aParam)
|
||||
{
|
||||
RegisterNotificationNotification::Dispatch(
|
||||
&BluetoothAvrcpNotificationHandler::RegisterNotificationNotification,
|
||||
aEvent, aParam);
|
||||
}
|
||||
#endif // ANDROID_VERSION >= 18
|
||||
|
||||
#if ANDROID_VERSION >= 19
|
||||
static void
|
||||
RemoteFeature(bt_bdaddr_t* aBdAddr, btrc_remote_features_t aFeatures)
|
||||
{
|
||||
RemoteFeatureNotification::Dispatch(
|
||||
&BluetoothAvrcpNotificationHandler::RemoteFeatureNotification,
|
||||
aBdAddr, aFeatures);
|
||||
}
|
||||
|
||||
static void
|
||||
VolumeChange(uint8_t aVolume, uint8_t aCType)
|
||||
{
|
||||
VolumeChangeNotification::Dispatch(
|
||||
&BluetoothAvrcpNotificationHandler::VolumeChangeNotification,
|
||||
aVolume, aCType);
|
||||
}
|
||||
|
||||
static void
|
||||
PassthroughCmd(int aId, int aKeyState)
|
||||
{
|
||||
PassthroughCmdNotification::Dispatch(
|
||||
&BluetoothAvrcpNotificationHandler::PassthroughCmdNotification,
|
||||
aId, aKeyState);
|
||||
}
|
||||
#endif // ANDROID_VERSION >= 19
|
||||
};
|
||||
|
||||
// Interface
|
||||
//
|
||||
|
||||
BluetoothAvrcpHALInterface::BluetoothAvrcpHALInterface(
|
||||
#if ANDROID_VERSION >= 18
|
||||
const btrc_interface_t* aInterface
|
||||
#endif
|
||||
)
|
||||
#if ANDROID_VERSION >= 18
|
||||
: mInterface(aInterface)
|
||||
#endif
|
||||
{
|
||||
#if ANDROID_VERSION >= 18
|
||||
MOZ_ASSERT(mInterface);
|
||||
#endif
|
||||
}
|
||||
|
||||
BluetoothAvrcpHALInterface::~BluetoothAvrcpHALInterface()
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothAvrcpHALInterface::Init(
|
||||
BluetoothAvrcpNotificationHandler* aNotificationHandler,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
#if ANDROID_VERSION >= 18
|
||||
static btrc_callbacks_t sCallbacks = {
|
||||
sizeof(sCallbacks),
|
||||
#if ANDROID_VERSION >= 19
|
||||
BluetoothAvrcpCallback::RemoteFeature,
|
||||
#endif
|
||||
BluetoothAvrcpCallback::GetPlayStatus,
|
||||
BluetoothAvrcpCallback::ListPlayerAppAttr,
|
||||
BluetoothAvrcpCallback::ListPlayerAppValues,
|
||||
BluetoothAvrcpCallback::GetPlayerAppValue,
|
||||
BluetoothAvrcpCallback::GetPlayerAppAttrsText,
|
||||
BluetoothAvrcpCallback::GetPlayerAppValuesText,
|
||||
BluetoothAvrcpCallback::SetPlayerAppValue,
|
||||
BluetoothAvrcpCallback::GetElementAttr,
|
||||
BluetoothAvrcpCallback::RegisterNotification
|
||||
#if ANDROID_VERSION >= 19
|
||||
,
|
||||
BluetoothAvrcpCallback::VolumeChange,
|
||||
BluetoothAvrcpCallback::PassthroughCmd
|
||||
#endif
|
||||
};
|
||||
#endif // ANDROID_VERSION >= 18
|
||||
|
||||
sAvrcpNotificationHandler = aNotificationHandler;
|
||||
|
||||
#if ANDROID_VERSION >= 18
|
||||
bt_status_t status = mInterface->init(&sCallbacks);
|
||||
#else
|
||||
bt_status_t status = BT_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpHALResult(aRes, &BluetoothAvrcpResultHandler::Init,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothAvrcpHALInterface::Cleanup(BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
#if ANDROID_VERSION >= 18
|
||||
mInterface->cleanup();
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpHALResult(aRes,
|
||||
&BluetoothAvrcpResultHandler::Cleanup, STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothAvrcpHALInterface::GetPlayStatusRsp(
|
||||
ControlPlayStatus aPlayStatus, uint32_t aSongLen, uint32_t aSongPos,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
|
||||
#if ANDROID_VERSION >= 18
|
||||
btrc_play_status_t playStatus = BTRC_PLAYSTATE_STOPPED;
|
||||
|
||||
if (!(NS_FAILED(Convert(aPlayStatus, playStatus)))) {
|
||||
status = mInterface->get_play_status_rsp(playStatus, aSongLen, aSongPos);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
#else
|
||||
status = BT_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpHALResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::GetPlayStatusRsp,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothAvrcpHALInterface::ListPlayerAppAttrRsp(
|
||||
int aNumAttr, const BluetoothAvrcpPlayerAttribute* aPAttrs,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
|
||||
#if ANDROID_VERSION >= 18
|
||||
ConvertArray<BluetoothAvrcpPlayerAttribute> pAttrsArray(aPAttrs, aNumAttr);
|
||||
nsAutoArrayPtr<btrc_player_attr_t> pAttrs;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(pAttrsArray, pAttrs))) {
|
||||
status = mInterface->list_player_app_attr_rsp(aNumAttr, pAttrs);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
#else
|
||||
status = BT_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpHALResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::ListPlayerAppAttrRsp,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothAvrcpHALInterface::ListPlayerAppValueRsp(
|
||||
int aNumVal, uint8_t* aPVals, BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
#if ANDROID_VERSION >= 18
|
||||
bt_status_t status = mInterface->list_player_app_value_rsp(aNumVal, aPVals);
|
||||
#else
|
||||
bt_status_t status = BT_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpHALResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::ListPlayerAppValueRsp,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothAvrcpHALInterface::GetPlayerAppValueRsp(
|
||||
uint8_t aNumAttrs, const uint8_t* aIds, const uint8_t* aValues,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
|
||||
#if ANDROID_VERSION >= 18
|
||||
btrc_player_settings_t pVals;
|
||||
|
||||
/* FIXME: you need to implement the missing conversion functions */
|
||||
NS_NOTREACHED("Conversion function missing");
|
||||
|
||||
if (false /* TODO: we don't support any player app values currently */) {
|
||||
status = mInterface->get_player_app_value_rsp(&pVals);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
#else
|
||||
status = BT_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpHALResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueRsp,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothAvrcpHALInterface::GetPlayerAppAttrTextRsp(
|
||||
int aNumAttr, const uint8_t* aIds, const char** aTexts,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
|
||||
#if ANDROID_VERSION >= 18
|
||||
btrc_player_setting_text_t* aPAttrs;
|
||||
|
||||
/* FIXME: you need to implement the missing conversion functions */
|
||||
NS_NOTREACHED("Conversion function missing");
|
||||
|
||||
if (false /* TODO: we don't support any attributes currently */) {
|
||||
status = mInterface->get_player_app_attr_text_rsp(aNumAttr, aPAttrs);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
#else
|
||||
status = BT_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpHALResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::GetPlayerAppAttrTextRsp,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothAvrcpHALInterface::GetPlayerAppValueTextRsp(
|
||||
int aNumVal, const uint8_t* aIds, const char** aTexts,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
|
||||
#if ANDROID_VERSION >= 18
|
||||
btrc_player_setting_text_t* pVals;
|
||||
|
||||
/* FIXME: you need to implement the missing conversion functions */
|
||||
NS_NOTREACHED("Conversion function missing");
|
||||
|
||||
if (false /* TODO: we don't support any values currently */) {
|
||||
status = mInterface->get_player_app_value_text_rsp(aNumVal, pVals);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
#else
|
||||
status = BT_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpHALResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueTextRsp,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothAvrcpHALInterface::GetElementAttrRsp(
|
||||
uint8_t aNumAttr, const BluetoothAvrcpElementAttribute* aAttrs,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
|
||||
#if ANDROID_VERSION >= 18
|
||||
ConvertArray<BluetoothAvrcpElementAttribute> pAttrsArray(aAttrs, aNumAttr);
|
||||
nsAutoArrayPtr<btrc_element_attr_val_t> pAttrs;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(pAttrsArray, pAttrs))) {
|
||||
status = mInterface->get_element_attr_rsp(aNumAttr, pAttrs);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
#else
|
||||
status = BT_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpHALResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::GetElementAttrRsp,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothAvrcpHALInterface::SetPlayerAppValueRsp(
|
||||
BluetoothAvrcpStatus aRspStatus, BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
|
||||
#if ANDROID_VERSION >= 18
|
||||
btrc_status_t rspStatus = BTRC_STS_BAD_CMD; // silences compiler warning
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aRspStatus, rspStatus))) {
|
||||
status = mInterface->set_player_app_value_rsp(rspStatus);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
#else
|
||||
status = BT_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpHALResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::SetPlayerAppValueRsp,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothAvrcpHALInterface::RegisterNotificationRsp(
|
||||
BluetoothAvrcpEvent aEvent, BluetoothAvrcpNotification aType,
|
||||
const BluetoothAvrcpNotificationParam& aParam,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
|
||||
#if ANDROID_VERSION >= 18
|
||||
nsresult rv;
|
||||
btrc_event_id_t event = { };
|
||||
btrc_notification_type_t type = BTRC_NOTIFICATION_TYPE_INTERIM;
|
||||
btrc_register_notification_t param;
|
||||
|
||||
switch (aEvent) {
|
||||
case AVRCP_EVENT_PLAY_STATUS_CHANGED:
|
||||
rv = Convert(aParam.mPlayStatus, param.play_status);
|
||||
break;
|
||||
case AVRCP_EVENT_TRACK_CHANGE:
|
||||
MOZ_ASSERT(sizeof(aParam.mTrack) == sizeof(param.track));
|
||||
memcpy(param.track, aParam.mTrack, sizeof(param.track));
|
||||
rv = NS_OK;
|
||||
break;
|
||||
case AVRCP_EVENT_TRACK_REACHED_END:
|
||||
NS_NOTREACHED("Unknown conversion");
|
||||
rv = NS_ERROR_ILLEGAL_VALUE;
|
||||
break;
|
||||
case AVRCP_EVENT_TRACK_REACHED_START:
|
||||
NS_NOTREACHED("Unknown conversion");
|
||||
rv = NS_ERROR_ILLEGAL_VALUE;
|
||||
break;
|
||||
case AVRCP_EVENT_PLAY_POS_CHANGED:
|
||||
param.song_pos = aParam.mSongPos;
|
||||
rv = NS_OK;
|
||||
break;
|
||||
case AVRCP_EVENT_APP_SETTINGS_CHANGED:
|
||||
NS_NOTREACHED("Unknown conversion");
|
||||
rv = NS_ERROR_ILLEGAL_VALUE;
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("Unknown conversion");
|
||||
rv = NS_ERROR_ILLEGAL_VALUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
NS_SUCCEEDED(Convert(aEvent, event)) &&
|
||||
NS_SUCCEEDED(Convert(aType, type))) {
|
||||
status = mInterface->register_notification_rsp(event, type, ¶m);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
#else
|
||||
status = BT_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpHALResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::RegisterNotificationRsp,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothAvrcpHALInterface::SetVolume(uint8_t aVolume,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
#if ANDROID_VERSION >= 19
|
||||
bt_status_t status = mInterface->set_volume(aVolume);
|
||||
#else
|
||||
bt_status_t status = BT_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothAvrcpHALResult(
|
||||
aRes, &BluetoothAvrcpResultHandler::SetVolume,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
@ -1,84 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_bluetooth_bluedroid_bluetoothavrcphalinterface_h__
|
||||
#define mozilla_dom_bluetooth_bluedroid_bluetoothavrcphalinterface_h__
|
||||
|
||||
#include <hardware/bluetooth.h>
|
||||
#if ANDROID_VERSION >= 18
|
||||
#include <hardware/bt_rc.h>
|
||||
#endif
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothInterface.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothHALInterface;
|
||||
|
||||
class BluetoothAvrcpHALInterface final
|
||||
: public BluetoothAvrcpInterface
|
||||
{
|
||||
public:
|
||||
friend class BluetoothHALInterface;
|
||||
|
||||
void Init(BluetoothAvrcpNotificationHandler* aNotificationHandler,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
void Cleanup(BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
void GetPlayStatusRsp(ControlPlayStatus aPlayStatus,
|
||||
uint32_t aSongLen, uint32_t aSongPos,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
void ListPlayerAppAttrRsp(int aNumAttr,
|
||||
const BluetoothAvrcpPlayerAttribute* aPAttrs,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
void ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
/* TODO: redesign this interface once we actually use it */
|
||||
void GetPlayerAppValueRsp(uint8_t aNumAttrs,
|
||||
const uint8_t* aIds, const uint8_t* aValues,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
/* TODO: redesign this interface once we actually use it */
|
||||
void GetPlayerAppAttrTextRsp(int aNumAttr,
|
||||
const uint8_t* aIds, const char** aTexts,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
/* TODO: redesign this interface once we actually use it */
|
||||
void GetPlayerAppValueTextRsp(int aNumVal,
|
||||
const uint8_t* aIds, const char** aTexts,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
void GetElementAttrRsp(uint8_t aNumAttr,
|
||||
const BluetoothAvrcpElementAttribute* aAttr,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
void SetPlayerAppValueRsp(BluetoothAvrcpStatus aRspStatus,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
void RegisterNotificationRsp(BluetoothAvrcpEvent aEvent,
|
||||
BluetoothAvrcpNotification aType,
|
||||
const BluetoothAvrcpNotificationParam& aParam,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
void SetVolume(uint8_t aVolume, BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
BluetoothAvrcpHALInterface(
|
||||
#if ANDROID_VERSION >= 18
|
||||
const btrc_interface_t* aInterface
|
||||
#endif
|
||||
);
|
||||
~BluetoothAvrcpHALInterface();
|
||||
|
||||
private:
|
||||
#if ANDROID_VERSION >= 18
|
||||
const btrc_interface_t* mInterface;
|
||||
#endif
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
@ -10,6 +10,8 @@
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
//
|
||||
// A2DP module
|
||||
//
|
||||
|
@ -9,11 +9,13 @@
|
||||
|
||||
#include "BluetoothDaemonHelpers.h"
|
||||
#include "BluetoothInterface.h"
|
||||
#include "BluetoothInterfaceHelpers.h"
|
||||
#include "mozilla/ipc/DaemonRunnables.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using mozilla::ipc::DaemonSocketPDU;
|
||||
using mozilla::ipc::DaemonSocketPDUHeader;
|
||||
|
||||
class BluetoothSetupResultHandler;
|
||||
|
||||
class BluetoothDaemonA2dpModule
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
//
|
||||
// AVRCP module
|
||||
//
|
||||
|
@ -9,11 +9,13 @@
|
||||
|
||||
#include "BluetoothDaemonHelpers.h"
|
||||
#include "BluetoothInterface.h"
|
||||
#include "BluetoothInterfaceHelpers.h"
|
||||
#include "mozilla/ipc/DaemonRunnables.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using mozilla::ipc::DaemonSocketPDU;
|
||||
using mozilla::ipc::DaemonSocketPDUHeader;
|
||||
|
||||
class BluetoothSetupResultHandler;
|
||||
|
||||
class BluetoothDaemonAvrcpModule
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
//
|
||||
// GATT module
|
||||
//
|
||||
|
@ -9,11 +9,13 @@
|
||||
|
||||
#include "BluetoothDaemonHelpers.h"
|
||||
#include "BluetoothInterface.h"
|
||||
#include "BluetoothInterfaceHelpers.h"
|
||||
#include "mozilla/ipc/DaemonRunnables.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using mozilla::ipc::DaemonSocketPDU;
|
||||
using mozilla::ipc::DaemonSocketPDUHeader;
|
||||
|
||||
class BluetoothSetupResultHandler;
|
||||
|
||||
class BluetoothDaemonGattModule
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
//
|
||||
// Handsfree module
|
||||
//
|
||||
|
@ -9,11 +9,13 @@
|
||||
|
||||
#include "BluetoothDaemonHelpers.h"
|
||||
#include "BluetoothInterface.h"
|
||||
#include "BluetoothInterfaceHelpers.h"
|
||||
#include "mozilla/ipc/DaemonRunnables.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using mozilla::ipc::DaemonSocketPDU;
|
||||
using mozilla::ipc::DaemonSocketPDUHeader;
|
||||
|
||||
class BluetoothSetupResultHandler;
|
||||
|
||||
class BluetoothDaemonHandsfreeModule
|
||||
|
@ -11,40 +11,13 @@
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using mozilla::ipc::DaemonSocketPDUHelpers::Convert;
|
||||
using mozilla::ipc::DaemonSocketPDUHelpers::PackPDU;
|
||||
|
||||
//
|
||||
// Conversion
|
||||
//
|
||||
|
||||
nsresult
|
||||
Convert(bool aIn, uint8_t& aOut)
|
||||
{
|
||||
static const bool sValue[] = {
|
||||
CONVERT(false, 0x00),
|
||||
CONVERT(true, 0x01)
|
||||
};
|
||||
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sValue))) {
|
||||
aOut = 0;
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
aOut = sValue[aIn];
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(bool aIn, int32_t& aOut)
|
||||
{
|
||||
static const bool sValue[] = {
|
||||
CONVERT(false, 0x00),
|
||||
CONVERT(true, 0x01)
|
||||
};
|
||||
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sValue))) {
|
||||
aOut = 0;
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
aOut = sValue[aIn];
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(bool aIn, BluetoothScanMode& aOut)
|
||||
{
|
||||
@ -60,42 +33,6 @@ Convert(bool aIn, BluetoothScanMode& aOut)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(int aIn, uint8_t& aOut)
|
||||
{
|
||||
if (NS_WARN_IF(aIn < std::numeric_limits<uint8_t>::min()) ||
|
||||
NS_WARN_IF(aIn > std::numeric_limits<uint8_t>::max())) {
|
||||
aOut = 0; // silences compiler warning
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
aOut = static_cast<uint8_t>(aIn);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(int aIn, int16_t& aOut)
|
||||
{
|
||||
if (NS_WARN_IF(aIn < std::numeric_limits<int16_t>::min()) ||
|
||||
NS_WARN_IF(aIn > std::numeric_limits<int16_t>::max())) {
|
||||
aOut = 0; // silences compiler warning
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
aOut = static_cast<int16_t>(aIn);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(int aIn, int32_t& aOut)
|
||||
{
|
||||
if (NS_WARN_IF(aIn < std::numeric_limits<int32_t>::min()) ||
|
||||
NS_WARN_IF(aIn > std::numeric_limits<int32_t>::max())) {
|
||||
aOut = 0; // silences compiler warning
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
aOut = static_cast<int32_t>(aIn);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(int32_t aIn, BluetoothTypeOfDevice& aOut)
|
||||
{
|
||||
@ -129,41 +66,6 @@ Convert(int32_t aIn, BluetoothScanMode& aOut)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(uint8_t aIn, bool& aOut)
|
||||
{
|
||||
static const bool sBool[] = {
|
||||
CONVERT(0x00, false),
|
||||
CONVERT(0x01, true)
|
||||
};
|
||||
if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sBool))) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
aOut = sBool[aIn];
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(uint8_t aIn, char& aOut)
|
||||
{
|
||||
aOut = static_cast<char>(aIn);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(uint8_t aIn, int& aOut)
|
||||
{
|
||||
aOut = static_cast<int>(aIn);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(uint8_t aIn, unsigned long& aOut)
|
||||
{
|
||||
aOut = static_cast<unsigned long>(aIn);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(uint8_t aIn, BluetoothA2dpAudioState& aOut)
|
||||
{
|
||||
@ -547,36 +449,6 @@ Convert(int32_t aIn, BluetoothGattStatus& aOut)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(uint32_t aIn, int& aOut)
|
||||
{
|
||||
aOut = static_cast<int>(aIn);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(uint32_t aIn, uint8_t& aOut)
|
||||
{
|
||||
if (NS_WARN_IF(aIn < std::numeric_limits<uint8_t>::min()) ||
|
||||
NS_WARN_IF(aIn > std::numeric_limits<uint8_t>::max())) {
|
||||
aOut = 0; // silences compiler warning
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
aOut = static_cast<uint8_t>(aIn);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(size_t aIn, uint16_t& aOut)
|
||||
{
|
||||
if (NS_WARN_IF(aIn >= (1ul << 16))) {
|
||||
aOut = 0; // silences compiler warning
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
aOut = static_cast<uint16_t>(aIn);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const nsAString& aIn, BluetoothAddress& aOut)
|
||||
{
|
||||
@ -652,6 +524,19 @@ Convert(const nsAString& aIn, BluetoothServiceName& aOut)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(nsresult aIn, BluetoothStatus& aOut)
|
||||
{
|
||||
if (NS_SUCCEEDED(aIn)) {
|
||||
aOut = STATUS_SUCCESS;
|
||||
} else if (aIn == NS_ERROR_OUT_OF_MEMORY) {
|
||||
aOut = STATUS_NOMEM;
|
||||
} else {
|
||||
aOut = STATUS_FAIL;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(BluetoothAclState aIn, bool& aOut)
|
||||
{
|
||||
@ -1260,12 +1145,6 @@ PackPDU(const BluetoothConfigurationParameter& aIn, DaemonSocketPDU& aPDU)
|
||||
PackArray<uint8_t>(aIn.mValue.get(), aIn.mLength), aPDU);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PackPDU(const DaemonSocketPDUHeader& aIn, DaemonSocketPDU& aPDU)
|
||||
{
|
||||
return PackPDU(aIn.mService, aIn.mOpcode, aIn.mLength, aPDU);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PackPDU(const BluetoothHandsfreeAtResponse& aIn, DaemonSocketPDU& aPDU)
|
||||
{
|
||||
@ -1873,64 +1752,5 @@ UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattNotifyParam& aOut)
|
||||
/* unpack value */
|
||||
return aPDU.Read(aOut.mValue, aOut.mLength);
|
||||
}
|
||||
nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, nsDependentCString& aOut)
|
||||
{
|
||||
// We get a pointer to the first character in the PDU, a length
|
||||
// of 1 ensures we consume the \0 byte. With 'str' pointing to
|
||||
// the string in the PDU, we can copy the actual bytes.
|
||||
|
||||
const char* str = reinterpret_cast<const char*>(aPDU.Consume(1));
|
||||
if (NS_WARN_IF(!str)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE; // end of PDU
|
||||
}
|
||||
|
||||
const char* end = static_cast<char*>(memchr(str, '\0', aPDU.GetSize() + 1));
|
||||
if (NS_WARN_IF(!end)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE; // no string terminator
|
||||
}
|
||||
|
||||
ptrdiff_t len = end - str;
|
||||
|
||||
const uint8_t* rest = aPDU.Consume(len);
|
||||
if (NS_WARN_IF(!rest)) {
|
||||
// We couldn't consume bytes that should have been there.
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
aOut.Rebind(str, len);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, const UnpackCString0& aOut)
|
||||
{
|
||||
nsDependentCString cstring;
|
||||
|
||||
nsresult rv = UnpackPDU(aPDU, cstring);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
aOut.mString->AssignASCII(cstring.get(), cstring.Length());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, const UnpackString0& aOut)
|
||||
{
|
||||
nsDependentCString cstring;
|
||||
|
||||
nsresult rv = UnpackPDU(aPDU, cstring);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
*aOut.mString = NS_ConvertUTF8toUTF16(cstring);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
@ -11,12 +11,18 @@
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/ipc/DaemonSocketPDU.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
#include "mozilla/ipc/DaemonSocketPDUHelpers.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using mozilla::ipc::DaemonSocketPDU;
|
||||
using mozilla::ipc::DaemonSocketPDUHeader;
|
||||
using mozilla::ipc::DaemonSocketPDUHelpers::Convert;
|
||||
using mozilla::ipc::DaemonSocketPDUHelpers::PackPDU;
|
||||
using mozilla::ipc::DaemonSocketPDUHelpers::UnpackPDU;
|
||||
|
||||
using namespace mozilla::ipc::DaemonSocketPDUHelpers;
|
||||
|
||||
//
|
||||
// Helper structures
|
||||
//
|
||||
@ -106,24 +112,6 @@ struct BluetoothConfigurationParameter {
|
||||
nsAutoArrayPtr<uint8_t> mValue;
|
||||
};
|
||||
|
||||
struct DaemonSocketPDUHeader {
|
||||
DaemonSocketPDUHeader()
|
||||
: mService(0x00)
|
||||
, mOpcode(0x00)
|
||||
, mLength(0x00)
|
||||
{ }
|
||||
|
||||
DaemonSocketPDUHeader(uint8_t aService, uint8_t aOpcode, uint8_t aLength)
|
||||
: mService(aService)
|
||||
, mOpcode(aOpcode)
|
||||
, mLength(aLength)
|
||||
{ }
|
||||
|
||||
uint8_t mService;
|
||||
uint8_t mOpcode;
|
||||
uint16_t mLength;
|
||||
};
|
||||
|
||||
struct BluetoothPinCode {
|
||||
uint8_t mPinCode[16];
|
||||
uint8_t mLength;
|
||||
@ -140,49 +128,16 @@ struct BluetoothServiceName {
|
||||
//
|
||||
// Conversion
|
||||
//
|
||||
// PDUs can only store primitive data types, such as intergers or
|
||||
// strings. Gecko often uses more complex data types, such as
|
||||
// enumators or stuctures. Conversion functions convert between
|
||||
// primitive data and internal Gecko's data types during a PDU's
|
||||
// packing and unpacking.
|
||||
//
|
||||
|
||||
nsresult
|
||||
Convert(bool aIn, uint8_t& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(bool aIn, int32_t& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(bool aIn, BluetoothScanMode& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(int aIn, uint8_t& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(int aIn, int16_t& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(int aIn, int32_t& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(int32_t aIn, BluetoothTypeOfDevice& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(int32_t aIn, BluetoothScanMode& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(uint8_t aIn, bool& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(uint8_t aIn, char& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(uint8_t aIn, int& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(uint8_t aIn, unsigned long& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(uint8_t aIn, BluetoothA2dpAudioState& aOut);
|
||||
|
||||
@ -246,15 +201,6 @@ Convert(uint8_t aIn, BluetoothStatus& aOut);
|
||||
nsresult
|
||||
Convert(int32_t aIn, BluetoothGattStatus& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(uint32_t aIn, int& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(uint32_t aIn, uint8_t& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(size_t aIn, uint16_t& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(const nsAString& aIn, BluetoothAddress& aOut);
|
||||
|
||||
@ -342,42 +288,16 @@ Convert(BluetoothGattAuthReq aIn, int32_t& aOut);
|
||||
nsresult
|
||||
Convert(BluetoothGattWriteType aIn, int32_t& aOut);
|
||||
|
||||
nsresult
|
||||
Convert(nsresult aIn, BluetoothStatus& aOut);
|
||||
|
||||
//
|
||||
// Packing
|
||||
//
|
||||
|
||||
// introduce link errors on non-handled data types
|
||||
template <typename T>
|
||||
nsresult
|
||||
PackPDU(T aIn, DaemonSocketPDU& aPDU);
|
||||
|
||||
nsresult
|
||||
PackPDU(bool aIn, DaemonSocketPDU& aPDU);
|
||||
|
||||
inline nsresult
|
||||
PackPDU(uint8_t aIn, DaemonSocketPDU& aPDU)
|
||||
{
|
||||
return aPDU.Write(aIn);
|
||||
}
|
||||
|
||||
inline nsresult
|
||||
PackPDU(uint16_t aIn, DaemonSocketPDU& aPDU)
|
||||
{
|
||||
return aPDU.Write(aIn);
|
||||
}
|
||||
|
||||
inline nsresult
|
||||
PackPDU(int32_t aIn, DaemonSocketPDU& aPDU)
|
||||
{
|
||||
return aPDU.Write(aIn);
|
||||
}
|
||||
|
||||
inline nsresult
|
||||
PackPDU(uint32_t aIn, DaemonSocketPDU& aPDU)
|
||||
{
|
||||
return aPDU.Write(aIn);
|
||||
}
|
||||
|
||||
nsresult
|
||||
PackPDU(const BluetoothAddress& aIn, DaemonSocketPDU& aPDU);
|
||||
|
||||
@ -410,9 +330,6 @@ PackPDU(BluetoothAvrcpStatus aIn, DaemonSocketPDU& aPDU);
|
||||
nsresult
|
||||
PackPDU(const BluetoothConfigurationParameter& aIn, DaemonSocketPDU& aPDU);
|
||||
|
||||
nsresult
|
||||
PackPDU(const DaemonSocketPDUHeader& aIn, DaemonSocketPDU& aPDU);
|
||||
|
||||
nsresult
|
||||
PackPDU(const BluetoothHandsfreeAtResponse& aIn, DaemonSocketPDU& aPDU);
|
||||
|
||||
@ -877,41 +794,6 @@ PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3,
|
||||
// Unpacking
|
||||
//
|
||||
|
||||
// introduce link errors on non-handled data types
|
||||
template <typename T>
|
||||
nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, T& aOut);
|
||||
|
||||
inline nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, int8_t& aOut)
|
||||
{
|
||||
return aPDU.Read(aOut);
|
||||
}
|
||||
|
||||
inline nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, uint8_t& aOut)
|
||||
{
|
||||
return aPDU.Read(aOut);
|
||||
}
|
||||
|
||||
inline nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, uint16_t& aOut)
|
||||
{
|
||||
return aPDU.Read(aOut);
|
||||
}
|
||||
|
||||
inline nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, int32_t& aOut)
|
||||
{
|
||||
return aPDU.Read(aOut);
|
||||
}
|
||||
|
||||
inline nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, uint32_t& aOut)
|
||||
{
|
||||
return aPDU.Read(aOut);
|
||||
}
|
||||
|
||||
nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, bool& aOut);
|
||||
|
||||
@ -951,20 +833,6 @@ UnpackPDU(DaemonSocketPDU& aPDU, BluetoothAvrcpRemoteFeature& aOut);
|
||||
nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, BluetoothBondState& aOut);
|
||||
|
||||
inline nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, DaemonSocketPDUHeader& aOut)
|
||||
{
|
||||
nsresult rv = UnpackPDU(aPDU, aOut.mService);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
rv = UnpackPDU(aPDU, aOut.mOpcode);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return UnpackPDU(aPDU, aOut.mLength);
|
||||
}
|
||||
|
||||
nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, BluetoothTypeOfDevice& aOut);
|
||||
|
||||
@ -1038,9 +906,6 @@ UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattWriteParam& aOut);
|
||||
nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, BluetoothGattNotifyParam& aOut);
|
||||
|
||||
nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, nsDependentCString& aOut);
|
||||
|
||||
/* |UnpackConversion| is a helper for convering unpacked values. Pass
|
||||
* an instance of this structure to |UnpackPDU| to read a value from
|
||||
* the PDU in the input type and convert it to the output type.
|
||||
@ -1145,44 +1010,6 @@ UnpackPDU(DaemonSocketPDU& aPDU, nsTArray<T>& aOut)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* |UnpackCString0| is a helper for unpacking 0-terminated C string,
|
||||
* including the \0 character. Pass an instance of this structure
|
||||
* as the first argument to |UnpackPDU| to unpack a string.
|
||||
*/
|
||||
struct UnpackCString0
|
||||
{
|
||||
UnpackCString0(nsCString& aString)
|
||||
: mString(&aString)
|
||||
{ }
|
||||
|
||||
nsCString* mString; // non-null by construction
|
||||
};
|
||||
|
||||
/* This implementation of |UnpackPDU| unpacks a 0-terminated C string.
|
||||
*/
|
||||
nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, const UnpackCString0& aOut);
|
||||
|
||||
/* |UnpackString0| is a helper for unpacking 0-terminated C string,
|
||||
* including the \0 character. Pass an instance of this structure
|
||||
* as the first argument to |UnpackPDU| to unpack a C string and convert
|
||||
* it to wide-character encoding.
|
||||
*/
|
||||
struct UnpackString0
|
||||
{
|
||||
UnpackString0(nsString& aString)
|
||||
: mString(&aString)
|
||||
{ }
|
||||
|
||||
nsString* mString; // non-null by construction
|
||||
};
|
||||
|
||||
/* This implementation of |UnpackPDU| unpacks a 0-terminated C string
|
||||
* and converts it to wide-character encoding.
|
||||
*/
|
||||
nsresult
|
||||
UnpackPDU(DaemonSocketPDU& aPDU, const UnpackString0& aOut);
|
||||
|
||||
/* |UnpackReversed| is a helper for unpacking data in reversed order. Pass an
|
||||
* instance of this structure as the second argument to |UnpackPDU| to unpack
|
||||
* data in reversed order.
|
||||
@ -1240,39 +1067,6 @@ UnpackPDU<BluetoothUuid>(DaemonSocketPDU& aPDU,
|
||||
// Init operators
|
||||
//
|
||||
|
||||
// |PDUInitOP| provides functionality for init operators that unpack PDUs.
|
||||
class PDUInitOp
|
||||
{
|
||||
protected:
|
||||
PDUInitOp(DaemonSocketPDU& aPDU)
|
||||
: mPDU(&aPDU)
|
||||
{ }
|
||||
|
||||
DaemonSocketPDU& GetPDU() const
|
||||
{
|
||||
return *mPDU; // cannot be nullptr
|
||||
}
|
||||
|
||||
void WarnAboutTrailingData() const
|
||||
{
|
||||
size_t size = mPDU->GetSize();
|
||||
|
||||
if (MOZ_LIKELY(!size)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t service, opcode;
|
||||
uint16_t payloadSize;
|
||||
mPDU->GetHeader(service, opcode, payloadSize);
|
||||
|
||||
BT_LOGR("Unpacked PDU of type (%x,%x) still contains %zu Bytes of data.",
|
||||
service, opcode, size);
|
||||
}
|
||||
|
||||
private:
|
||||
DaemonSocketPDU* mPDU; // Hold pointer to allow for constant instances
|
||||
};
|
||||
|
||||
// |UnpackPDUInitOp| is a general-purpose init operator for all variants
|
||||
// of |BluetoothResultRunnable| and |BluetoothNotificationRunnable|. The
|
||||
// call operators of |UnpackPDUInitOp| unpack a PDU into the supplied
|
||||
|
@ -16,17 +16,16 @@
|
||||
#include "BluetoothDaemonHelpers.h"
|
||||
#include "BluetoothDaemonSetupInterface.h"
|
||||
#include "BluetoothDaemonSocketInterface.h"
|
||||
#include "BluetoothInterfaceHelpers.h"
|
||||
#include "mozilla/ipc/DaemonRunnables.h"
|
||||
#include "mozilla/ipc/DaemonSocket.h"
|
||||
#include "mozilla/ipc/ListenSocket.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "prrng.h"
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
static const int sRetryInterval = 100; // ms
|
||||
|
||||
//
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
//
|
||||
// Socket module
|
||||
//
|
||||
|
@ -9,12 +9,12 @@
|
||||
|
||||
#include "BluetoothDaemonHelpers.h"
|
||||
#include "BluetoothInterface.h"
|
||||
#include "BluetoothInterfaceHelpers.h"
|
||||
#include "mozilla/ipc/DaemonRunnables.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
using mozilla::ipc::DaemonSocketPDU;
|
||||
using mozilla::ipc::DaemonSocketPDUHeader;
|
||||
|
||||
class BluetoothDaemonSocketModule
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,277 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_bluetooth_bluedroid_bluetoothgatthalinterface_h__
|
||||
#define mozilla_dom_bluetooth_bluedroid_bluetoothgatthalinterface_h__
|
||||
|
||||
#include <hardware/bluetooth.h>
|
||||
#if ANDROID_VERSION >= 19
|
||||
#include <hardware/bt_gatt.h>
|
||||
#endif
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothInterface.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothHALInterface;
|
||||
|
||||
class BluetoothGattClientHALInterface final
|
||||
: public BluetoothGattClientInterface
|
||||
{
|
||||
public:
|
||||
friend class BluetoothGattHALInterface;
|
||||
|
||||
/* Register / Unregister */
|
||||
void RegisterClient(const BluetoothUuid& aUuid,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void UnregisterClient(int aClientIf,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Start / Stop LE Scan */
|
||||
void Scan(int aClientIf, bool aStart,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Connect / Disconnect */
|
||||
void Connect(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
bool aIsDirect, /* auto connect */
|
||||
BluetoothTransport aTransport,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void Disconnect(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
int aConnId,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Start / Stop advertisements to listen for incoming connections */
|
||||
void Listen(int aClientIf,
|
||||
bool aIsStart,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Clear the attribute cache for a given device*/
|
||||
void Refresh(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Enumerate Attributes */
|
||||
void SearchService(int aConnId,
|
||||
bool aSearchAll,
|
||||
const BluetoothUuid& aUuid,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void GetIncludedService(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
bool aFirst,
|
||||
const BluetoothGattServiceId& aStartServiceId,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void GetCharacteristic(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
bool aFirst,
|
||||
const BluetoothGattId& aStartCharId,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void GetDescriptor(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
bool aFirst,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Read / Write An Attribute */
|
||||
void ReadCharacteristic(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
BluetoothGattAuthReq aAuthReq,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void WriteCharacteristic(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
BluetoothGattWriteType aWriteType,
|
||||
BluetoothGattAuthReq aAuthReq,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void ReadDescriptor(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
BluetoothGattAuthReq aAuthReq,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void WriteDescriptor(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
BluetoothGattWriteType aWriteType,
|
||||
BluetoothGattAuthReq aAuthReq,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Execute / Abort Prepared Write*/
|
||||
void ExecuteWrite(int aConnId,
|
||||
int aIsExecute,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
|
||||
/* Register / Deregister Characteristic Notifications or Indications */
|
||||
void RegisterNotification(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
void DeregisterNotification(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
void ReadRemoteRssi(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
void GetDeviceType(const nsAString& aBdAddr,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
/* Set advertising data or scan response data */
|
||||
void SetAdvData(int aServerIf,
|
||||
bool aIsScanRsp,
|
||||
bool aIsNameIncluded,
|
||||
bool aIsTxPowerIncluded,
|
||||
int aMinInterval,
|
||||
int aMaxInterval,
|
||||
int aApperance,
|
||||
uint16_t aManufacturerLen, char* aManufacturerData,
|
||||
uint16_t aServiceDataLen, char* aServiceData,
|
||||
uint16_t aServiceUUIDLen, char* aServiceUUID,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
void TestCommand(int aCommand, const BluetoothGattTestParam& aTestParam,
|
||||
BluetoothGattClientResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
BluetoothGattClientHALInterface(
|
||||
#if ANDROID_VERSION >= 19
|
||||
const btgatt_client_interface_t* aInterface
|
||||
#endif
|
||||
);
|
||||
~BluetoothGattClientHALInterface();
|
||||
|
||||
private:
|
||||
#if ANDROID_VERSION >= 19
|
||||
const btgatt_client_interface_t* mInterface;
|
||||
#endif
|
||||
};
|
||||
|
||||
class BluetoothGattServerHALInterface final
|
||||
: public BluetoothGattServerInterface
|
||||
{
|
||||
public:
|
||||
friend class BluetoothGattHALInterface;
|
||||
|
||||
/* Register / Unregister */
|
||||
void RegisterServer(const BluetoothUuid& aUuid,
|
||||
BluetoothGattServerResultHandler* aRes);
|
||||
void UnregisterServer(int aServerIf,
|
||||
BluetoothGattServerResultHandler* aRes);
|
||||
|
||||
/* Connect / Disconnect */
|
||||
void ConnectPeripheral(int aServerIf,
|
||||
const nsAString& aBdAddr,
|
||||
bool aIsDirect, /* auto connect */
|
||||
BluetoothTransport aTransport,
|
||||
BluetoothGattServerResultHandler* aRes);
|
||||
void DisconnectPeripheral(int aServerIf,
|
||||
const nsAString& aBdAddr,
|
||||
int aConnId,
|
||||
BluetoothGattServerResultHandler* aRes);
|
||||
|
||||
/* Add a services / a characteristic / a descriptor */
|
||||
void AddService(int aServerIf,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
int aNumHandles,
|
||||
BluetoothGattServerResultHandler* aRes);
|
||||
void AddIncludedService(int aServerIf,
|
||||
int aServiceHandle,
|
||||
int aIncludedServiceHandle,
|
||||
BluetoothGattServerResultHandler* aRes);
|
||||
void AddCharacteristic(int aServerIf,
|
||||
int aServiceHandle,
|
||||
const BluetoothUuid& aUuid,
|
||||
BluetoothGattCharProp aProperties,
|
||||
BluetoothGattAttrPerm aPermissions,
|
||||
BluetoothGattServerResultHandler* aRes);
|
||||
void AddDescriptor(int aServerIf,
|
||||
int aServiceHandle,
|
||||
const BluetoothUuid& aUuid,
|
||||
BluetoothGattAttrPerm aPermissions,
|
||||
BluetoothGattServerResultHandler* aRes);
|
||||
|
||||
/* Start / Stop / Delete a service */
|
||||
void StartService(int aServerIf,
|
||||
int aServiceHandle,
|
||||
BluetoothTransport aTransport,
|
||||
BluetoothGattServerResultHandler* aRes);
|
||||
void StopService(int aServerIf,
|
||||
int aServiceHandle,
|
||||
BluetoothGattServerResultHandler* aRes);
|
||||
void DeleteService(int aServerIf,
|
||||
int aServiceHandle,
|
||||
BluetoothGattServerResultHandler* aRes);
|
||||
|
||||
/* Send an indication or a notification */
|
||||
void SendIndication(int aServerIf,
|
||||
int aAttributeHandle,
|
||||
int aConnId,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
bool aConfirm, /* true: indication, false: notification */
|
||||
BluetoothGattServerResultHandler* aRes);
|
||||
|
||||
/* Send a response for an incoming indication */
|
||||
void SendResponse(int aConnId,
|
||||
int aTransId,
|
||||
BluetoothGattStatus aStatus,
|
||||
const BluetoothGattResponse& aResponse,
|
||||
BluetoothGattServerResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
BluetoothGattServerHALInterface(
|
||||
#if ANDROID_VERSION >= 19
|
||||
const btgatt_server_interface_t* aInterface
|
||||
#endif
|
||||
);
|
||||
~BluetoothGattServerHALInterface();
|
||||
|
||||
private:
|
||||
#if ANDROID_VERSION >= 19
|
||||
const btgatt_server_interface_t* mInterface;
|
||||
#endif
|
||||
};
|
||||
|
||||
class BluetoothGattHALInterface final
|
||||
: public BluetoothGattInterface
|
||||
{
|
||||
public:
|
||||
friend class BluetoothHALInterface;
|
||||
|
||||
void Init(BluetoothGattNotificationHandler* aNotificationHandler,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
void Cleanup(BluetoothGattResultHandler* aRes);
|
||||
|
||||
BluetoothGattClientInterface* GetBluetoothGattClientInterface();
|
||||
BluetoothGattServerInterface* GetBluetoothGattServerInterface();
|
||||
|
||||
protected:
|
||||
BluetoothGattHALInterface(
|
||||
#if ANDROID_VERSION >= 19
|
||||
const btgatt_interface_t* aInterface
|
||||
#endif
|
||||
);
|
||||
~BluetoothGattHALInterface();
|
||||
|
||||
private:
|
||||
#if ANDROID_VERSION >= 19
|
||||
const btgatt_interface_t* mInterface;
|
||||
#endif
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,558 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BluetoothHALHelpers.h"
|
||||
|
||||
#define MAX_UUID_SIZE 16
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
//
|
||||
// Conversion
|
||||
//
|
||||
|
||||
nsresult
|
||||
Convert(const nsAString& aIn, bt_property_type_t& aOut)
|
||||
{
|
||||
if (aIn.EqualsLiteral("Name")) {
|
||||
aOut = BT_PROPERTY_BDNAME;
|
||||
} else if (aIn.EqualsLiteral("Discoverable")) {
|
||||
aOut = BT_PROPERTY_ADAPTER_SCAN_MODE;
|
||||
} else if (aIn.EqualsLiteral("DiscoverableTimeout")) {
|
||||
aOut = BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT;
|
||||
} else {
|
||||
BT_LOGR("Invalid property name: %s", NS_ConvertUTF16toUTF8(aIn).get());
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(ConvertNamedValue& aIn, bt_property_t& aOut)
|
||||
{
|
||||
nsresult rv = Convert(aIn.mNamedValue.name(), aOut.type);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (aIn.mNamedValue.value().type() == BluetoothValue::Tuint32_t) {
|
||||
// Set discoverable timeout
|
||||
aOut.val = const_cast<void*>(static_cast<const void*>(
|
||||
&(aIn.mNamedValue.value().get_uint32_t())));
|
||||
aOut.len = sizeof(uint32_t);
|
||||
} else if (aIn.mNamedValue.value().type() == BluetoothValue::TnsString) {
|
||||
// Set name
|
||||
aIn.mStringValue =
|
||||
NS_ConvertUTF16toUTF8(aIn.mNamedValue.value().get_nsString());
|
||||
aOut.val =
|
||||
const_cast<void*>(static_cast<const void*>(aIn.mStringValue.get()));
|
||||
aOut.len = strlen(static_cast<char*>(aOut.val));
|
||||
} else if (aIn.mNamedValue.value().type() == BluetoothValue::Tbool) {
|
||||
// Set scan mode
|
||||
rv = Convert(aIn.mNamedValue.value().get_bool(), aIn.mScanMode);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
aOut.val = &aIn.mScanMode;
|
||||
aOut.len = sizeof(aIn.mScanMode);
|
||||
} else {
|
||||
BT_LOGR("Invalid property value type");
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const nsAString& aIn, bt_bdaddr_t& aOut)
|
||||
{
|
||||
NS_ConvertUTF16toUTF8 bdAddressUTF8(aIn);
|
||||
const char* str = bdAddressUTF8.get();
|
||||
|
||||
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(aOut.address); ++i, ++str) {
|
||||
aOut.address[i] =
|
||||
static_cast<uint8_t>(strtoul(str, const_cast<char**>(&str), 16));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const BluetoothSspVariant aIn, bt_ssp_variant_t& aOut)
|
||||
{
|
||||
static const bt_ssp_variant_t sSspVariant[] = {
|
||||
CONVERT(SSP_VARIANT_PASSKEY_CONFIRMATION,
|
||||
BT_SSP_VARIANT_PASSKEY_CONFIRMATION),
|
||||
CONVERT(SSP_VARIANT_PASSKEY_ENTRY, BT_SSP_VARIANT_PASSKEY_ENTRY),
|
||||
CONVERT(SSP_VARIANT_CONSENT, BT_SSP_VARIANT_CONSENT),
|
||||
CONVERT(SSP_VARIANT_PASSKEY_NOTIFICATION,
|
||||
BT_SSP_VARIANT_PASSKEY_NOTIFICATION)
|
||||
};
|
||||
if (aIn >= MOZ_ARRAY_LENGTH(sSspVariant)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
aOut = sSspVariant[aIn];
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const uint8_t aIn[16], bt_uuid_t& aOut)
|
||||
{
|
||||
if (sizeof(aOut.uu) != 16) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
memcpy(aOut.uu, aIn, sizeof(aOut.uu));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const bt_uuid_t& aIn, BluetoothUuid& aOut)
|
||||
{
|
||||
if (sizeof(aIn.uu) != sizeof(aOut.mUuid)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
memcpy(aOut.mUuid, aIn.uu, sizeof(aOut.mUuid));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const BluetoothUuid& aIn, bt_uuid_t& aOut)
|
||||
{
|
||||
if (sizeof(aIn.mUuid) != sizeof(aOut.uu)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
memcpy(aOut.uu, aIn.mUuid, sizeof(aOut.uu));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const nsAString& aIn, bt_pin_code_t& aOut)
|
||||
{
|
||||
if (aIn.Length() > MOZ_ARRAY_LENGTH(aOut.pin)) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 pinCodeUTF8(aIn);
|
||||
const char* str = pinCodeUTF8.get();
|
||||
|
||||
nsAString::size_type i;
|
||||
|
||||
// Fill pin into aOut
|
||||
for (i = 0; i < aIn.Length(); ++i, ++str) {
|
||||
aOut.pin[i] = static_cast<uint8_t>(*str);
|
||||
}
|
||||
|
||||
// Clear remaining bytes in aOut
|
||||
size_t ntrailing =
|
||||
(MOZ_ARRAY_LENGTH(aOut.pin) - aIn.Length()) * sizeof(aOut.pin[0]);
|
||||
memset(aOut.pin + aIn.Length(), 0, ntrailing);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const bt_bdaddr_t& aIn, nsAString& aOut)
|
||||
{
|
||||
char str[BLUETOOTH_ADDRESS_LENGTH + 1];
|
||||
|
||||
int res = snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
static_cast<int>(aIn.address[0]),
|
||||
static_cast<int>(aIn.address[1]),
|
||||
static_cast<int>(aIn.address[2]),
|
||||
static_cast<int>(aIn.address[3]),
|
||||
static_cast<int>(aIn.address[4]),
|
||||
static_cast<int>(aIn.address[5]));
|
||||
if (res < 0) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
} else if ((size_t)res >= sizeof(str)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY; /* string buffer too small */
|
||||
}
|
||||
|
||||
aOut = NS_ConvertUTF8toUTF16(str);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const bt_service_record_t& aIn, BluetoothServiceRecord& aOut)
|
||||
{
|
||||
nsresult rv = Convert(aIn.uuid, aOut.mUuid);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
aOut.mChannel = aIn.channel;
|
||||
|
||||
MOZ_ASSERT(sizeof(aIn.name) == sizeof(aOut.mName));
|
||||
memcpy(aOut.mName, aIn.name, sizeof(aOut.mName));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const uint8_t* aIn, BluetoothGattAdvData& aOut)
|
||||
{
|
||||
memcpy(aOut.mAdvData, aIn, sizeof(aOut.mAdvData));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#if ANDROID_VERSION >= 18
|
||||
nsresult
|
||||
Convert(const BluetoothAvrcpElementAttribute& aIn, btrc_element_attr_val_t& aOut)
|
||||
{
|
||||
const NS_ConvertUTF16toUTF8 value(aIn.mValue);
|
||||
size_t len = std::min<size_t>(strlen(value.get()), sizeof(aOut.text) - 1);
|
||||
|
||||
memcpy(aOut.text, value.get(), len);
|
||||
aOut.text[len] = '\0';
|
||||
aOut.attr_id = aIn.mId;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const btrc_player_settings_t& aIn, BluetoothAvrcpPlayerSettings& aOut)
|
||||
{
|
||||
aOut.mNumAttr = aIn.num_attr;
|
||||
memcpy(aOut.mIds, aIn.attr_ids, aIn.num_attr);
|
||||
memcpy(aOut.mValues, aIn.attr_values, aIn.num_attr);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif // ANDROID_VERSION >= 18
|
||||
|
||||
#if ANDROID_VERSION >= 19
|
||||
nsresult
|
||||
Convert(const BluetoothGattId& aIn, btgatt_gatt_id_t& aOut)
|
||||
{
|
||||
nsresult rv = Convert(aIn.mUuid, aOut.uuid);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
// HAL uses reversed UUID for GATT
|
||||
for (uint8_t i = 0; i < sizeof(aOut.uuid.uu) / 2; i++) {
|
||||
auto temp = aOut.uuid.uu[i];
|
||||
aOut.uuid.uu[i] = aOut.uuid.uu[sizeof(aOut.uuid.uu) - i - 1];
|
||||
aOut.uuid.uu[sizeof(aOut.uuid.uu) - i - 1] = temp;
|
||||
}
|
||||
aOut.inst_id = aIn.mInstanceId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const btgatt_gatt_id_t& aIn, BluetoothGattId& aOut)
|
||||
{
|
||||
nsresult rv = Convert(aIn.uuid, aOut.mUuid);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
// HAL uses reversed UUID for GATT
|
||||
for (uint8_t i = 0; i < sizeof(aOut.mUuid.mUuid) / 2; i++) {
|
||||
auto temp = aOut.mUuid.mUuid[i];
|
||||
aOut.mUuid.mUuid[i] = aOut.mUuid.mUuid[sizeof(aOut.mUuid.mUuid) - i - 1];
|
||||
aOut.mUuid.mUuid[sizeof(aOut.mUuid.mUuid) - i - 1] = temp;
|
||||
}
|
||||
aOut.mInstanceId = aIn.inst_id;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const BluetoothGattServiceId& aIn, btgatt_srvc_id_t& aOut)
|
||||
{
|
||||
aOut.is_primary = aIn.mIsPrimary;
|
||||
return Convert(aIn.mId, aOut.id);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const btgatt_srvc_id_t& aIn, BluetoothGattServiceId& aOut)
|
||||
{
|
||||
aOut.mIsPrimary = aIn.is_primary;
|
||||
return Convert(aIn.id, aOut.mId);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const btgatt_read_params_t& aIn, BluetoothGattReadParam& aOut)
|
||||
{
|
||||
nsresult rv = Convert(aIn.srvc_id, aOut.mServiceId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = Convert(aIn.char_id, aOut.mCharId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = Convert(aIn.descr_id, aOut.mDescriptorId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
memcpy(aOut.mValue, aIn.value.value, aIn.value.len);
|
||||
aOut.mValueLength = aIn.value.len;
|
||||
aOut.mValueType = aIn.value_type;
|
||||
aOut.mStatus = aIn.status;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const btgatt_write_params_t& aIn, BluetoothGattWriteParam& aOut)
|
||||
{
|
||||
nsresult rv = Convert(aIn.srvc_id, aOut.mServiceId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = Convert(aIn.char_id, aOut.mCharId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = Convert(aIn.descr_id, aOut.mDescriptorId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
aOut.mStatus = aIn.status;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const btgatt_notify_params_t& aIn, BluetoothGattNotifyParam& aOut)
|
||||
{
|
||||
nsresult rv = Convert(aIn.bda, aOut.mBdAddr);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = Convert(aIn.srvc_id, aOut.mServiceId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = Convert(aIn.char_id, aOut.mCharId);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
memcpy(aOut.mValue, aIn.value, aIn.len);
|
||||
aOut.mLength = aIn.len;
|
||||
aOut.mIsNotify = (aIn.is_notify != 0);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const BluetoothGattTestParam& aIn, btgatt_test_params_t& aOut)
|
||||
{
|
||||
nsresult rv = Convert(aIn.mBdAddr, *aOut.bda1);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = Convert(aIn.mUuid, *aOut.uuid1);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = Convert(aIn.mU1, aOut.u1);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = Convert(aIn.mU2, aOut.u2);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = Convert(aIn.mU3, aOut.u3);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = Convert(aIn.mU4, aOut.u4);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = Convert(aIn.mU5, aOut.u5);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const BluetoothGattResponse& aIn, btgatt_response_t& aOut)
|
||||
{
|
||||
// Only the read response format is used in bluedroid.
|
||||
nsresult rv = Convert(
|
||||
ConvertArray<uint8_t>(aIn.mValue, sizeof(aIn.mValue)),
|
||||
aOut.attr_value.value);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = Convert(aIn.mHandle, aOut.attr_value.handle);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = Convert(aIn.mOffset, aOut.attr_value.offset);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = Convert(aIn.mLength, aOut.attr_value.len);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = Convert(aIn.mAuthReq, aOut.attr_value.auth_req);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif // ANDROID_VERSION >= 19
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
nsresult
|
||||
Convert(const BluetoothTransport& aIn, btgatt_transport_t& aOut)
|
||||
{
|
||||
static const btgatt_transport_t sTransport[] = {
|
||||
CONVERT(TRANSPORT_AUTO, GATT_TRANSPORT_AUTO),
|
||||
CONVERT(TRANSPORT_BREDR, GATT_TRANSPORT_BREDR),
|
||||
CONVERT(TRANSPORT_LE, GATT_TRANSPORT_LE)
|
||||
};
|
||||
if (aIn >= MOZ_ARRAY_LENGTH(sTransport)) {
|
||||
aOut = static_cast<btgatt_transport_t>(0); // silence compiler warning
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
aOut = sTransport[aIn];
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Convert(const bt_activity_energy_info& aIn, BluetoothActivityEnergyInfo& aOut)
|
||||
{
|
||||
nsresult rv = Convert(aIn.status, aOut.mStatus);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
rv = Convert(aIn.ctrl_state, aOut.mStackState);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
rv = Convert(aIn.tx_time, aOut.mTxTime);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
rv = Convert(aIn.rx_time, aOut.mRxTime);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
rv = Convert(aIn.idle_time, aOut.mIdleTime);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
rv = Convert(aIn.energy_used, aOut.mEnergyUsed);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif // ANDROID_VERSION >= 21
|
||||
|
||||
nsresult
|
||||
Convert(const bt_property_t& aIn, BluetoothProperty& aOut)
|
||||
{
|
||||
/* type conversion */
|
||||
|
||||
nsresult rv = Convert(aIn.type, aOut.mType);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* value conversion */
|
||||
|
||||
switch (aOut.mType) {
|
||||
case PROPERTY_UNKNOWN:
|
||||
/* Bug 1065999: working around unknown properties */
|
||||
break;
|
||||
case PROPERTY_BDNAME:
|
||||
/* fall through */
|
||||
case PROPERTY_REMOTE_FRIENDLY_NAME:
|
||||
{
|
||||
// We construct an nsCString here because bdname
|
||||
// returned from Bluedroid is not 0-terminated.
|
||||
aOut.mString = NS_ConvertUTF8toUTF16(
|
||||
nsCString(static_cast<char*>(aIn.val), aIn.len));
|
||||
}
|
||||
break;
|
||||
case PROPERTY_BDADDR:
|
||||
rv = Convert(*static_cast<bt_bdaddr_t*>(aIn.val), aOut.mString);
|
||||
break;
|
||||
case PROPERTY_UUIDS:
|
||||
{
|
||||
size_t numUuids = aIn.len / MAX_UUID_SIZE;
|
||||
ConvertArray<bt_uuid_t> array(
|
||||
static_cast<bt_uuid_t*>(aIn.val), numUuids);
|
||||
aOut.mUuidArray.SetLength(numUuids);
|
||||
rv = Convert(array, aOut.mUuidArray);
|
||||
}
|
||||
break;
|
||||
case PROPERTY_CLASS_OF_DEVICE:
|
||||
/* fall through */
|
||||
case PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
|
||||
aOut.mUint32 = *static_cast<uint32_t*>(aIn.val);
|
||||
break;
|
||||
case PROPERTY_TYPE_OF_DEVICE:
|
||||
rv = Convert(*static_cast<bt_device_type_t*>(aIn.val),
|
||||
aOut.mTypeOfDevice);
|
||||
break;
|
||||
case PROPERTY_SERVICE_RECORD:
|
||||
rv = Convert(*static_cast<bt_service_record_t*>(aIn.val),
|
||||
aOut.mServiceRecord);
|
||||
break;
|
||||
case PROPERTY_ADAPTER_SCAN_MODE:
|
||||
rv = Convert(*static_cast<bt_scan_mode_t*>(aIn.val),
|
||||
aOut.mScanMode);
|
||||
break;
|
||||
case PROPERTY_ADAPTER_BONDED_DEVICES:
|
||||
{
|
||||
size_t numAddresses = aIn.len / BLUETOOTH_ADDRESS_BYTES;
|
||||
ConvertArray<bt_bdaddr_t> array(
|
||||
static_cast<bt_bdaddr_t*>(aIn.val), numAddresses);
|
||||
aOut.mStringArray.SetLength(numAddresses);
|
||||
rv = Convert(array, aOut.mStringArray);
|
||||
}
|
||||
break;
|
||||
case PROPERTY_REMOTE_RSSI:
|
||||
aOut.mInt32 = *static_cast<int8_t*>(aIn.val);
|
||||
break;
|
||||
#if ANDROID_VERSION >= 18
|
||||
case PROPERTY_REMOTE_VERSION_INFO:
|
||||
rv = Convert(*static_cast<bt_remote_version_t*>(aIn.val),
|
||||
aOut.mRemoteInfo);
|
||||
break;
|
||||
#endif
|
||||
case PROPERTY_REMOTE_DEVICE_TIMESTAMP:
|
||||
/* nothing to do */
|
||||
break;
|
||||
default:
|
||||
/* mismatch with type conversion */
|
||||
NS_NOTREACHED("Unhandled property type");
|
||||
break;
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,121 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_bluetooth_bluedroid_bluetoothhalinterface_h__
|
||||
#define mozilla_dom_bluetooth_bluedroid_bluetoothhalinterface_h__
|
||||
|
||||
#include <hardware/bluetooth.h>
|
||||
#include "BluetoothInterface.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothHALInterface final : public BluetoothInterface
|
||||
{
|
||||
public:
|
||||
static BluetoothHALInterface* GetInstance();
|
||||
|
||||
void Init(BluetoothNotificationHandler* aNotificationHandler,
|
||||
BluetoothResultHandler* aRes);
|
||||
void Cleanup(BluetoothResultHandler* aRes);
|
||||
|
||||
void Enable(BluetoothResultHandler* aRes);
|
||||
void Disable(BluetoothResultHandler* aRes);
|
||||
|
||||
|
||||
/* Adapter Properties */
|
||||
|
||||
void GetAdapterProperties(BluetoothResultHandler* aRes);
|
||||
void GetAdapterProperty(const nsAString& aName,
|
||||
BluetoothResultHandler* aRes);
|
||||
void SetAdapterProperty(const BluetoothNamedValue& aProperty,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
/* Remote Device Properties */
|
||||
|
||||
void GetRemoteDeviceProperties(const nsAString& aRemoteAddr,
|
||||
BluetoothResultHandler* aRes);
|
||||
void GetRemoteDeviceProperty(const nsAString& aRemoteAddr,
|
||||
const nsAString& aName,
|
||||
BluetoothResultHandler* aRes);
|
||||
void SetRemoteDeviceProperty(const nsAString& aRemoteAddr,
|
||||
const BluetoothNamedValue& aProperty,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
/* Remote Services */
|
||||
|
||||
void GetRemoteServiceRecord(const nsAString& aRemoteAddr,
|
||||
const uint8_t aUuid[16],
|
||||
BluetoothResultHandler* aRes);
|
||||
void GetRemoteServices(const nsAString& aRemoteAddr,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
/* Discovery */
|
||||
|
||||
void StartDiscovery(BluetoothResultHandler* aRes);
|
||||
void CancelDiscovery(BluetoothResultHandler* aRes);
|
||||
|
||||
/* Bonds */
|
||||
|
||||
void CreateBond(const nsAString& aBdAddr, BluetoothTransport aTransport,
|
||||
BluetoothResultHandler* aRes);
|
||||
void RemoveBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes);
|
||||
void CancelBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes);
|
||||
|
||||
/* Connection */
|
||||
|
||||
void GetConnectionState(const nsAString& aBdAddr,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
/* Authentication */
|
||||
|
||||
void PinReply(const nsAString& aBdAddr, bool aAccept,
|
||||
const nsAString& aPinCode,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
void SspReply(const nsAString& aBdAddr, BluetoothSspVariant aVariant,
|
||||
bool aAccept, uint32_t aPasskey,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
/* DUT Mode */
|
||||
|
||||
void DutModeConfigure(bool aEnable, BluetoothResultHandler* aRes);
|
||||
void DutModeSend(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
/* LE Mode */
|
||||
|
||||
void LeTestMode(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
|
||||
BluetoothResultHandler* aRes);
|
||||
|
||||
/* Energy Information */
|
||||
|
||||
void ReadEnergyInfo(BluetoothResultHandler* aRes);
|
||||
|
||||
/* Profile Interfaces */
|
||||
|
||||
BluetoothSocketInterface* GetBluetoothSocketInterface();
|
||||
BluetoothHandsfreeInterface* GetBluetoothHandsfreeInterface();
|
||||
BluetoothA2dpInterface* GetBluetoothA2dpInterface();
|
||||
BluetoothAvrcpInterface* GetBluetoothAvrcpInterface();
|
||||
BluetoothGattInterface* GetBluetoothGattInterface();
|
||||
|
||||
protected:
|
||||
BluetoothHALInterface(const bt_interface_t* aInterface);
|
||||
~BluetoothHALInterface();
|
||||
|
||||
private:
|
||||
template <class T>
|
||||
T* CreateProfileInterface();
|
||||
|
||||
template <class T>
|
||||
T* GetProfileInterface();
|
||||
|
||||
const bt_interface_t* mInterface;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,957 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BluetoothHandsfreeHALInterface.h"
|
||||
#include "BluetoothHALHelpers.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
typedef
|
||||
BluetoothHALInterfaceRunnable0<BluetoothHandsfreeResultHandler, void>
|
||||
BluetoothHandsfreeHALResultRunnable;
|
||||
|
||||
typedef
|
||||
BluetoothHALInterfaceRunnable1<BluetoothHandsfreeResultHandler, void,
|
||||
BluetoothStatus, BluetoothStatus>
|
||||
BluetoothHandsfreeHALErrorRunnable;
|
||||
|
||||
static nsresult
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
BluetoothHandsfreeResultHandler* aRes,
|
||||
void (BluetoothHandsfreeResultHandler::*aMethod)(),
|
||||
BluetoothStatus aStatus)
|
||||
{
|
||||
MOZ_ASSERT(aRes);
|
||||
|
||||
nsRefPtr<nsRunnable> runnable;
|
||||
|
||||
if (aStatus == STATUS_SUCCESS) {
|
||||
runnable = new BluetoothHandsfreeHALResultRunnable(aRes, aMethod);
|
||||
} else {
|
||||
runnable = new BluetoothHandsfreeHALErrorRunnable(aRes,
|
||||
&BluetoothHandsfreeResultHandler::OnError, aStatus);
|
||||
}
|
||||
nsresult rv = NS_DispatchToMainThread(runnable);
|
||||
if (NS_FAILED(rv)) {
|
||||
BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Notification handling
|
||||
//
|
||||
|
||||
static BluetoothHandsfreeNotificationHandler* sHandsfreeNotificationHandler;
|
||||
|
||||
struct BluetoothHandsfreeHALCallback
|
||||
{
|
||||
class HandsfreeNotificationHandlerWrapper
|
||||
{
|
||||
public:
|
||||
typedef BluetoothHandsfreeNotificationHandler ObjectType;
|
||||
|
||||
static ObjectType* GetInstance()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
return sHandsfreeNotificationHandler;
|
||||
}
|
||||
};
|
||||
|
||||
// Notifications
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
BluetoothHandsfreeConnectionState, nsString,
|
||||
BluetoothHandsfreeConnectionState, const nsAString&>
|
||||
ConnectionStateNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
BluetoothHandsfreeAudioState, nsString,
|
||||
BluetoothHandsfreeAudioState, const nsAString&>
|
||||
AudioStateNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
BluetoothHandsfreeVoiceRecognitionState, nsString,
|
||||
BluetoothHandsfreeVoiceRecognitionState, const nsAString&>
|
||||
VoiceRecognitionNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable1<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
nsString, const nsAString&>
|
||||
AnswerCallNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable1<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
nsString, const nsAString&>
|
||||
HangupCallNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable3<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
BluetoothHandsfreeVolumeType, int, nsString,
|
||||
BluetoothHandsfreeVolumeType, int, const nsAString&>
|
||||
VolumeNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
nsString, nsString, const nsAString&, const nsAString&>
|
||||
DialCallNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
char, nsString, char, const nsAString&>
|
||||
DtmfNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
BluetoothHandsfreeNRECState, nsString,
|
||||
BluetoothHandsfreeNRECState, const nsAString&>
|
||||
NRECNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
BluetoothHandsfreeWbsConfig, nsString,
|
||||
BluetoothHandsfreeWbsConfig, const nsAString&>
|
||||
WbsNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
BluetoothHandsfreeCallHoldType, nsString,
|
||||
BluetoothHandsfreeCallHoldType, const nsAString&>
|
||||
CallHoldNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable1<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
nsString, const nsAString&>
|
||||
CnumNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable1<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
nsString, const nsAString&>
|
||||
CindNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable1<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
nsString, const nsAString&>
|
||||
CopsNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable1<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
nsString, const nsAString&>
|
||||
ClccNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable2<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
nsCString, nsString, const nsACString&, const nsAString&>
|
||||
UnknownAtNotification;
|
||||
|
||||
typedef BluetoothNotificationHALRunnable1<
|
||||
HandsfreeNotificationHandlerWrapper, void,
|
||||
nsString, const nsAString&>
|
||||
KeyPressedNotification;
|
||||
|
||||
// Bluedroid Handsfree callbacks
|
||||
|
||||
static void
|
||||
ConnectionState(bthf_connection_state_t aState, bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
#if ANDROID_VERSION < 21
|
||||
if (aState == BTHF_CONNECTION_STATE_CONNECTED && aBdAddr) {
|
||||
memcpy(&sConnectedDeviceAddress, aBdAddr,
|
||||
sizeof(sConnectedDeviceAddress));
|
||||
} else if (aState == BTHF_CONNECTION_STATE_DISCONNECTED) {
|
||||
memset(&sConnectedDeviceAddress, 0,
|
||||
sizeof(sConnectedDeviceAddress));
|
||||
}
|
||||
#endif
|
||||
|
||||
ConnectionStateNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::ConnectionStateNotification,
|
||||
aState, aBdAddr);
|
||||
}
|
||||
|
||||
static void
|
||||
AudioState(bthf_audio_state_t aState, bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
AudioStateNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::AudioStateNotification,
|
||||
aState, aBdAddr);
|
||||
}
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
VoiceRecognition(bthf_vr_state_t aState, bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
VoiceRecognitionNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::VoiceRecognitionNotification,
|
||||
aState, aBdAddr);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
VoiceRecognition(bthf_vr_state_t aState)
|
||||
{
|
||||
VoiceRecognitionNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::VoiceRecognitionNotification,
|
||||
aState, &sConnectedDeviceAddress);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
AnswerCall(bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
AnswerCallNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::AnswerCallNotification,
|
||||
aBdAddr);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
AnswerCall()
|
||||
{
|
||||
AnswerCallNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::AnswerCallNotification,
|
||||
&sConnectedDeviceAddress);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
HangupCall(bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
HangupCallNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::HangupCallNotification,
|
||||
aBdAddr);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
HangupCall()
|
||||
{
|
||||
HangupCallNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::HangupCallNotification,
|
||||
&sConnectedDeviceAddress);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
Volume(bthf_volume_type_t aType, int aVolume, bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
VolumeNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::VolumeNotification,
|
||||
aType, aVolume, aBdAddr);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
Volume(bthf_volume_type_t aType, int aVolume)
|
||||
{
|
||||
VolumeNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::VolumeNotification,
|
||||
aType, aVolume, &sConnectedDeviceAddress);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
DialCall(char* aNumber, bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
DialCallNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::DialCallNotification,
|
||||
aNumber, aBdAddr);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
DialCall(char* aNumber)
|
||||
{
|
||||
DialCallNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::DialCallNotification,
|
||||
aNumber, &sConnectedDeviceAddress);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
Dtmf(char aDtmf, bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
DtmfNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::DtmfNotification,
|
||||
aDtmf, aBdAddr);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
Dtmf(char aDtmf)
|
||||
{
|
||||
DtmfNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::DtmfNotification,
|
||||
aDtmf, &sConnectedDeviceAddress);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
NoiseReductionEchoCancellation(bthf_nrec_t aNrec, bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
NRECNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::NRECNotification,
|
||||
aNrec, aBdAddr);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
NoiseReductionEchoCancellation(bthf_nrec_t aNrec)
|
||||
{
|
||||
NRECNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::NRECNotification,
|
||||
aNrec, &sConnectedDeviceAddress);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
WideBandSpeech(bthf_wbs_config_t aWbs, bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
WbsNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::WbsNotification,
|
||||
aWbs, aBdAddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
CallHold(bthf_chld_type_t aChld, bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
CallHoldNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::CallHoldNotification,
|
||||
aChld, aBdAddr);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
CallHold(bthf_chld_type_t aChld)
|
||||
{
|
||||
CallHoldNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::CallHoldNotification,
|
||||
aChld, &sConnectedDeviceAddress);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
Cnum(bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
CnumNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::CnumNotification,
|
||||
aBdAddr);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
Cnum()
|
||||
{
|
||||
CnumNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::CnumNotification,
|
||||
&sConnectedDeviceAddress);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
Cind(bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
CindNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::CindNotification,
|
||||
aBdAddr);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
Cind()
|
||||
{
|
||||
CindNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::CindNotification,
|
||||
&sConnectedDeviceAddress);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
Cops(bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
CopsNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::CopsNotification,
|
||||
aBdAddr);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
Cops()
|
||||
{
|
||||
CopsNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::CopsNotification,
|
||||
&sConnectedDeviceAddress);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
Clcc(bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
ClccNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::ClccNotification,
|
||||
aBdAddr);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
Clcc()
|
||||
{
|
||||
ClccNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::ClccNotification,
|
||||
&sConnectedDeviceAddress);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
UnknownAt(char* aAtString, bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
UnknownAtNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::UnknownAtNotification,
|
||||
aAtString, aBdAddr);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
UnknownAt(char* aAtString)
|
||||
{
|
||||
UnknownAtNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::UnknownAtNotification,
|
||||
aAtString, &sConnectedDeviceAddress);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
static void
|
||||
KeyPressed(bt_bdaddr_t* aBdAddr)
|
||||
{
|
||||
KeyPressedNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::KeyPressedNotification,
|
||||
aBdAddr);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
KeyPressed()
|
||||
{
|
||||
KeyPressedNotification::Dispatch(
|
||||
&BluetoothHandsfreeNotificationHandler::KeyPressedNotification,
|
||||
&sConnectedDeviceAddress);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ANDROID_VERSION < 21
|
||||
/* |sConnectedDeviceAddress| stores Bluetooth device address of the
|
||||
* connected device. Before Android Lollipop, we maintain this address by
|
||||
* ourselves through ConnectionState(); after Android Lollipop, every callback
|
||||
* carries this address directly so we don't have to keep it.
|
||||
*/
|
||||
static bt_bdaddr_t sConnectedDeviceAddress;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if ANDROID_VERSION < 21
|
||||
bt_bdaddr_t BluetoothHandsfreeHALCallback::sConnectedDeviceAddress = {
|
||||
{0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
// Interface
|
||||
//
|
||||
|
||||
BluetoothHandsfreeHALInterface::BluetoothHandsfreeHALInterface(
|
||||
const bthf_interface_t* aInterface)
|
||||
: mInterface(aInterface)
|
||||
{
|
||||
MOZ_ASSERT(mInterface);
|
||||
}
|
||||
|
||||
BluetoothHandsfreeHALInterface::~BluetoothHandsfreeHALInterface()
|
||||
{ }
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::Init(
|
||||
BluetoothHandsfreeNotificationHandler* aNotificationHandler,
|
||||
int aMaxNumClients, BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
static bthf_callbacks_t sCallbacks = {
|
||||
sizeof(sCallbacks),
|
||||
BluetoothHandsfreeHALCallback::ConnectionState,
|
||||
BluetoothHandsfreeHALCallback::AudioState,
|
||||
BluetoothHandsfreeHALCallback::VoiceRecognition,
|
||||
BluetoothHandsfreeHALCallback::AnswerCall,
|
||||
BluetoothHandsfreeHALCallback::HangupCall,
|
||||
BluetoothHandsfreeHALCallback::Volume,
|
||||
BluetoothHandsfreeHALCallback::DialCall,
|
||||
BluetoothHandsfreeHALCallback::Dtmf,
|
||||
BluetoothHandsfreeHALCallback::NoiseReductionEchoCancellation,
|
||||
#if ANDROID_VERSION >= 21
|
||||
BluetoothHandsfreeHALCallback::WideBandSpeech,
|
||||
#endif
|
||||
BluetoothHandsfreeHALCallback::CallHold,
|
||||
BluetoothHandsfreeHALCallback::Cnum,
|
||||
BluetoothHandsfreeHALCallback::Cind,
|
||||
BluetoothHandsfreeHALCallback::Cops,
|
||||
BluetoothHandsfreeHALCallback::Clcc,
|
||||
BluetoothHandsfreeHALCallback::UnknownAt,
|
||||
BluetoothHandsfreeHALCallback::KeyPressed
|
||||
};
|
||||
|
||||
sHandsfreeNotificationHandler = aNotificationHandler;
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
bt_status_t status = mInterface->init(&sCallbacks, aMaxNumClients);
|
||||
#else
|
||||
bt_status_t status = mInterface->init(&sCallbacks);
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::Init,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::Cleanup(
|
||||
BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
mInterface->cleanup();
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::Cleanup, STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
/* Connect / Disconnect */
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::Connect(
|
||||
const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
bt_bdaddr_t bdAddr;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
|
||||
status = mInterface->connect(&bdAddr);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::Connect,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::Disconnect(
|
||||
const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
bt_bdaddr_t bdAddr;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
|
||||
status = mInterface->disconnect(&bdAddr);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::Disconnect,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::ConnectAudio(
|
||||
const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
bt_bdaddr_t bdAddr;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
|
||||
status = mInterface->connect_audio(&bdAddr);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::ConnectAudio,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::DisconnectAudio(
|
||||
const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
bt_bdaddr_t bdAddr;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
|
||||
status = mInterface->disconnect_audio(&bdAddr);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::DisconnectAudio,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
/* Voice Recognition */
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::StartVoiceRecognition(
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
bt_bdaddr_t bdAddr;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
|
||||
status = mInterface->start_voice_recognition(&bdAddr);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
#else
|
||||
status = mInterface->start_voice_recognition();
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::StartVoiceRecognition,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::StopVoiceRecognition(
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
bt_bdaddr_t bdAddr;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
|
||||
status = mInterface->stop_voice_recognition(&bdAddr);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
#else
|
||||
status = mInterface->stop_voice_recognition();
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::StopVoiceRecognition,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
/* Volume */
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::VolumeControl(
|
||||
BluetoothHandsfreeVolumeType aType, int aVolume, const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
bthf_volume_type_t type = BTHF_VOLUME_TYPE_SPK;
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
bt_bdaddr_t bdAddr;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aType, type)) &&
|
||||
NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
|
||||
status = mInterface->volume_control(type, aVolume, &bdAddr);
|
||||
#else
|
||||
if (NS_SUCCEEDED(Convert(aType, type))) {
|
||||
status = mInterface->volume_control(type, aVolume);
|
||||
#endif
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::VolumeControl,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
/* Device status */
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::DeviceStatusNotification(
|
||||
BluetoothHandsfreeNetworkState aNtkState,
|
||||
BluetoothHandsfreeServiceType aSvcType, int aSignal,
|
||||
int aBattChg, BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
bthf_network_state_t ntkState = BTHF_NETWORK_STATE_NOT_AVAILABLE;
|
||||
bthf_service_type_t svcType = BTHF_SERVICE_TYPE_HOME;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aNtkState, ntkState)) &&
|
||||
NS_SUCCEEDED(Convert(aSvcType, svcType))) {
|
||||
status = mInterface->device_status_notification(ntkState, svcType,
|
||||
aSignal, aBattChg);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::DeviceStatusNotification,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
/* Responses */
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::CopsResponse(
|
||||
const char* aCops, const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
bt_bdaddr_t bdAddr;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
|
||||
status = mInterface->cops_response(aCops, &bdAddr);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
#else
|
||||
status = mInterface->cops_response(aCops);
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::CopsResponse,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::CindResponse(
|
||||
int aSvc, int aNumActive, int aNumHeld,
|
||||
BluetoothHandsfreeCallState aCallSetupState,
|
||||
int aSignal, int aRoam, int aBattChg,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
bthf_call_state_t callSetupState = BTHF_CALL_STATE_ACTIVE;
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
bt_bdaddr_t bdAddr;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aCallSetupState, callSetupState)) &&
|
||||
NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
|
||||
status = mInterface->cind_response(aSvc, aNumActive, aNumHeld,
|
||||
callSetupState, aSignal,
|
||||
aRoam, aBattChg, &bdAddr);
|
||||
#else
|
||||
if (NS_SUCCEEDED(Convert(aCallSetupState, callSetupState))) {
|
||||
status = mInterface->cind_response(aSvc, aNumActive, aNumHeld,
|
||||
callSetupState, aSignal,
|
||||
aRoam, aBattChg);
|
||||
#endif
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::CindResponse,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::FormattedAtResponse(
|
||||
const char* aRsp, const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
bt_bdaddr_t bdAddr;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
|
||||
status = mInterface->formatted_at_response(aRsp, &bdAddr);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
#else
|
||||
status = mInterface->formatted_at_response(aRsp);
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::FormattedAtResponse,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::AtResponse(
|
||||
BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
bthf_at_response_t responseCode = BTHF_AT_RESPONSE_ERROR;
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
bt_bdaddr_t bdAddr;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aResponseCode, responseCode)) &&
|
||||
NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
|
||||
status = mInterface->at_response(responseCode, aErrorCode, &bdAddr);
|
||||
#else
|
||||
if (NS_SUCCEEDED(Convert(aResponseCode, responseCode))) {
|
||||
status = mInterface->at_response(responseCode, aErrorCode);
|
||||
#endif
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::AtResponse,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::ClccResponse(
|
||||
int aIndex,
|
||||
BluetoothHandsfreeCallDirection aDir,
|
||||
BluetoothHandsfreeCallState aState,
|
||||
BluetoothHandsfreeCallMode aMode,
|
||||
BluetoothHandsfreeCallMptyType aMpty,
|
||||
const nsAString& aNumber,
|
||||
BluetoothHandsfreeCallAddressType aType,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
bthf_call_direction_t dir = BTHF_CALL_DIRECTION_OUTGOING;
|
||||
bthf_call_state_t state = BTHF_CALL_STATE_ACTIVE;
|
||||
bthf_call_mode_t mode = BTHF_CALL_TYPE_VOICE;
|
||||
bthf_call_mpty_type_t mpty = BTHF_CALL_MPTY_TYPE_SINGLE;
|
||||
bthf_call_addrtype_t type = BTHF_CALL_ADDRTYPE_UNKNOWN;
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
bt_bdaddr_t bdAddr;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aDir, dir)) &&
|
||||
NS_SUCCEEDED(Convert(aState, state)) &&
|
||||
NS_SUCCEEDED(Convert(aMode, mode)) &&
|
||||
NS_SUCCEEDED(Convert(aMpty, mpty)) &&
|
||||
NS_SUCCEEDED(Convert(aType, type)) &&
|
||||
NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
|
||||
status = mInterface->clcc_response(aIndex, dir, state, mode, mpty,
|
||||
NS_ConvertUTF16toUTF8(aNumber).get(),
|
||||
type, &bdAddr);
|
||||
#else
|
||||
if (NS_SUCCEEDED(Convert(aDir, dir)) &&
|
||||
NS_SUCCEEDED(Convert(aState, state)) &&
|
||||
NS_SUCCEEDED(Convert(aMode, mode)) &&
|
||||
NS_SUCCEEDED(Convert(aMpty, mpty)) &&
|
||||
NS_SUCCEEDED(Convert(aType, type))) {
|
||||
status = mInterface->clcc_response(aIndex, dir, state, mode, mpty,
|
||||
NS_ConvertUTF16toUTF8(aNumber).get(),
|
||||
type);
|
||||
#endif
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::ClccResponse,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
/* Phone State */
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::PhoneStateChange(int aNumActive, int aNumHeld,
|
||||
BluetoothHandsfreeCallState aCallSetupState, const nsAString& aNumber,
|
||||
BluetoothHandsfreeCallAddressType aType,
|
||||
BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
bthf_call_state_t callSetupState = BTHF_CALL_STATE_ACTIVE;
|
||||
bthf_call_addrtype_t type = BTHF_CALL_ADDRTYPE_UNKNOWN;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aCallSetupState, callSetupState)) &&
|
||||
NS_SUCCEEDED(Convert(aType, type))) {
|
||||
status = mInterface->phone_state_change(
|
||||
aNumActive, aNumHeld, callSetupState,
|
||||
NS_ConvertUTF16toUTF8(aNumber).get(), type);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::PhoneStateChange,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
/* Wide Band Speech */
|
||||
|
||||
void
|
||||
BluetoothHandsfreeHALInterface::ConfigureWbs(
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeWbsConfig aConfig,
|
||||
BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
bt_status_t status;
|
||||
|
||||
#if ANDROID_VERSION >= 21
|
||||
bt_bdaddr_t bdAddr;
|
||||
bthf_wbs_config_t wbsConfig;
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr)) &&
|
||||
NS_SUCCEEDED(Convert(aConfig, wbsConfig))) {
|
||||
status = mInterface->configure_wbs(&bdAddr, wbsConfig);
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
#else
|
||||
status = BT_STATUS_UNSUPPORTED;
|
||||
#endif
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothHandsfreeHALResult(
|
||||
aRes, &BluetoothHandsfreeResultHandler::ConfigureWbs,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
@ -1,107 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_bluetooth_bluedroid_bluetoothhandsfreehalinterface_h__
|
||||
#define mozilla_dom_bluetooth_bluedroid_bluetoothhandsfreehalinterface_h__
|
||||
|
||||
#include <hardware/bluetooth.h>
|
||||
#include <hardware/bt_hf.h>
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothInterface.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothHALInterface;
|
||||
|
||||
class BluetoothHandsfreeHALInterface final
|
||||
: public BluetoothHandsfreeInterface
|
||||
{
|
||||
public:
|
||||
friend class BluetoothHALInterface;
|
||||
|
||||
void Init(BluetoothHandsfreeNotificationHandler* aNotificationHandler,
|
||||
int aMaxNumClients,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
void Cleanup(BluetoothHandsfreeResultHandler* aRes);
|
||||
|
||||
/* Connect / Disconnect */
|
||||
|
||||
void Connect(const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
void Disconnect(const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
void ConnectAudio(const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
void DisconnectAudio(const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
|
||||
/* Voice Recognition */
|
||||
|
||||
void StartVoiceRecognition(const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
void StopVoiceRecognition(const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
|
||||
/* Volume */
|
||||
|
||||
void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
|
||||
/* Device status */
|
||||
|
||||
void DeviceStatusNotification(BluetoothHandsfreeNetworkState aNtkState,
|
||||
BluetoothHandsfreeServiceType aSvcType,
|
||||
int aSignal, int aBattChg,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
|
||||
/* Responses */
|
||||
|
||||
void CopsResponse(const char* aCops, const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
void CindResponse(int aSvc, int aNumActive, int aNumHeld,
|
||||
BluetoothHandsfreeCallState aCallSetupState, int aSignal,
|
||||
int aRoam, int aBattChg, const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
void FormattedAtResponse(const char* aRsp, const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
void AtResponse(BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
void ClccResponse(int aIndex, BluetoothHandsfreeCallDirection aDir,
|
||||
BluetoothHandsfreeCallState aState,
|
||||
BluetoothHandsfreeCallMode aMode,
|
||||
BluetoothHandsfreeCallMptyType aMpty,
|
||||
const nsAString& aNumber,
|
||||
BluetoothHandsfreeCallAddressType aType,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
|
||||
/* Phone State */
|
||||
|
||||
void PhoneStateChange(int aNumActive, int aNumHeld,
|
||||
BluetoothHandsfreeCallState aCallSetupState,
|
||||
const nsAString& aNumber,
|
||||
BluetoothHandsfreeCallAddressType aType,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
|
||||
/* Wide Band Speech */
|
||||
|
||||
void ConfigureWbs(const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeWbsConfig aConfig,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
BluetoothHandsfreeHALInterface(const bthf_interface_t* aInterface);
|
||||
~BluetoothHandsfreeHALInterface();
|
||||
|
||||
private:
|
||||
const bthf_interface_t* mInterface;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,243 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BluetoothSocketHALInterface.h"
|
||||
#include "BluetoothHALHelpers.h"
|
||||
#include "BluetoothSocketMessageWatcher.h"
|
||||
#include "mozilla/FileUtils.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
typedef
|
||||
BluetoothHALInterfaceRunnable1<BluetoothSocketResultHandler, void,
|
||||
int, int>
|
||||
BluetoothSocketHALIntResultRunnable;
|
||||
|
||||
typedef
|
||||
BluetoothHALInterfaceRunnable3<BluetoothSocketResultHandler, void,
|
||||
int, const nsString, int,
|
||||
int, const nsAString_internal&, int>
|
||||
BluetoothSocketHALIntStringIntResultRunnable;
|
||||
|
||||
typedef
|
||||
BluetoothHALInterfaceRunnable1<BluetoothSocketResultHandler, void,
|
||||
BluetoothStatus, BluetoothStatus>
|
||||
BluetoothSocketHALErrorRunnable;
|
||||
|
||||
static nsresult
|
||||
DispatchBluetoothSocketHALResult(
|
||||
BluetoothSocketResultHandler* aRes,
|
||||
void (BluetoothSocketResultHandler::*aMethod)(int), int aArg,
|
||||
BluetoothStatus aStatus)
|
||||
{
|
||||
MOZ_ASSERT(aRes);
|
||||
|
||||
nsRefPtr<nsRunnable> runnable;
|
||||
|
||||
if (aStatus == STATUS_SUCCESS) {
|
||||
runnable = new BluetoothSocketHALIntResultRunnable(aRes, aMethod, aArg);
|
||||
} else {
|
||||
runnable = new BluetoothSocketHALErrorRunnable(aRes,
|
||||
&BluetoothSocketResultHandler::OnError, aStatus);
|
||||
}
|
||||
nsresult rv = NS_DispatchToMainThread(runnable);
|
||||
if (NS_FAILED(rv)) {
|
||||
BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
DispatchBluetoothSocketHALResult(
|
||||
BluetoothSocketResultHandler* aRes,
|
||||
void (BluetoothSocketResultHandler::*aMethod)(int, const nsAString&, int),
|
||||
int aArg1, const nsAString& aArg2, int aArg3, BluetoothStatus aStatus)
|
||||
{
|
||||
MOZ_ASSERT(aRes);
|
||||
|
||||
nsRefPtr<nsRunnable> runnable;
|
||||
|
||||
if (aStatus == STATUS_SUCCESS) {
|
||||
runnable = new BluetoothSocketHALIntStringIntResultRunnable(
|
||||
aRes, aMethod, aArg1, aArg2, aArg3);
|
||||
} else {
|
||||
runnable = new BluetoothSocketHALErrorRunnable(aRes,
|
||||
&BluetoothSocketResultHandler::OnError, aStatus);
|
||||
}
|
||||
nsresult rv = NS_DispatchToMainThread(runnable);
|
||||
if (NS_FAILED(rv)) {
|
||||
BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothSocketHALInterface::Listen(BluetoothSocketType aType,
|
||||
const nsAString& aServiceName,
|
||||
const uint8_t aServiceUuid[16],
|
||||
int aChannel, bool aEncrypt,
|
||||
bool aAuth,
|
||||
BluetoothSocketResultHandler* aRes)
|
||||
{
|
||||
int fd;
|
||||
bt_status_t status;
|
||||
btsock_type_t type = BTSOCK_RFCOMM; // silences compiler warning
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aType, type))) {
|
||||
status = mInterface->listen(type,
|
||||
NS_ConvertUTF16toUTF8(aServiceName).get(),
|
||||
aServiceUuid, aChannel, &fd,
|
||||
(BTSOCK_FLAG_ENCRYPT * aEncrypt) |
|
||||
(BTSOCK_FLAG_AUTH * aAuth));
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
||||
if (aRes) {
|
||||
DispatchBluetoothSocketHALResult(
|
||||
aRes, &BluetoothSocketResultHandler::Listen, fd,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
/* |DeleteTask| deletes a class instance on the I/O thread
|
||||
*/
|
||||
template <typename T>
|
||||
class DeleteTask final : public Task
|
||||
{
|
||||
public:
|
||||
DeleteTask(T* aPtr)
|
||||
: mPtr(aPtr)
|
||||
{ }
|
||||
|
||||
void Run() override
|
||||
{
|
||||
mPtr = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoPtr<T> mPtr;
|
||||
};
|
||||
|
||||
/* |ConnectWatcher| specializes SocketMessageWatcher for
|
||||
* connect operations by reading the socket messages from
|
||||
* Bluedroid and forwarding the connected socket to the
|
||||
* resource handler.
|
||||
*/
|
||||
class BluetoothSocketHALInterface::ConnectWatcher final
|
||||
: public SocketMessageWatcher
|
||||
{
|
||||
public:
|
||||
ConnectWatcher(int aFd, BluetoothSocketResultHandler* aRes)
|
||||
: SocketMessageWatcher(aFd, aRes)
|
||||
{ }
|
||||
|
||||
void Proceed(BluetoothStatus aStatus) override
|
||||
{
|
||||
DispatchBluetoothSocketHALResult(
|
||||
GetResultHandler(), &BluetoothSocketResultHandler::Connect,
|
||||
GetFd(), GetBdAddress(), GetConnectionStatus(), aStatus);
|
||||
|
||||
MessageLoopForIO::current()->PostTask(
|
||||
FROM_HERE, new DeleteTask<ConnectWatcher>(this));
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothSocketHALInterface::Connect(const nsAString& aBdAddr,
|
||||
BluetoothSocketType aType,
|
||||
const uint8_t aUuid[16],
|
||||
int aChannel, bool aEncrypt,
|
||||
bool aAuth,
|
||||
BluetoothSocketResultHandler* aRes)
|
||||
{
|
||||
int fd;
|
||||
bt_status_t status;
|
||||
bt_bdaddr_t bdAddr;
|
||||
btsock_type_t type = BTSOCK_RFCOMM; // silences compiler warning
|
||||
|
||||
if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr)) &&
|
||||
NS_SUCCEEDED(Convert(aType, type))) {
|
||||
status = mInterface->connect(&bdAddr, type, aUuid, aChannel, &fd,
|
||||
(BTSOCK_FLAG_ENCRYPT * aEncrypt) |
|
||||
(BTSOCK_FLAG_AUTH * aAuth));
|
||||
} else {
|
||||
status = BT_STATUS_PARM_INVALID;
|
||||
}
|
||||
|
||||
if (status == BT_STATUS_SUCCESS) {
|
||||
/* receive Bluedroid's socket-setup messages */
|
||||
Task* t = new SocketMessageWatcherTask(new ConnectWatcher(fd, aRes));
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t);
|
||||
} else if (aRes) {
|
||||
DispatchBluetoothSocketHALResult(
|
||||
aRes, &BluetoothSocketResultHandler::Connect, -1, EmptyString(), 0,
|
||||
ConvertDefault(status, STATUS_FAIL));
|
||||
}
|
||||
}
|
||||
|
||||
/* |AcceptWatcher| specializes SocketMessageWatcher for Accept
|
||||
* operations by reading the socket messages from Bluedroid and
|
||||
* forwarding the received client socket to the resource handler.
|
||||
* The first message is received immediately. When there's a new
|
||||
* connection, Bluedroid sends the 2nd message with the socket
|
||||
* info and socket file descriptor.
|
||||
*/
|
||||
class BluetoothSocketHALInterface::AcceptWatcher final
|
||||
: public SocketMessageWatcher
|
||||
{
|
||||
public:
|
||||
AcceptWatcher(int aFd, BluetoothSocketResultHandler* aRes)
|
||||
: SocketMessageWatcher(aFd, aRes)
|
||||
{ }
|
||||
|
||||
void Proceed(BluetoothStatus aStatus) override
|
||||
{
|
||||
if ((aStatus != STATUS_SUCCESS) && (GetClientFd() != -1)) {
|
||||
mozilla::ScopedClose(GetClientFd()); // Close received socket fd on error
|
||||
}
|
||||
|
||||
DispatchBluetoothSocketHALResult(
|
||||
GetResultHandler(), &BluetoothSocketResultHandler::Accept,
|
||||
GetClientFd(), GetBdAddress(), GetConnectionStatus(), aStatus);
|
||||
|
||||
MessageLoopForIO::current()->PostTask(
|
||||
FROM_HERE, new DeleteTask<AcceptWatcher>(this));
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
BluetoothSocketHALInterface::Accept(int aFd,
|
||||
BluetoothSocketResultHandler* aRes)
|
||||
{
|
||||
/* receive Bluedroid's socket-setup messages and client fd */
|
||||
Task* t = new SocketMessageWatcherTask(new AcceptWatcher(aFd, aRes));
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothSocketHALInterface::Close(BluetoothSocketResultHandler* aRes)
|
||||
{
|
||||
MOZ_ASSERT(aRes);
|
||||
|
||||
/* stop the watcher corresponding to |aRes| */
|
||||
Task* t = new DeleteSocketMessageWatcherTask(aRes);
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t);
|
||||
}
|
||||
|
||||
BluetoothSocketHALInterface::BluetoothSocketHALInterface(
|
||||
const btsock_interface_t* aInterface)
|
||||
: mInterface(aInterface)
|
||||
{
|
||||
MOZ_ASSERT(mInterface);
|
||||
}
|
||||
|
||||
BluetoothSocketHALInterface::~BluetoothSocketHALInterface()
|
||||
{ }
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
@ -1,54 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_bluetooth_bluedroid_bluetoothsockethalinterface_h__
|
||||
#define mozilla_dom_bluetooth_bluedroid_bluetoothsockethalinterface_h__
|
||||
|
||||
#include <hardware/bluetooth.h>
|
||||
#include <hardware/bt_sock.h>
|
||||
#include "BluetoothCommon.h"
|
||||
#include "BluetoothInterface.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothHALInterface;
|
||||
|
||||
class BluetoothSocketHALInterface final
|
||||
: public BluetoothSocketInterface
|
||||
{
|
||||
public:
|
||||
class ConnectWatcher;
|
||||
class AcceptWatcher;
|
||||
|
||||
friend class BluetoothHALInterface;
|
||||
|
||||
void Listen(BluetoothSocketType aType,
|
||||
const nsAString& aServiceName,
|
||||
const uint8_t aServiceUuid[16],
|
||||
int aChannel, bool aEncrypt, bool aAuth,
|
||||
BluetoothSocketResultHandler* aRes);
|
||||
|
||||
void Connect(const nsAString& aBdAddr,
|
||||
BluetoothSocketType aType,
|
||||
const uint8_t aUuid[16],
|
||||
int aChannel, bool aEncrypt, bool aAuth,
|
||||
BluetoothSocketResultHandler* aRes);
|
||||
|
||||
void Accept(int aFd, BluetoothSocketResultHandler* aRes);
|
||||
|
||||
void Close(BluetoothSocketResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
BluetoothSocketHALInterface(const btsock_interface_t* aInterface);
|
||||
~BluetoothSocketHALInterface();
|
||||
|
||||
private:
|
||||
const btsock_interface_t* mInterface;
|
||||
};
|
||||
|
||||
END_BLUETOOTH_NAMESPACE
|
||||
|
||||
#endif
|
@ -15,7 +15,7 @@
|
||||
#include "BluetoothManager.h"
|
||||
#include "BluetoothOppManager.h"
|
||||
#include "BluetoothParent.h"
|
||||
#if defined(MOZ_B2G_BT_BLUEDROID)
|
||||
#if defined(MOZ_B2G_BT_DAEMON)
|
||||
#include "BluetoothPbapManager.h"
|
||||
#endif
|
||||
#include "BluetoothReplyRunnable.h"
|
||||
@ -52,17 +52,10 @@
|
||||
* MOZ_B2G_BT and MOZ_B2G_BT_BLUEZ are both defined.
|
||||
*/
|
||||
#include "BluetoothDBusService.h"
|
||||
#elif defined(MOZ_B2G_BT_BLUEDROID)
|
||||
/**
|
||||
* B2G bluedroid:
|
||||
* MOZ_B2G_BT and MOZ_B2G_BT_BLUEDROID are both defined;
|
||||
* MOZ_B2G_BLUEZ or MOZ_B2G_DAEMON are not defined.
|
||||
*/
|
||||
#include "BluetoothServiceBluedroid.h"
|
||||
#elif defined(MOZ_B2G_BT_DAEMON)
|
||||
/**
|
||||
* B2G Bluetooth daemon:
|
||||
* MOZ_B2G_BT, MOZ_B2G_BLUEDROID and MOZ_B2G_BT_DAEMON are defined;
|
||||
* MOZ_B2G_BT and MOZ_B2G_BT_DAEMON are defined;
|
||||
* MOZ_B2G_BLUEZ is not defined.
|
||||
*/
|
||||
#include "BluetoothServiceBluedroid.h"
|
||||
@ -220,8 +213,6 @@ BluetoothService::Create()
|
||||
|
||||
#if defined(MOZ_B2G_BT_BLUEZ)
|
||||
return new BluetoothDBusService();
|
||||
#elif defined(MOZ_B2G_BT_BLUEDROID)
|
||||
return new BluetoothServiceBluedroid();
|
||||
#elif defined(MOZ_B2G_BT_DAEMON)
|
||||
return new BluetoothServiceBluedroid();
|
||||
#endif
|
||||
@ -409,7 +400,7 @@ BluetoothService::StopBluetooth(bool aIsStartup)
|
||||
BluetoothHfpManager::Get(),
|
||||
BluetoothA2dpManager::Get(),
|
||||
BluetoothOppManager::Get(),
|
||||
#if defined(MOZ_B2G_BT_BLUEDROID)
|
||||
#if defined(MOZ_B2G_BT_DAEMON)
|
||||
BluetoothPbapManager::Get(),
|
||||
#endif
|
||||
BluetoothHidManager::Get()
|
||||
|
@ -43,17 +43,10 @@
|
||||
* MOZ_B2G_BT and MOZ_B2G_BT_BLUEZ are both defined.
|
||||
*/
|
||||
#include "BluetoothDBusService.h"
|
||||
#elif defined(MOZ_B2G_BT_BLUEDROID)
|
||||
/**
|
||||
* B2G bluedroid:
|
||||
* MOZ_B2G_BT and MOZ_B2G_BT_BLUEDROID are both defined;
|
||||
* MOZ_B2G_BLUEZ or MOZ_B2G_DAEMON are not defined.
|
||||
*/
|
||||
#include "BluetoothServiceBluedroid.h"
|
||||
#elif defined(MOZ_B2G_BT_DAEMON)
|
||||
/**
|
||||
* B2G Bluetooth daemon:
|
||||
* MOZ_B2G_BT, MOZ_B2G_BLUEDROID and MOZ_B2G_BT_DAEMON are defined;
|
||||
* MOZ_B2G_BT and MOZ_B2G_BT_DAEMON are defined;
|
||||
* MOZ_B2G_BLUEZ is not defined.
|
||||
*/
|
||||
#include "BluetoothServiceBluedroid.h"
|
||||
@ -199,8 +192,6 @@ BluetoothService::Create()
|
||||
|
||||
#if defined(MOZ_B2G_BT_BLUEZ)
|
||||
return new BluetoothDBusService();
|
||||
#elif defined(MOZ_B2G_BT_BLUEDROID)
|
||||
return new BluetoothServiceBluedroid();
|
||||
#elif defined(MOZ_B2G_BT_DAEMON)
|
||||
return new BluetoothServiceBluedroid();
|
||||
#endif
|
||||
|
@ -13,7 +13,6 @@ if CONFIG['MOZ_B2G_BT']:
|
||||
SOURCES += [
|
||||
'BluetoothHidManager.cpp',
|
||||
'BluetoothInterface.cpp',
|
||||
'BluetoothInterfaceHelpers.cpp',
|
||||
'BluetoothUtils.cpp',
|
||||
'BluetoothUuid.cpp',
|
||||
'ObexBase.cpp'
|
||||
@ -87,11 +86,9 @@ if CONFIG['MOZ_B2G_BT']:
|
||||
'bluez',
|
||||
]
|
||||
DEFINES['MOZ_B2G_BT_BLUEZ'] = True
|
||||
elif CONFIG['MOZ_B2G_BT_BLUEDROID']:
|
||||
elif CONFIG['MOZ_B2G_BT_DAEMON']:
|
||||
SOURCES += [
|
||||
'bluedroid/BluetoothA2dpHALInterface.cpp',
|
||||
'bluedroid/BluetoothA2dpManager.cpp',
|
||||
'bluedroid/BluetoothAvrcpHALInterface.cpp',
|
||||
'bluedroid/BluetoothDaemonA2dpInterface.cpp',
|
||||
'bluedroid/BluetoothDaemonAvrcpInterface.cpp',
|
||||
'bluedroid/BluetoothDaemonConnector.cpp',
|
||||
@ -101,15 +98,10 @@ if CONFIG['MOZ_B2G_BT']:
|
||||
'bluedroid/BluetoothDaemonInterface.cpp',
|
||||
'bluedroid/BluetoothDaemonSetupInterface.cpp',
|
||||
'bluedroid/BluetoothDaemonSocketInterface.cpp',
|
||||
'bluedroid/BluetoothGattHALInterface.cpp',
|
||||
'bluedroid/BluetoothHALHelpers.cpp',
|
||||
'bluedroid/BluetoothHALInterface.cpp',
|
||||
'bluedroid/BluetoothHandsfreeHALInterface.cpp',
|
||||
'bluedroid/BluetoothOppManager.cpp',
|
||||
'bluedroid/BluetoothPbapManager.cpp',
|
||||
'bluedroid/BluetoothServiceBluedroid.cpp',
|
||||
'bluedroid/BluetoothSocket.cpp',
|
||||
'bluedroid/BluetoothSocketHALInterface.cpp',
|
||||
'bluedroid/BluetoothSocketMessageWatcher.cpp'
|
||||
]
|
||||
LOCAL_INCLUDES += [
|
||||
@ -135,9 +127,7 @@ if CONFIG['MOZ_B2G_BT']:
|
||||
'bluedroid/BluetoothGattManager.cpp',
|
||||
]
|
||||
|
||||
DEFINES['MOZ_B2G_BT_BLUEDROID'] = True
|
||||
if CONFIG['MOZ_B2G_BT_DAEMON']:
|
||||
DEFINES['MOZ_B2G_BT_DAEMON'] = True
|
||||
DEFINES['MOZ_B2G_BT_DAEMON'] = True
|
||||
elif CONFIG['MOZ_ENABLE_DBUS']:
|
||||
CFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
|
||||
CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
|
||||
|
@ -56,7 +56,8 @@ let CERTIFICATE_ERROR_PAGE_PREF = 'security.alternate_certificate_error_page';
|
||||
const OBSERVED_EVENTS = [
|
||||
'xpcom-shutdown',
|
||||
'media-playback',
|
||||
'activity-done'
|
||||
'activity-done',
|
||||
'invalid-widget'
|
||||
];
|
||||
|
||||
const COMMAND_MAP = {
|
||||
@ -300,6 +301,9 @@ BrowserElementChild.prototype = {
|
||||
case 'xpcom-shutdown':
|
||||
this._shuttingDown = true;
|
||||
break;
|
||||
case 'invalid-widget':
|
||||
sendAsyncMsg('error', { type: 'invalid-widget' });
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -189,9 +189,9 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
|
||||
}
|
||||
|
||||
GLsizei srcSamples;
|
||||
GLenum srcColorFormat;
|
||||
GLenum srcDepthFormat;
|
||||
GLenum srcStencilFormat;
|
||||
GLenum srcColorFormat = 0;
|
||||
GLenum srcDepthFormat = 0;
|
||||
GLenum srcStencilFormat = 0;
|
||||
|
||||
if (mBoundReadFramebuffer) {
|
||||
if (!GetFBInfoForBlit(mBoundReadFramebuffer, this, "READ_FRAMEBUFFER",
|
||||
@ -220,9 +220,9 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
|
||||
}
|
||||
|
||||
GLsizei dstSamples;
|
||||
GLenum dstColorFormat;
|
||||
GLenum dstDepthFormat;
|
||||
GLenum dstStencilFormat;
|
||||
GLenum dstColorFormat = 0;
|
||||
GLenum dstDepthFormat = 0;
|
||||
GLenum dstStencilFormat = 0;
|
||||
|
||||
if (mBoundDrawFramebuffer) {
|
||||
if (!GetFBInfoForBlit(mBoundDrawFramebuffer, this, "DRAW_FRAMEBUFFER",
|
||||
|
@ -311,7 +311,8 @@ public:
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
return mallocSizeOf(this) + mTreeData.SizeOfExcludingThis(mallocSizeOf);
|
||||
return mallocSizeOf(this) +
|
||||
mTreeData.ShallowSizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
};
|
||||
|
||||
@ -624,7 +625,7 @@ size_t
|
||||
WebGLElementArrayCache::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
return mallocSizeOf(this) +
|
||||
mBytes.SizeOfExcludingThis(mallocSizeOf) +
|
||||
mBytes.ShallowSizeOfExcludingThis(mallocSizeOf) +
|
||||
SizeOfNullable(mallocSizeOf, mUint8Tree) +
|
||||
SizeOfNullable(mallocSizeOf, mUint16Tree) +
|
||||
SizeOfNullable(mallocSizeOf, mUint32Tree);
|
||||
|
@ -1444,7 +1444,7 @@ size_t
|
||||
EventListenerManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t n = aMallocSizeOf(this);
|
||||
n += mListeners.SizeOfExcludingThis(aMallocSizeOf);
|
||||
n += mListeners.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
uint32_t count = mListeners.Length();
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
JSEventHandler* jsEventHandler =
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "mozilla/dom/Fetch.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/URL.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
#include "mozilla/dom/workers/bindings/URL.h"
|
||||
|
||||
#include "WorkerPrivate.h"
|
||||
@ -42,6 +43,25 @@ Request::~Request()
|
||||
{
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
Request::RequestContextEnabled(JSContext* aCx, JSObject* aObj)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
return Preferences::GetBool("dom.requestcontext.enabled", false);
|
||||
}
|
||||
|
||||
using namespace workers;
|
||||
|
||||
// Otherwise, check the pref via the WorkerPrivate
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
if (!workerPrivate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return workerPrivate->RequestContextEnabled();
|
||||
}
|
||||
|
||||
already_AddRefed<InternalRequest>
|
||||
Request::GetInternalRequest()
|
||||
{
|
||||
|
@ -34,6 +34,9 @@ class Request final : public nsISupports
|
||||
public:
|
||||
Request(nsIGlobalObject* aOwner, InternalRequest* aRequest);
|
||||
|
||||
static bool
|
||||
RequestContextEnabled(JSContext* aCx, JSObject* aObj);
|
||||
|
||||
JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
|
||||
{
|
||||
|
@ -192,6 +192,7 @@
|
||||
#include "mozilla/widget/PuppetBidiKeyboard.h"
|
||||
#include "mozilla/RemoteSpellCheckEngineChild.h"
|
||||
#include "GMPServiceChild.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::docshell;
|
||||
@ -2905,6 +2906,15 @@ ContentChild::RecvEndDragSession(const bool& aDoneDrag,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvTestGraphicsDeviceReset(const uint32_t& aResetReason)
|
||||
{
|
||||
#if defined(XP_WIN)
|
||||
gfxPlatform::GetPlatform()->TestDeviceReset(DeviceResetReason(aResetReason));
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -469,6 +469,8 @@ public:
|
||||
|
||||
virtual bool RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent) override;
|
||||
|
||||
virtual bool RecvTestGraphicsDeviceReset(const uint32_t& aResetReason) override;
|
||||
|
||||
private:
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
|
@ -650,6 +650,12 @@ child:
|
||||
* Send gamepad status update to child.
|
||||
*/
|
||||
GamepadUpdate(GamepadChangeEvent aGamepadEvent);
|
||||
|
||||
/**
|
||||
* Tell the child that for testing purposes, a graphics device reset has
|
||||
* occurred.
|
||||
*/
|
||||
async TestGraphicsDeviceReset(uint32_t aReason);
|
||||
parent:
|
||||
/**
|
||||
* Tell the content process some attributes of itself. This is
|
||||
|
@ -11,112 +11,81 @@
|
||||
*
|
||||
* BUG: https://bugzilla.mozilla.org/show_bug.cgi?id=1083410
|
||||
*/
|
||||
/*globals content, sendAsyncMessage, addMessageListener, Components*/
|
||||
'use strict';
|
||||
/*globals Task, ManifestObtainer, ManifestFinder, content, sendAsyncMessage, addMessageListener, Components*/
|
||||
"use strict";
|
||||
const {
|
||||
utils: Cu,
|
||||
classes: Cc,
|
||||
interfaces: Ci
|
||||
} = Components;
|
||||
const {
|
||||
ManifestProcessor
|
||||
} = Cu.import('resource://gre/modules/WebManifest.jsm', {});
|
||||
const {
|
||||
Task: {
|
||||
spawn, async
|
||||
}
|
||||
} = Components.utils.import('resource://gre/modules/Task.jsm', {});
|
||||
Cu.import("resource://gre/modules/ManifestObtainer.jsm");
|
||||
Cu.import("resource://gre/modules/ManifestFinder.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
addMessageListener('DOM:ManifestObtainer:Obtain', async(function* (aMsg) {
|
||||
const response = {
|
||||
msgId: aMsg.data.msgId,
|
||||
success: true,
|
||||
result: undefined
|
||||
};
|
||||
try {
|
||||
response.result = yield fetchManifest();
|
||||
} catch (err) {
|
||||
response.success = false;
|
||||
response.result = cloneError(err);
|
||||
}
|
||||
sendAsyncMessage('DOM:ManifestObtainer:Obtain', response);
|
||||
}));
|
||||
const MessageHandler = {
|
||||
registerListeners() {
|
||||
addMessageListener(
|
||||
"DOM:WebManifest:hasManifestLink",
|
||||
this.hasManifestLink.bind(this)
|
||||
);
|
||||
addMessageListener(
|
||||
"DOM:ManifestObtainer:Obtain",
|
||||
this.obtainManifest.bind(this)
|
||||
);
|
||||
},
|
||||
|
||||
function cloneError(aError) {
|
||||
/**
|
||||
* Check if the content document includes a link to a web manifest.
|
||||
* @param {Object} aMsg The IPC message, which is destructured to just
|
||||
* get the id.
|
||||
*/
|
||||
hasManifestLink({data: {id}}) {
|
||||
const response = makeMsgResponse(id);
|
||||
response.result = ManifestFinder.contentHasManifestLink(content);
|
||||
response.success = true;
|
||||
sendAsyncMessage("DOM:WebManifest:hasManifestLink", response);
|
||||
},
|
||||
|
||||
/**
|
||||
* Asynchronously obtains a web manifest from content by using the
|
||||
* ManifestObtainer and messages back the result.
|
||||
* @param {Object} aMsg The IPC message, which is destructured to just
|
||||
* get the id.
|
||||
*/
|
||||
obtainManifest: Task.async(function* ({data: {id}}) {
|
||||
const response = makeMsgResponse(id);
|
||||
try {
|
||||
response.result = yield ManifestObtainer.contentObtainManifest(content);
|
||||
response.success = true;
|
||||
} catch (err) {
|
||||
response.result = serializeError(err);
|
||||
}
|
||||
sendAsyncMessage("DOM:ManifestObtainer:Obtain", response);
|
||||
}),
|
||||
};
|
||||
/**
|
||||
* Utility function to Serializes an JS Error, so it can be transferred over
|
||||
* the message channel.
|
||||
* FIX ME: https://bugzilla.mozilla.org/show_bug.cgi?id=1172586
|
||||
* @param {Error} aError The error to serialize.
|
||||
* @return {Object} The serialized object.
|
||||
*/
|
||||
function serializeError(aError) {
|
||||
const clone = {
|
||||
'fileName': String(aError.fileName),
|
||||
'lineNumber': String(aError.lineNumber),
|
||||
'columnNumber': String(aError.columnNumber),
|
||||
'stack': String(aError.stack),
|
||||
'message': String(aError.message),
|
||||
'name': String(aError.name)
|
||||
"fileName": aError.fileName,
|
||||
"lineNumber": aError.lineNumber,
|
||||
"columnNumber": aError.columnNumber,
|
||||
"stack": aError.stack,
|
||||
"message": aError.message,
|
||||
"name": aError.name
|
||||
};
|
||||
return clone;
|
||||
}
|
||||
|
||||
function fetchManifest() {
|
||||
return spawn(function* () {
|
||||
if (!content || content.top !== content) {
|
||||
let msg = 'Content window must be a top-level browsing context.';
|
||||
throw new Error(msg);
|
||||
}
|
||||
const elem = content.document.querySelector('link[rel~="manifest"]');
|
||||
if (!elem || !elem.getAttribute('href')) {
|
||||
let msg = 'No manifest to fetch.';
|
||||
throw new Error(msg);
|
||||
}
|
||||
// Throws on malformed URLs
|
||||
const manifestURL = new content.URL(elem.href, elem.baseURI);
|
||||
if (!canLoadManifest(elem)) {
|
||||
let msg = `Content Security Policy: The page's settings blocked the `;
|
||||
msg += `loading of a resource at ${elem.href}`;
|
||||
throw new Error(msg);
|
||||
}
|
||||
const reqInit = {
|
||||
mode: 'cors'
|
||||
function makeMsgResponse(aId) {
|
||||
return {
|
||||
id: aId,
|
||||
success: false,
|
||||
result: undefined
|
||||
};
|
||||
if (elem.crossOrigin === 'use-credentials') {
|
||||
reqInit.credentials = 'include';
|
||||
}
|
||||
const req = new content.Request(manifestURL, reqInit);
|
||||
req.setContentPolicyType(Ci.nsIContentPolicy.TYPE_WEB_MANIFEST);
|
||||
const response = yield content.fetch(req);
|
||||
const manifest = yield processResponse(response, content);
|
||||
return manifest;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function canLoadManifest(aElem) {
|
||||
const contentPolicy = Cc['@mozilla.org/layout/content-policy;1']
|
||||
.getService(Ci.nsIContentPolicy);
|
||||
const mimeType = aElem.type || 'application/manifest+json';
|
||||
const elemURI = BrowserUtils.makeURI(
|
||||
aElem.href, aElem.ownerDocument.characterSet
|
||||
);
|
||||
const shouldLoad = contentPolicy.shouldLoad(
|
||||
Ci.nsIContentPolicy.TYPE_WEB_MANIFEST, elemURI,
|
||||
aElem.ownerDocument.documentURIObject,
|
||||
aElem, mimeType, null
|
||||
);
|
||||
return shouldLoad === Ci.nsIContentPolicy.ACCEPT;
|
||||
}
|
||||
|
||||
function processResponse(aResp, aContentWindow) {
|
||||
return spawn(function* () {
|
||||
const badStatus = aResp.status < 200 || aResp.status >= 300;
|
||||
if (aResp.type === 'error' || badStatus) {
|
||||
let msg =
|
||||
`Fetch error: ${aResp.status} - ${aResp.statusText} at ${aResp.url}`;
|
||||
throw new Error(msg);
|
||||
}
|
||||
const text = yield aResp.text();
|
||||
const args = {
|
||||
jsonText: text,
|
||||
manifestURL: aResp.url,
|
||||
docURL: aContentWindow.location.href
|
||||
};
|
||||
const processor = new ManifestProcessor();
|
||||
const manifest = processor.process(args);
|
||||
return Cu.cloneInto(manifest, content);
|
||||
});
|
||||
}
|
||||
MessageHandler.registerListeners();
|
||||
|
68
dom/manifest/ManifestFinder.jsm
Normal file
68
dom/manifest/ManifestFinder.jsm
Normal file
@ -0,0 +1,68 @@
|
||||
/* 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 https://mozilla.org/MPL/2.0/. */
|
||||
/* globals Components, Task, PromiseMessage */
|
||||
"use strict";
|
||||
const {
|
||||
utils: Cu
|
||||
} = Components;
|
||||
Cu.import("resource://gre/modules/PromiseMessage.jsm");
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
this.ManifestFinder = {// jshint ignore:line
|
||||
/**
|
||||
* Check from content process if DOM Window has a conforming
|
||||
* manifest link relationship.
|
||||
* @param aContent DOM Window to check.
|
||||
* @return {Promise<Boolean>}
|
||||
*/
|
||||
contentHasManifestLink(aContent) {
|
||||
if (!aContent || isXULBrowser(aContent)) {
|
||||
throw new TypeError("Invalid input.");
|
||||
}
|
||||
return checkForManifest(aContent);
|
||||
},
|
||||
|
||||
/**
|
||||
* Check from a XUL browser (parent process) if it's content document has a
|
||||
* manifest link relationship.
|
||||
* @param aBrowser The XUL browser to check.
|
||||
* @return {Promise}
|
||||
*/
|
||||
browserHasManifestLink: Task.async(
|
||||
function* (aBrowser) {
|
||||
if (!isXULBrowser(aBrowser)) {
|
||||
throw new TypeError("Invalid input.");
|
||||
}
|
||||
const msgKey = "DOM:WebManifest:hasManifestLink";
|
||||
const mm = aBrowser.messageManager;
|
||||
const reply = yield PromiseMessage.send(mm, msgKey);
|
||||
return reply.data.result;
|
||||
}
|
||||
)
|
||||
};
|
||||
|
||||
function isXULBrowser(aBrowser) {
|
||||
if (!aBrowser || !aBrowser.namespaceURI || !aBrowser.localName) {
|
||||
return false;
|
||||
}
|
||||
const XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
return (aBrowser.namespaceURI === XUL && aBrowser.localName === "browser");
|
||||
}
|
||||
|
||||
function checkForManifest(aWindow) {
|
||||
// Only top-level browsing contexts are valid.
|
||||
if (!aWindow || aWindow.top !== aWindow) {
|
||||
return false;
|
||||
}
|
||||
const elem = aWindow.document.querySelector("link[rel~='manifest']");
|
||||
// Only if we have an element and a non-empty href attribute.
|
||||
if (!elem || !elem.getAttribute("href")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
this.EXPORTED_SYMBOLS = [// jshint ignore:line
|
||||
"ManifestFinder"
|
||||
];
|
@ -1,92 +0,0 @@
|
||||
/* 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/.
|
||||
*
|
||||
* ManifestObtainer is an implementation of:
|
||||
* http://w3c.github.io/manifest/#obtaining
|
||||
*
|
||||
* Exposes public method `.obtainManifest(browserWindow)`, which returns
|
||||
* a promise. If successful, you get back a manifest (string).
|
||||
*
|
||||
* For e10s compat, this JSM relies on the following to do
|
||||
* the nessesary IPC:
|
||||
* dom/ipc/manifestMessages.js
|
||||
*
|
||||
* whose internal URL is:
|
||||
* 'chrome://global/content/manifestMessages.js'
|
||||
*
|
||||
* Which is injected into every browser instance via browser.js.
|
||||
*
|
||||
* BUG: https://bugzilla.mozilla.org/show_bug.cgi?id=1083410
|
||||
* exported ManifestObtainer
|
||||
*/
|
||||
'use strict';
|
||||
const MSG_KEY = 'DOM:ManifestObtainer:Obtain';
|
||||
let messageCounter = 0;
|
||||
// FIXME: Ideally, we would store a reference to the
|
||||
// message manager in a weakmap instead of needing a
|
||||
// browserMap. However, trying to store a messageManager
|
||||
// results in a TypeError because of:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=888600
|
||||
const browsersMap = new WeakMap();
|
||||
|
||||
function ManifestObtainer() {}
|
||||
|
||||
ManifestObtainer.prototype = {
|
||||
obtainManifest(aBrowserWindow) {
|
||||
if (!aBrowserWindow) {
|
||||
const err = new TypeError('Invalid input. Expected xul browser.');
|
||||
return Promise.reject(err);
|
||||
}
|
||||
const mm = aBrowserWindow.messageManager;
|
||||
const onMessage = function(aMsg) {
|
||||
const msgId = aMsg.data.msgId;
|
||||
const {
|
||||
resolve, reject
|
||||
} = browsersMap.get(aBrowserWindow).get(msgId);
|
||||
browsersMap.get(aBrowserWindow).delete(msgId);
|
||||
// If we we've processed all messages,
|
||||
// stop listening.
|
||||
if (!browsersMap.get(aBrowserWindow).size) {
|
||||
browsersMap.delete(aBrowserWindow);
|
||||
mm.removeMessageListener(MSG_KEY, onMessage);
|
||||
}
|
||||
if (aMsg.data.success) {
|
||||
return resolve(aMsg.data.result);
|
||||
}
|
||||
reject(toError(aMsg.data.result));
|
||||
};
|
||||
// If we are not already listening for messages
|
||||
// start listening.
|
||||
if (!browsersMap.has(aBrowserWindow)) {
|
||||
browsersMap.set(aBrowserWindow, new Map());
|
||||
mm.addMessageListener(MSG_KEY, onMessage);
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const msgId = messageCounter++;
|
||||
browsersMap.get(aBrowserWindow).set(msgId, {
|
||||
resolve: resolve,
|
||||
reject: reject
|
||||
});
|
||||
mm.sendAsyncMessage(MSG_KEY, {
|
||||
msgId: msgId
|
||||
});
|
||||
});
|
||||
|
||||
function toError(aErrorClone) {
|
||||
let error;
|
||||
switch (aErrorClone.name) {
|
||||
case 'TypeError':
|
||||
error = new TypeError();
|
||||
break;
|
||||
default:
|
||||
error = new Error();
|
||||
}
|
||||
Object.getOwnPropertyNames(aErrorClone)
|
||||
.forEach(name => error[name] = aErrorClone[name]);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
};
|
||||
this.ManifestObtainer = ManifestObtainer; // jshint ignore:line
|
||||
this.EXPORTED_SYMBOLS = ['ManifestObtainer']; // jshint ignore:line
|
175
dom/manifest/ManifestObtainer.jsm
Normal file
175
dom/manifest/ManifestObtainer.jsm
Normal file
@ -0,0 +1,175 @@
|
||||
/* 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/.
|
||||
*/
|
||||
/*
|
||||
* ManifestObtainer is an implementation of:
|
||||
* http://w3c.github.io/manifest/#obtaining
|
||||
*
|
||||
* Exposes 2 public method:
|
||||
*
|
||||
* .contentObtainManifest(aContent) - used in content process
|
||||
* .browserObtainManifest(aBrowser) - used in browser/parent process
|
||||
*
|
||||
* both return a promise. If successful, you get back a manifest object.
|
||||
*
|
||||
* Import it with URL:
|
||||
* 'chrome://global/content/manifestMessages.js'
|
||||
*
|
||||
* e10s IPC message from this components are handled by:
|
||||
* dom/ipc/manifestMessages.js
|
||||
*
|
||||
* Which is injected into every browser instance via browser.js.
|
||||
*
|
||||
* exported ManifestObtainer
|
||||
*/
|
||||
/*globals Components, Task, PromiseMessage, XPCOMUtils, ManifestProcessor, BrowserUtils*/
|
||||
"use strict";
|
||||
const {
|
||||
utils: Cu,
|
||||
classes: Cc,
|
||||
interfaces: Ci
|
||||
} = Components;
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
Cu.import("resource://gre/modules/PromiseMessage.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/ManifestProcessor.jsm");
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils", // jshint ignore:line
|
||||
"resource://gre/modules/BrowserUtils.jsm");
|
||||
|
||||
this.ManifestObtainer = { // jshint ignore:line
|
||||
/**
|
||||
* Public interface for obtaining a web manifest from a XUL browser, to use
|
||||
* on the parent process.
|
||||
* @param {XULBrowser} The browser to check for the manifest.
|
||||
* @return {Promise<Object>} The processed manifest.
|
||||
*/
|
||||
browserObtainManifest: Task.async(function* (aBrowser) {
|
||||
const msgKey = "DOM:ManifestObtainer:Obtain";
|
||||
if (!isXULBrowser(aBrowser)) {
|
||||
throw new TypeError("Invalid input. Expected XUL browser.");
|
||||
}
|
||||
const mm = aBrowser.messageManager;
|
||||
const {data: {success, result}} = yield PromiseMessage.send(mm, msgKey);
|
||||
if (!success) {
|
||||
const error = toError(result);
|
||||
throw error;
|
||||
}
|
||||
return result;
|
||||
}),
|
||||
/**
|
||||
* Public interface for obtaining a web manifest from a XUL browser.
|
||||
* @param {Window} The content Window from which to extract the manifest.
|
||||
* @return {Promise<Object>} The processed manifest.
|
||||
*/
|
||||
contentObtainManifest: Task.async(function* (aContent) {
|
||||
if (!aContent || isXULBrowser(aContent)) {
|
||||
throw new TypeError("Invalid input. Expected a DOM Window.");
|
||||
}
|
||||
const manifest = yield fetchManifest(aContent);
|
||||
return manifest;
|
||||
}
|
||||
)};
|
||||
|
||||
function toError(aErrorClone) {
|
||||
let error;
|
||||
switch (aErrorClone.name) {
|
||||
case "TypeError":
|
||||
error = new TypeError();
|
||||
break;
|
||||
default:
|
||||
error = new Error();
|
||||
}
|
||||
Object.getOwnPropertyNames(aErrorClone)
|
||||
.forEach(name => error[name] = aErrorClone[name]);
|
||||
return error;
|
||||
}
|
||||
|
||||
function isXULBrowser(aBrowser) {
|
||||
if (!aBrowser || !aBrowser.namespaceURI || !aBrowser.localName) {
|
||||
return false;
|
||||
}
|
||||
const XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
return (aBrowser.namespaceURI === XUL && aBrowser.localName === "browser");
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously processes the result of response after having fetched
|
||||
* a manifest.
|
||||
* @param {Response} aResp Response from fetch().
|
||||
* @param {Window} aContentWindow The content window.
|
||||
* @return {Promise<Object>} The processed manifest.
|
||||
*/
|
||||
const processResponse = Task.async(function* (aResp, aContentWindow) {
|
||||
const badStatus = aResp.status < 200 || aResp.status >= 300;
|
||||
if (aResp.type === "error" || badStatus) {
|
||||
const msg =
|
||||
`Fetch error: ${aResp.status} - ${aResp.statusText} at ${aResp.url}`;
|
||||
throw new Error(msg);
|
||||
}
|
||||
const text = yield aResp.text();
|
||||
const args = {
|
||||
jsonText: text,
|
||||
manifestURL: aResp.url,
|
||||
docURL: aContentWindow.location.href
|
||||
};
|
||||
const manifest = ManifestProcessor.process(args);
|
||||
return manifest;
|
||||
});
|
||||
|
||||
/**
|
||||
* Asynchronously fetches a web manifest.
|
||||
* @param {Window} a The content Window from where to extract the manifest.
|
||||
* @return {Promise<Object>}
|
||||
*/
|
||||
const fetchManifest = Task.async(function* (aWindow) {
|
||||
if (!aWindow || aWindow.top !== aWindow) {
|
||||
let msg = "Window must be a top-level browsing context.";
|
||||
throw new Error(msg);
|
||||
}
|
||||
const elem = aWindow.document.querySelector("link[rel~='manifest']");
|
||||
if (!elem || !elem.getAttribute("href")) {
|
||||
let msg = `No manifest to fetch at ${aWindow.location}`;
|
||||
throw new Error(msg);
|
||||
}
|
||||
// Throws on malformed URLs
|
||||
const manifestURL = new aWindow.URL(elem.href, elem.baseURI);
|
||||
if (!canLoadManifest(elem)) {
|
||||
let msg = `Content Security Policy: The page's settings blocked the `;
|
||||
msg += `loading of a resource at ${elem.href}`;
|
||||
throw new Error(msg);
|
||||
}
|
||||
const reqInit = {
|
||||
mode: "cors"
|
||||
};
|
||||
if (elem.crossOrigin === "use-credentials") {
|
||||
reqInit.credentials = "include";
|
||||
}
|
||||
const req = new aWindow.Request(manifestURL, reqInit);
|
||||
req.setContentPolicyType(Ci.nsIContentPolicy.TYPE_WEB_MANIFEST);
|
||||
const response = yield aWindow.fetch(req);
|
||||
const manifest = yield processResponse(response, aWindow);
|
||||
return manifest;
|
||||
});
|
||||
|
||||
/**
|
||||
* Checks against security manager if we can load the web manifest.
|
||||
* @param {HTMLLinkElement} aElem The HTML element to security check.
|
||||
* @return {Boolean} True if it can, false if it can't.
|
||||
*/
|
||||
function canLoadManifest(aElem) {
|
||||
const contentPolicy = Cc["@mozilla.org/layout/content-policy;1"]
|
||||
.getService(Ci.nsIContentPolicy);
|
||||
const mimeType = aElem.type || "application/manifest+json";
|
||||
const elemURI = BrowserUtils.makeURI(
|
||||
aElem.href, aElem.ownerDocument.characterSet
|
||||
);
|
||||
const shouldLoad = contentPolicy.shouldLoad(
|
||||
Ci.nsIContentPolicy.TYPE_WEB_MANIFEST, elemURI,
|
||||
aElem.ownerDocument.documentURIObject,
|
||||
aElem, mimeType, null
|
||||
);
|
||||
return shouldLoad === Ci.nsIContentPolicy.ACCEPT;
|
||||
}
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["ManifestObtainer"]; // jshint ignore:line
|
@ -19,12 +19,10 @@
|
||||
* TODO: The constructor should accept the UA's supported display modes.
|
||||
* TODO: hook up developer tools to console. (1086997).
|
||||
*/
|
||||
/*globals Components*/
|
||||
/*globals Components, ValueExtractor, ImageObjectProcessor, ConsoleAPI*/
|
||||
'use strict';
|
||||
const {
|
||||
utils: Cu,
|
||||
interfaces: Ci,
|
||||
classes: Cc
|
||||
utils: Cu
|
||||
} = Components;
|
||||
Cu.importGlobalProperties(['URL']);
|
||||
const displayModes = new Set(['fullscreen', 'standalone', 'minimal-ui',
|
||||
@ -34,41 +32,23 @@ const orientationTypes = new Set(['any', 'natural', 'landscape', 'portrait',
|
||||
'portrait-primary', 'portrait-secondary', 'landscape-primary',
|
||||
'landscape-secondary'
|
||||
]);
|
||||
const {
|
||||
ConsoleAPI
|
||||
} = Cu.import('resource://gre/modules/devtools/Console.jsm', {});
|
||||
Cu.import('resource://gre/modules/devtools/Console.jsm');
|
||||
// ValueExtractor is used by the various processors to get values
|
||||
// from the manifest and to report errors.
|
||||
const {
|
||||
ValueExtractor
|
||||
} = Cu.import('resource://gre/modules/ValueExtractor.js', {});
|
||||
Cu.import('resource://gre/modules/ValueExtractor.jsm');
|
||||
// ImageObjectProcessor is used to process things like icons and images
|
||||
const {
|
||||
ImageObjectProcessor
|
||||
} = Cu.import('resource://gre/modules/ImageObjectProcessor.js', {});
|
||||
Cu.import('resource://gre/modules/ImageObjectProcessor.jsm');
|
||||
|
||||
function ManifestProcessor() {}
|
||||
|
||||
// Static getters
|
||||
Object.defineProperties(ManifestProcessor, {
|
||||
'defaultDisplayMode': {
|
||||
get: function() {
|
||||
return 'browser';
|
||||
}
|
||||
this.ManifestProcessor = { // jshint ignore:line
|
||||
get defaultDisplayMode() {
|
||||
return 'browser';
|
||||
},
|
||||
'displayModes': {
|
||||
get: function() {
|
||||
return displayModes;
|
||||
}
|
||||
get displayModes() {
|
||||
return displayModes;
|
||||
},
|
||||
get orientationTypes() {
|
||||
return orientationTypes;
|
||||
},
|
||||
'orientationTypes': {
|
||||
get: function() {
|
||||
return orientationTypes;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ManifestProcessor.prototype = {
|
||||
// process() method processes JSON text into a clean manifest
|
||||
// that conforms with the W3C specification. Takes an object
|
||||
// expecting the following dictionary items:
|
||||
@ -99,8 +79,8 @@ ManifestProcessor.prototype = {
|
||||
const processedManifest = {
|
||||
'lang': processLangMember(),
|
||||
'start_url': processStartURLMember(),
|
||||
'display': processDisplayMember(),
|
||||
'orientation': processOrientationMember(),
|
||||
'display': processDisplayMember.call(this),
|
||||
'orientation': processOrientationMember.call(this),
|
||||
'name': processNameMember(),
|
||||
'icons': imgObjProcessor.process(
|
||||
rawManifest, manifestURL, 'icons'
|
||||
@ -145,7 +125,7 @@ ManifestProcessor.prototype = {
|
||||
trim: true
|
||||
};
|
||||
const value = extractor.extractValue(spec);
|
||||
if (ManifestProcessor.orientationTypes.has(value)) {
|
||||
if (this.orientationTypes.has(value)) {
|
||||
return value;
|
||||
}
|
||||
// The spec special-cases orientation to return the empty string.
|
||||
@ -161,10 +141,10 @@ ManifestProcessor.prototype = {
|
||||
trim: true
|
||||
};
|
||||
const value = extractor.extractValue(spec);
|
||||
if (ManifestProcessor.displayModes.has(value)) {
|
||||
if (displayModes.has(value)) {
|
||||
return value;
|
||||
}
|
||||
return ManifestProcessor.defaultDisplayMode;
|
||||
return this.defaultDisplayMode;
|
||||
}
|
||||
|
||||
function processScopeMember() {
|
||||
@ -249,8 +229,7 @@ ManifestProcessor.prototype = {
|
||||
objectName: 'manifest',
|
||||
object: rawManifest,
|
||||
property: 'lang',
|
||||
expectedType: 'string',
|
||||
trim: true
|
||||
expectedType: 'string', trim: true
|
||||
};
|
||||
let tag = extractor.extractValue(spec);
|
||||
// TODO: Check if tag is structurally valid.
|
||||
@ -265,5 +244,4 @@ ManifestProcessor.prototype = {
|
||||
}
|
||||
}
|
||||
};
|
||||
this.ManifestProcessor = ManifestProcessor; // jshint ignore:line
|
||||
this.EXPORTED_SYMBOLS = ['ManifestProcessor']; // jshint ignore:line
|
@ -25,9 +25,7 @@ ValueExtractor.prototype = {
|
||||
// objectName: string used to construct the developer warning.
|
||||
// property: the name of the property being extracted.
|
||||
// trim: boolean, if the value should be trimmed (used by string type).
|
||||
extractValue({
|
||||
expectedType, object, objectName, property, trim
|
||||
}) {
|
||||
extractValue({expectedType, object, objectName, property, trim}) {
|
||||
const value = object[property];
|
||||
const isArray = Array.isArray(value);
|
||||
// We need to special-case "array", as it's not a JS primitive.
|
@ -1,19 +0,0 @@
|
||||
/* 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 https://mozilla.org/MPL/2.0/. */
|
||||
/*exported EXPORTED_SYMBOLS, ManifestProcessor, ManifestObtainer*/
|
||||
/*globals Components */
|
||||
'use strict';
|
||||
const {
|
||||
utils: Cu
|
||||
} = Components;
|
||||
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
'ManifestObtainer',
|
||||
'ManifestProcessor'
|
||||
];
|
||||
|
||||
// Export public interfaces
|
||||
for (let symbl of EXPORTED_SYMBOLS) {
|
||||
Cu.import(`resource://gre/modules/${symbl}.js`);
|
||||
}
|
@ -5,11 +5,11 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'ImageObjectProcessor.js',
|
||||
'ManifestObtainer.js',
|
||||
'ManifestProcessor.js',
|
||||
'ValueExtractor.js',
|
||||
'WebManifest.jsm'
|
||||
'ImageObjectProcessor.jsm',
|
||||
'ManifestFinder.jsm',
|
||||
'ManifestObtainer.jsm',
|
||||
'ManifestProcessor.jsm',
|
||||
'ValueExtractor.jsm',
|
||||
]
|
||||
|
||||
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
||||
|
@ -1,2 +1,3 @@
|
||||
[DEFAULT]
|
||||
[browser_ManifestObtainer_obtain.js]
|
||||
[browser_ManifestFinder_browserHasManifestLink.js]
|
||||
[browser_ManifestObtainer_obtain.js]
|
||||
|
@ -0,0 +1,114 @@
|
||||
//Used by JSHint:
|
||||
/*global Cu, BrowserTestUtils, is, ok, add_task, gBrowser, ManifestFinder */
|
||||
"use strict";
|
||||
Cu.import("resource://gre/modules/ManifestFinder.jsm", this); // jshint ignore:line
|
||||
|
||||
const defaultURL =
|
||||
"http://example.org/tests/dom/manifest/test/resource.sjs";
|
||||
const tests = [{
|
||||
expected: "Document has a web manifest.",
|
||||
get tabURL() {
|
||||
let query = [
|
||||
`body=<h1>${this.expected}</h1>`,
|
||||
"Content-Type=text/html; charset=utf-8",
|
||||
];
|
||||
const URL = `${defaultURL}?${query.join("&")}`;
|
||||
return URL;
|
||||
},
|
||||
run(result) {
|
||||
is(result, true, this.expected);
|
||||
},
|
||||
testData: `
|
||||
<link rel="manifesto" href='${defaultURL}?body={"name":"fail"}'>
|
||||
<link rel="foo bar manifest bar test" href='${defaultURL}?body={"name":"value"}'>
|
||||
<link rel="manifest" href='${defaultURL}?body={"name":"fail"}'>`
|
||||
}, {
|
||||
expected: "Document does not have a web manifest.",
|
||||
get tabURL() {
|
||||
let query = [
|
||||
`body=<h1>${this.expected}</h1>`,
|
||||
"Content-Type=text/html; charset=utf-8",
|
||||
];
|
||||
const URL = `${defaultURL}?${query.join("&")}`;
|
||||
return URL;
|
||||
},
|
||||
run(result) {
|
||||
is(result, false, this.expected);
|
||||
},
|
||||
testData: `
|
||||
<link rel="amanifista" href='${defaultURL}?body={"name":"fail"}'>
|
||||
<link rel="foo bar manifesto bar test" href='${defaultURL}?body={"name":"pass-1"}'>
|
||||
<link rel="manifesto" href='${defaultURL}?body={"name":"fail"}'>`
|
||||
}, {
|
||||
expected: "Manifest link is has empty href.",
|
||||
get tabURL() {
|
||||
let query = [
|
||||
`body=<h1>${this.expected}</h1>`,
|
||||
"Content-Type=text/html; charset=utf-8",
|
||||
];
|
||||
const URL = `${defaultURL}?${query.join("&")}`;
|
||||
return URL;
|
||||
},
|
||||
run(result) {
|
||||
is(result, false, this.expected);
|
||||
},
|
||||
testData: `
|
||||
<link rel="manifest" href="">
|
||||
<link rel="manifest" href='${defaultURL}?body={"name":"fail"}'>`
|
||||
}, {
|
||||
expected: "Manifest link is missing.",
|
||||
get tabURL() {
|
||||
let query = [
|
||||
`body=<h1>${this.expected}</h1>`,
|
||||
"Content-Type=text/html; charset=utf-8",
|
||||
];
|
||||
const URL = `${defaultURL}?${query.join("&")}`;
|
||||
return URL;
|
||||
},
|
||||
run(result) {
|
||||
is(result, false, this.expected);
|
||||
},
|
||||
testData: `
|
||||
<link rel="manifest">
|
||||
<link rel="manifest" href='${defaultURL}?body={"name":"fail"}'>`
|
||||
}];
|
||||
|
||||
/**
|
||||
* Test basic API error conditions
|
||||
*/
|
||||
add_task(function* () {
|
||||
let expected = "Invalid types should throw a TypeError.";
|
||||
for (let invalidValue of [undefined, null, 1, {}, "test"]) {
|
||||
try {
|
||||
yield ManifestFinder.contentManifestLink(invalidValue);
|
||||
ok(false, expected);
|
||||
} catch (e) {
|
||||
is(e.name, "TypeError", expected);
|
||||
}
|
||||
try {
|
||||
yield ManifestFinder.browserManifestLink(invalidValue);
|
||||
ok(false, expected);
|
||||
} catch (e) {
|
||||
is(e.name, "TypeError", expected);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
for (let test of tests) {
|
||||
let tabOptions = {
|
||||
gBrowser: gBrowser,
|
||||
url: test.tabURL,
|
||||
};
|
||||
yield BrowserTestUtils.withNewTab(
|
||||
tabOptions,
|
||||
browser => testHasManifest(browser, test)
|
||||
);
|
||||
}
|
||||
|
||||
function* testHasManifest(aBrowser, aTest) {
|
||||
aBrowser.contentWindowAsCPOW.document.head.innerHTML = aTest.testData;
|
||||
const result = yield ManifestFinder.browserHasManifestLink(aBrowser);
|
||||
aTest.run(result);
|
||||
}
|
||||
});
|
@ -1,9 +1,8 @@
|
||||
//Used by JSHint:
|
||||
/*global Cu, BrowserTestUtils, add_task, SpecialPowers, gBrowser, Assert*/
|
||||
'use strict';
|
||||
/*global requestLongerTimeout, Cu, BrowserTestUtils, add_task, SpecialPowers, gBrowser, Assert*/ 'use strict';
|
||||
const {
|
||||
ManifestObtainer
|
||||
} = Cu.import('resource://gre/modules/WebManifest.jsm', {});
|
||||
} = Cu.import('resource://gre/modules/ManifestObtainer.jsm', {});
|
||||
|
||||
requestLongerTimeout(4); // e10s tests take time.
|
||||
const defaultURL =
|
||||
@ -177,10 +176,9 @@ add_task(function*() {
|
||||
}
|
||||
|
||||
function* testObtainingManifest(aBrowser, aTest) {
|
||||
const obtainer = new ManifestObtainer();
|
||||
aBrowser.contentWindowAsCPOW.document.head.innerHTML = aTest.testData;
|
||||
try {
|
||||
const manifest = yield obtainer.obtainManifest(aBrowser);
|
||||
const manifest = yield ManifestObtainer.browserObtainManifest(aBrowser);
|
||||
aTest.run(manifest);
|
||||
} catch (e) {
|
||||
aTest.run(e);
|
||||
@ -194,7 +192,6 @@ add_task(function*() {
|
||||
* in each tab. They should all return pass.
|
||||
*/
|
||||
add_task(function*() {
|
||||
const obtainer = new ManifestObtainer();
|
||||
const defaultPath = '/tests/dom/manifest/test/manifestLoader.html';
|
||||
const tabURLs = [
|
||||
`http://test:80${defaultPath}`,
|
||||
@ -237,7 +234,7 @@ add_task(function*() {
|
||||
// Flood random browsers with requests. Once promises settle, check that
|
||||
// responses all pass.
|
||||
const results = yield Promise.all((
|
||||
for (browser of randBrowsers(browsers, 100)) obtainer.obtainManifest(browser)
|
||||
for (browser of randBrowsers(browsers, 100)) ManifestObtainer.browserObtainManifest(browser)
|
||||
));
|
||||
const expected = 'Expect every manifest to have name equal to `pass`.';
|
||||
const pass = results.every(manifest => manifest.name === 'pass');
|
||||
|
@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Common infrastructure for manifest tests.
|
||||
**/
|
||||
|
||||
/*globals SpecialPowers, ManifestProcessor*/
|
||||
'use strict';
|
||||
const {
|
||||
ManifestProcessor
|
||||
} = SpecialPowers.Cu.import('resource://gre/modules/WebManifest.jsm');
|
||||
const processor = new ManifestProcessor();
|
||||
} = SpecialPowers.Cu.import('resource://gre/modules/ManifestProcessor.jsm');
|
||||
const processor = ManifestProcessor;
|
||||
const manifestURL = new URL(document.location.origin + '/manifest.json');
|
||||
const docURL = document.location;
|
||||
const seperators = '\u2028\u2029\u0020\u00A0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000';
|
||||
|
@ -28,9 +28,9 @@ public:
|
||||
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
|
||||
{
|
||||
size_t amount = 0;
|
||||
amount += mBuffers.SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mBuffers.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (size_t i = 0; i < mBuffers.Length(); i++) {
|
||||
amount += mBuffers[i].SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mBuffers[i].ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
return amount;
|
||||
@ -176,7 +176,7 @@ struct AudioChunk {
|
||||
}
|
||||
|
||||
// Memory in the array is owned by mBuffer.
|
||||
amount += mChannelData.SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mChannelData.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
return amount;
|
||||
}
|
||||
|
||||
|
@ -167,7 +167,7 @@ AudioStream::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
// - mLatencyLog
|
||||
// - mCubebStream
|
||||
|
||||
amount += mInserts.SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mInserts.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mBuffer.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
return amount;
|
||||
|
@ -391,7 +391,7 @@ size_t MediaCacheStream::SizeOfExcludingThis(
|
||||
// Looks like these are not owned:
|
||||
// - mClient
|
||||
// - mPrincipal
|
||||
size_t size = mBlocks.SizeOfExcludingThis(aMallocSizeOf);
|
||||
size_t size = mBlocks.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mReadaheadBlocks.SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mMetadataBlocks.SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mPlayedBlocks.SizeOfExcludingThis(aMallocSizeOf);
|
||||
|
@ -581,7 +581,7 @@ MediaRawData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t size = aMallocSizeOf(this);
|
||||
|
||||
size += mBuffer->SizeOfIncludingThis(aMallocSizeOf);
|
||||
size += mBuffer->ShallowSizeOfIncludingThis(aMallocSizeOf);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -1038,18 +1038,21 @@ MediaFormatReader::Update(TrackType aTrack)
|
||||
mVideo.mIsHardwareAccelerated =
|
||||
mVideo.mDecoder && mVideo.mDecoder->IsHardwareAccelerated();
|
||||
}
|
||||
nsRefPtr<MediaData> output = decoder.mOutput[0];
|
||||
decoder.mOutput.RemoveElementAt(0);
|
||||
decoder.mSizeOfQueue -= 1;
|
||||
if (decoder.mTimeThreshold.isNothing() ||
|
||||
media::TimeUnit::FromMicroseconds(output->mTime) >= decoder.mTimeThreshold.ref()) {
|
||||
ReturnOutput(output, aTrack);
|
||||
decoder.mTimeThreshold.reset();
|
||||
} else {
|
||||
LOGV("Internal Seeking: Dropping frame time:%f wanted:%f (kf:%d)",
|
||||
media::TimeUnit::FromMicroseconds(output->mTime).ToSeconds(),
|
||||
decoder.mTimeThreshold.ref().ToSeconds(),
|
||||
output->mKeyframe);
|
||||
while (decoder.mOutput.Length()) {
|
||||
nsRefPtr<MediaData> output = decoder.mOutput[0];
|
||||
decoder.mOutput.RemoveElementAt(0);
|
||||
decoder.mSizeOfQueue -= 1;
|
||||
if (decoder.mTimeThreshold.isNothing() ||
|
||||
media::TimeUnit::FromMicroseconds(output->mTime) >= decoder.mTimeThreshold.ref()) {
|
||||
ReturnOutput(output, aTrack);
|
||||
decoder.mTimeThreshold.reset();
|
||||
break;
|
||||
} else {
|
||||
LOGV("Internal Seeking: Dropping frame time:%f wanted:%f (kf:%d)",
|
||||
media::TimeUnit::FromMicroseconds(output->mTime).ToSeconds(),
|
||||
decoder.mTimeThreshold.ref().ToSeconds(),
|
||||
output->mKeyframe);
|
||||
}
|
||||
}
|
||||
} else if (decoder.mDrainComplete) {
|
||||
decoder.mDrainComplete = false;
|
||||
@ -1195,8 +1198,9 @@ MediaFormatReader::ResetDecode()
|
||||
void
|
||||
MediaFormatReader::Output(TrackType aTrack, MediaData* aSample)
|
||||
{
|
||||
LOGV("Decoded %s sample time=%lld dur=%lld",
|
||||
TrackTypeToStr(aTrack), aSample->mTime, aSample->mDuration);
|
||||
LOGV("Decoded %s sample time=%lld timecode=%lld kf=%d dur=%lld",
|
||||
TrackTypeToStr(aTrack), aSample->mTime, aSample->mTimecode,
|
||||
aSample->mKeyframe, aSample->mDuration);
|
||||
|
||||
if (!aSample) {
|
||||
NS_WARNING("MediaFormatReader::Output() passed a null sample");
|
||||
|
@ -291,7 +291,7 @@ public:
|
||||
|
||||
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
|
||||
{
|
||||
size_t amount = mChunks.SizeOfExcludingThis(aMallocSizeOf);
|
||||
size_t amount = mChunks.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (size_t i = 0; i < mChunks.Length(); i++) {
|
||||
amount += mChunks[i].SizeOfExcludingThisIfUnshared(aMallocSizeOf);
|
||||
}
|
||||
|
@ -1950,15 +1950,15 @@ MediaStream::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
// - mAudioOutputStream - elements
|
||||
|
||||
amount += mBuffer.SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mAudioOutputs.SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mVideoOutputs.SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mAudioOutputs.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mVideoOutputs.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mExplicitBlockerCount.SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mListeners.SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mMainThreadListeners.SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mDisabledTrackIDs.SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mListeners.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mMainThreadListeners.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mDisabledTrackIDs.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mBlocked.SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mGraphUpdateIndices.SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mConsumers.SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mConsumers.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
@ -1199,7 +1199,7 @@ public:
|
||||
size_t amount = MediaStream::SizeOfExcludingThis(aMallocSizeOf);
|
||||
// Not owned:
|
||||
// - mInputs elements
|
||||
amount += mInputs.SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mInputs.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
return amount;
|
||||
}
|
||||
|
||||
|
@ -546,7 +546,7 @@ size_t
|
||||
RtspMediaResource::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t size = BaseMediaResource::SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mTrackBuffer.SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mTrackBuffer.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
// Include the size of each track buffer.
|
||||
for (size_t i = 0; i < mTrackBuffer.Length(); i++) {
|
||||
|
@ -177,7 +177,7 @@ public:
|
||||
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t amount = 0;
|
||||
amount += mTracks.SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mTracks.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
for (size_t i = 0; i < mTracks.Length(); i++) {
|
||||
amount += mTracks[i]->SizeOfIncludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ public:
|
||||
|
||||
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return mChanges.SizeOfExcludingThis(aMallocSizeOf);
|
||||
return mChanges.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -202,7 +202,7 @@ MediaEncoder::GetEncodedData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
|
||||
rv = mWriter->GetContainerData(aOutputBufs,
|
||||
ContainerWriter::GET_HEADER);
|
||||
if (aOutputBufs != nullptr) {
|
||||
mSizeOfBuffer = aOutputBufs->SizeOfExcludingThis(MallocSizeOf);
|
||||
mSizeOfBuffer = aOutputBufs->ShallowSizeOfExcludingThis(MallocSizeOf);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(LogLevel::Error,("Error! writer fail to generate header!"));
|
||||
@ -237,7 +237,7 @@ MediaEncoder::GetEncodedData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
|
||||
isAudioCompleted && isVideoCompleted ?
|
||||
ContainerWriter::FLUSH_NEEDED : 0);
|
||||
if (aOutputBufs != nullptr) {
|
||||
mSizeOfBuffer = aOutputBufs->SizeOfExcludingThis(MallocSizeOf);
|
||||
mSizeOfBuffer = aOutputBufs->ShallowSizeOfExcludingThis(MallocSizeOf);
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Successfully get the copy of final container data from writer.
|
||||
|
@ -291,8 +291,9 @@ private:
|
||||
uint64_t size = reader.ReadU32();
|
||||
const uint8_t* typec = reader.Peek(4);
|
||||
uint32_t type = reader.ReadU32();
|
||||
MSE_DEBUGV(AtomParser ,"Checking atom:'%c%c%c%c'",
|
||||
typec[0], typec[1], typec[2], typec[3]);
|
||||
MSE_DEBUGV(AtomParser ,"Checking atom:'%c%c%c%c' @ %u",
|
||||
typec[0], typec[1], typec[2], typec[3],
|
||||
(uint32_t)reader.Offset() - 8);
|
||||
if (mInitOffset.isNothing() &&
|
||||
mp4_demuxer::AtomType(type) == initAtom) {
|
||||
mInitOffset = Some(reader.Offset());
|
||||
|
@ -103,8 +103,7 @@ IsTypeSupported(const nsAString& aType)
|
||||
}
|
||||
return NS_OK;
|
||||
} else if (DecoderTraits::IsWebMType(mimeTypeUTF8)) {
|
||||
if (!Preferences::GetBool("media.mediasource.webm.enabled", false) ||
|
||||
Preferences::GetBool("media.mediasource.format-reader", false)) {
|
||||
if (!Preferences::GetBool("media.mediasource.webm.enabled", false)) {
|
||||
return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
|
||||
}
|
||||
if (hasCodecs &&
|
||||
|
@ -361,7 +361,7 @@ MediaSourceTrackDemuxer::BreakCycles()
|
||||
nsRefPtr<MediaSourceTrackDemuxer::SeekPromise>
|
||||
MediaSourceTrackDemuxer::DoSeek(media::TimeUnit aTime)
|
||||
{
|
||||
if (aTime.ToMicroseconds() && !mBufferedRanges.Contains(aTime)) {
|
||||
if (!mBufferedRanges.Contains(aTime)) {
|
||||
// We don't have the data to seek to.
|
||||
return SeekPromise::CreateAndReject(DemuxerFailureReason::WAITING_FOR_DATA,
|
||||
__func__);
|
||||
|
@ -34,7 +34,7 @@ ResourceItem::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
size_t size = aMallocSizeOf(this);
|
||||
|
||||
// size excluding this
|
||||
size += mData->SizeOfExcludingThis(aMallocSizeOf);
|
||||
size += mData->ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
@ -386,7 +386,7 @@ TrackBuffersManager::CompleteResetParserState()
|
||||
mInputBuffer = new MediaByteBuffer;
|
||||
mInputBuffer->AppendElements(*mInitData);
|
||||
}
|
||||
RecreateParser();
|
||||
RecreateParser(true);
|
||||
|
||||
// 7. Set append state to WAITING_FOR_SEGMENT.
|
||||
SetAppendState(AppendState::WAITING_FOR_SEGMENT);
|
||||
@ -558,9 +558,6 @@ TrackBuffersManager::CodedFrameRemoval(TimeInterval aInterval)
|
||||
}
|
||||
mEvictionOccurred = true;
|
||||
|
||||
// Tell our demuxer that data was removed.
|
||||
mMediaSourceDemuxer->NotifyTimeRangesChanged();
|
||||
|
||||
return dataRemoved;
|
||||
}
|
||||
|
||||
@ -584,6 +581,9 @@ TrackBuffersManager::UpdateBufferedRanges()
|
||||
#endif
|
||||
|
||||
mOfficialGroupEndTimestamp = mGroupEndTimestamp;
|
||||
|
||||
// Tell our demuxer that data was removed or added.
|
||||
mMediaSourceDemuxer->NotifyTimeRangesChanged();
|
||||
}
|
||||
|
||||
nsRefPtr<TrackBuffersManager::AppendPromise>
|
||||
@ -649,8 +649,7 @@ TrackBuffersManager::SegmentParserLoop()
|
||||
SetAppendState(AppendState::PARSING_INIT_SEGMENT);
|
||||
if (mFirstInitializationSegmentReceived) {
|
||||
// This is a new initialization segment. Obsolete the old one.
|
||||
mInitData = nullptr;
|
||||
RecreateParser();
|
||||
RecreateParser(false);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -994,7 +993,7 @@ TrackBuffersManager::OnDemuxerInitDone(nsresult)
|
||||
// This step has already been done in InitializationSegmentReceived when we
|
||||
// transferred the content into mCurrentInputBuffer.
|
||||
mCurrentInputBuffer->EvictAll();
|
||||
RecreateParser();
|
||||
RecreateParser(true);
|
||||
|
||||
// 4. Set append state to WAITING_FOR_SEGMENT.
|
||||
SetAppendState(AppendState::WAITING_FOR_SEGMENT);
|
||||
@ -1191,14 +1190,11 @@ TrackBuffersManager::CompleteCodedFrameProcessing()
|
||||
// from the resource.
|
||||
mCurrentInputBuffer->EvictAll();
|
||||
mInputDemuxer->NotifyDataRemoved();
|
||||
RecreateParser();
|
||||
RecreateParser(true);
|
||||
|
||||
// 7. Set append state to WAITING_FOR_SEGMENT.
|
||||
SetAppendState(AppendState::WAITING_FOR_SEGMENT);
|
||||
|
||||
// Tell our demuxer that data was added.
|
||||
mMediaSourceDemuxer->NotifyTimeRangesChanged();
|
||||
|
||||
// 8. Jump to the loop top step above.
|
||||
ResolveProcessing(false, __func__);
|
||||
}
|
||||
@ -1515,6 +1511,14 @@ TrackBuffersManager::InsertFrames(TrackBuffer& aSamples,
|
||||
CheckNextInsertionIndex(aTrackData,
|
||||
TimeUnit::FromMicroseconds(aSamples[0]->mTime));
|
||||
|
||||
// Adjust our demuxing index if necessary.
|
||||
if (trackBuffer.mNextGetSampleIndex.isSome() &&
|
||||
(trackBuffer.mNextInsertionIndex.ref() < trackBuffer.mNextGetSampleIndex.ref() ||
|
||||
(trackBuffer.mNextInsertionIndex.ref() == trackBuffer.mNextGetSampleIndex.ref() &&
|
||||
aIntervals.GetEnd() < trackBuffer.mNextSampleTime))) {
|
||||
trackBuffer.mNextGetSampleIndex.ref() += aSamples.Length();
|
||||
}
|
||||
|
||||
TrackBuffer& data = trackBuffer.mBuffers.LastElement();
|
||||
data.InsertElementsAt(trackBuffer.mNextInsertionIndex.ref(), aSamples);
|
||||
trackBuffer.mNextInsertionIndex.ref() += aSamples.Length();
|
||||
@ -1624,7 +1628,7 @@ TrackBuffersManager::RemoveFrames(const TimeIntervals& aIntervals,
|
||||
}
|
||||
|
||||
void
|
||||
TrackBuffersManager::RecreateParser()
|
||||
TrackBuffersManager::RecreateParser(bool aReuseInitData)
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
// Recreate our parser for only the data remaining. This is required
|
||||
@ -1632,7 +1636,7 @@ TrackBuffersManager::RecreateParser()
|
||||
// Once the old TrackBuffer/MediaSource implementation is removed
|
||||
// we can optimize this part. TODO
|
||||
mParser = ContainerParser::CreateForMIMEType(mType);
|
||||
if (mInitData) {
|
||||
if (aReuseInitData && mInitData) {
|
||||
int64_t start, end;
|
||||
mParser->ParseStartAndEndTimestamps(mInitData, start, end);
|
||||
mProcessedInput = mInitData->Length();
|
||||
|
@ -154,9 +154,9 @@ private:
|
||||
// ContainerParser objects and methods.
|
||||
// Those are used to parse the incoming input buffer.
|
||||
|
||||
// Recreate the ContainerParser and only feed it with the previous init
|
||||
// segment found.
|
||||
void RecreateParser();
|
||||
// Recreate the ContainerParser and if aReuseInitData is true then
|
||||
// feed it with the previous init segment found.
|
||||
void RecreateParser(bool aReuseInitData);
|
||||
nsAutoPtr<ContainerParser> mParser;
|
||||
|
||||
// Demuxer objects and methods.
|
||||
|
@ -65,6 +65,10 @@ skip-if = true # bug 1182946
|
||||
[test_MediaSource_mp4.html]
|
||||
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
|
||||
[test_MediaSource_disabled.html]
|
||||
[test_MultipleInitSegments.html]
|
||||
skip-if = true # bug 1182946
|
||||
[test_MultipleInitSegments_mp4.html]
|
||||
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
|
||||
[test_SeekableAfterEndOfStream.html]
|
||||
skip-if = true # bug 1182946
|
||||
[test_SeekableAfterEndOfStream_mp4.html]
|
||||
|
53
dom/media/mediasource/test/test_MultipleInitSegments.html
Normal file
53
dom/media/mediasource/test/test_MultipleInitSegments.html
Normal file
@ -0,0 +1,53 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=windows-1252">
|
||||
<title>MSE: Append buffer with multiple init segments</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="mediasource.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
runWithMSE(function (ms, v) {
|
||||
ms.addEventListener("sourceopen", function () {
|
||||
var sb = ms.addSourceBuffer("video/webm");
|
||||
fetchWithXHR("seek_lowres.webm", function (seek_lowres) {
|
||||
fetchWithXHR("seek.webm", function (seek) {
|
||||
var data = [
|
||||
[seek_lowres, 0, 438], // lowres init segment
|
||||
[seek_lowres, 438, 25950], // lowres media segment 0-1
|
||||
[seek, 0, 318], // init segment
|
||||
[seek, 46712, 67833] // media segment 0.8-1.201
|
||||
];
|
||||
var length = data.map(d => d[2] - d[1]).reduce((a, b) => a + b);
|
||||
var arrayBuffer = new Uint8Array(length);
|
||||
var pos = 0;
|
||||
data.forEach(function(d) {
|
||||
var buffer = new Uint8Array(d[0], d[1], d[2]-d[1]);
|
||||
arrayBuffer.set(buffer, pos);
|
||||
pos += buffer.byteLength;
|
||||
});
|
||||
loadSegment.bind(null, sb, arrayBuffer)().then(function() {
|
||||
// Since we are passing multiple segments in one buffer,
|
||||
// the first durationchange event from parsing the init
|
||||
// segment will be fired before updateend.
|
||||
v.addEventListener("durationchange", function () {
|
||||
ok(v.duration, 1.201);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
ms.endOfStream();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,52 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=windows-1252">
|
||||
<title>MSE: Append buffer with multiple init segments</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="mediasource.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
runWithMSE(function (ms, v) {
|
||||
ms.addEventListener("sourceopen", function () {
|
||||
var sb = ms.addSourceBuffer("video/mp4");
|
||||
fetchWithXHR("bipbop/bipbop_videoinit.mp4", function (init) {
|
||||
init = new Uint8Array(init);
|
||||
fetchWithXHR("bipbop/bipbop_video1.m4s", function (segment1) {
|
||||
segment1 = new Uint8Array(segment1);
|
||||
fetchWithXHR("bipbop/bipbop_video2.m4s", function (segment2) {
|
||||
segment2 = new Uint8Array(segment2);
|
||||
var data = [init, segment1, init, segment2];
|
||||
var length = data.map(d => d.byteLength).reduce((a, b) => a + b);
|
||||
var arrayBuffer = new Uint8Array(length);
|
||||
var pos = 0;
|
||||
data.forEach(function(buffer) {
|
||||
arrayBuffer.set(buffer, pos);
|
||||
pos += buffer.byteLength;
|
||||
});
|
||||
loadSegment.bind(null, sb, arrayBuffer)().then(function() {
|
||||
// Since we are passing multiple segments in one buffer,
|
||||
// the first durationchange event from parsing the init
|
||||
// segment will be fired before updateend.
|
||||
v.addEventListener("durationchange", function () {
|
||||
ok(v.duration, 1.601666);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
ms.endOfStream();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user