Merge m-c to fx-team. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-07-30 16:12:48 -04:00
commit 175f356f03
247 changed files with 13101 additions and 14525 deletions

View File

@ -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

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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"
}

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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 ========================================================

File diff suppressed because it is too large Load Diff

View File

@ -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 */
};
/*

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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);
});

View File

@ -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;
}

View File

@ -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);

View File

@ -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();
}
}
}
}

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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, &param);
} 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

View File

@ -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

View File

@ -10,6 +10,8 @@
BEGIN_BLUETOOTH_NAMESPACE
using namespace mozilla::ipc;
//
// A2DP module
//

View File

@ -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

View File

@ -10,6 +10,8 @@
BEGIN_BLUETOOTH_NAMESPACE
using namespace mozilla::ipc;
//
// AVRCP module
//

View File

@ -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

View File

@ -10,6 +10,8 @@
BEGIN_BLUETOOTH_NAMESPACE
using namespace mozilla::ipc;
//
// GATT module
//

View File

@ -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

View File

@ -10,6 +10,8 @@
BEGIN_BLUETOOTH_NAMESPACE
using namespace mozilla::ipc;
//
// Handsfree module
//

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
//

View File

@ -11,6 +11,8 @@
BEGIN_BLUETOOTH_NAMESPACE
using namespace mozilla::ipc;
//
// Socket module
//

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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']

View File

@ -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;
}
},

View File

@ -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",

View File

@ -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);

View File

@ -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 =

View File

@ -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()
{

View File

@ -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
{

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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();

View 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"
];

View File

@ -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

View 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

View File

@ -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

View File

@ -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.

View File

@ -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`);
}

View File

@ -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']

View File

@ -1,2 +1,3 @@
[DEFAULT]
[browser_ManifestObtainer_obtain.js]
[browser_ManifestFinder_browserHasManifestLink.js]
[browser_ManifestObtainer_obtain.js]

View File

@ -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);
}
});

View File

@ -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');

View File

@ -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';

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -581,7 +581,7 @@ MediaRawData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
{
size_t size = aMallocSizeOf(this);
size += mBuffer->SizeOfIncludingThis(aMallocSizeOf);
size += mBuffer->ShallowSizeOfIncludingThis(aMallocSizeOf);
return size;
}

View File

@ -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");

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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++) {

View File

@ -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);
}

View File

@ -217,7 +217,7 @@ public:
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
{
return mChanges.SizeOfExcludingThis(aMallocSizeOf);
return mChanges.ShallowSizeOfExcludingThis(aMallocSizeOf);
}
private:

View File

@ -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.

View File

@ -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());

View File

@ -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 &&

View File

@ -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__);

View File

@ -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;
}

View File

@ -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();

View File

@ -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.

View File

@ -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]

View 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>

View File

@ -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