WebAPI/WebBluetooth (Until Firefox OS 2.1)
Contents
WebBluetooth
Goals
The aim of WebBluetooth is to establish a DOM API to set up and communicate with Bluetooth devices. This includes setting properties on adapters and devices, scanning for devices, bonding, and socket initialization.
Firefox OS Needs
Firefox OS is the main consumer of WebBluetooth for the moment. Most operating systems already provide a configuration layer for bluetooth, and we do not plan on overriding that. However, Firefox OS will require its own settings and initialization code, so the focus of the API is on that platform for the time being.
Current Status
Until Firefox OS v2.1, Bluetooth APIs still haven't been exposed for 3rd party web apps. In other words, only certified apps with Bluetooth permission are allowed to use Bluetooth API for now, and there is no interface like BluetoothSocket for Gaia developers to use Bluetooth as a media to transfer data.
Since the API we have now is too BlueZ-specific, we will refine Bluetooth API since Firefox OS v2.2.
DOM API
BluetoothManager.webidl
interface BluetoothManager : EventTarget { [Throws] readonly attribute boolean enabled; attribute EventHandler onenabled; attribute EventHandler ondisabled; attribute EventHandler onadapteradded; [Throws] boolean isConnected(unsigned short aProfile); [NewObject, Throws] DOMRequest? getDefaultAdapter(); };
BluetoothAdapter.webidl
// MediaMetadata and MediaPlayStatus are used to keep data from Applications. // Please see specification of AVRCP 1.3 for more details. dictionary MediaMetaData { // track title DOMString title = ""; // artist name DOMString artist = ""; // album name DOMString album = ""; // track number long long mediaNumber = -1; // number of tracks in the album long long totalMediaCount = -1; // playing time (ms) long long duration = -1; };
dictionary MediaPlayStatus { // current track length (ms) long long duration = -1; // playing time (ms) long long position = -1; // one of 'STOPPED'/'PLAYING'/'PAUSED'/'FWD_SEEK'/'REV_SEEK'/'ERROR' DOMString playStatus = ""; };
interface BluetoothAdapter : EventTarget { readonly attribute DOMString address; readonly attribute unsigned long class; readonly attribute boolean discovering; readonly attribute DOMString name; readonly attribute boolean discoverable; readonly attribute unsigned long discoverableTimeout; // in seconds // array of type BluetoothDevice[] [GetterThrows] readonly attribute any devices; // array of type DOMString[] [GetterThrows] readonly attribute any uuids; attribute EventHandler ondevicefound; // Fired when pairing process is completed attribute EventHandler onpairedstatuschanged; // Fired when a2dp connection status changed attribute EventHandler ona2dpstatuschanged; // Fired when handsfree connection status changed attribute EventHandler onhfpstatuschanged; // Fired when sco connection status changed attribute EventHandler onscostatuschanged; // Fired when remote devices query current media play status attribute EventHandler onrequestmediaplaystatus; [NewObject, Throws] DOMRequest setName(DOMString name); [NewObject, Throws] DOMRequest setDiscoverable(boolean discoverable); [NewObject, Throws] DOMRequest setDiscoverableTimeout(unsigned long timeout); [NewObject, Throws] DOMRequest startDiscovery(); [NewObject, Throws] DOMRequest stopDiscovery(); [NewObject, Throws] DOMRequest pair(DOMString deviceAddress); [NewObject, Throws] DOMRequest unpair(DOMString deviceAddress); [NewObject, Throws] DOMRequest getPairedDevices(); [NewObject, Throws] DOMRequest getConnectedDevices(unsigned short serviceUuid); [NewObject, Throws] DOMRequest setPinCode(DOMString deviceAddress, DOMString pinCode); [NewObject, Throws] DOMRequest setPasskey(DOMString deviceAddress, unsigned long passkey); [NewObject, Throws] DOMRequest setPairingConfirmation(DOMString deviceAddress, boolean confirmation); /** * Connect/Disconnect to a specific service of a target remote device. * To check the value of service UUIDs, please check "Bluetooth Assigned * Numbers" / "Service Discovery Protocol" for more information. * * Note that service UUID is optional. If it isn't passed when calling * Connect, multiple profiles are tried sequentially based on the class of * device (CoD). If it isn't passed when calling Disconnect, all connected * profiles are going to be closed. * * Reply success if the connection of any profile is successfully * established/released; reply error if we failed to connect/disconnect all * of the planned profiles. * * @param device Remote device * @param profile 2-octets service UUID. This is optional. */ [NewObject, Throws] DOMRequest connect(BluetoothDevice device, optional unsigned short serviceUuid); [NewObject, Throws] DOMRequest disconnect(BluetoothDevice device, optional unsigned short serviceUuid); // One device can only send one file at a time [NewObject, Throws] DOMRequest sendFile(DOMString deviceAddress, Blob blob); [NewObject, Throws] DOMRequest stopSendingFile(DOMString deviceAddress); [NewObject, Throws] DOMRequest confirmReceivingFile(DOMString deviceAddress, boolean confirmation); // Connect/Disconnect SCO (audio) connection [NewObject, Throws] DOMRequest connectSco(); [NewObject, Throws] DOMRequest disconnectSco(); [NewObject, Throws] DOMRequest isScoConnected(); /** * Additional HFP methods to handle CDMA network. * * In GSM network we observe call operations from RIL call state changes; * however in CDMA network RIL call states do not change under some call * operations, so we need these additional methods to be informed of these * operations from dialer. * * For more information please refer to bug 912005 and 925638. */ [NewObject, Throws] DOMRequest answerWaitingCall(); [NewObject, Throws] DOMRequest ignoreWaitingCall(); [NewObject, Throws] DOMRequest toggleCalls(); // AVRCP 1.3 methods [NewObject,Throws] DOMRequest sendMediaMetaData(optional MediaMetaData mediaMetaData); [NewObject,Throws] DOMRequest sendMediaPlayStatus(optional MediaPlayStatus mediaPlayStatus); };
BluetoothDevice.webidl
interface BluetoothDevice : EventTarget { readonly attribute DOMString address; readonly attribute DOMString name; readonly attribute DOMString icon; readonly attribute boolean connected; readonly attribute boolean paired; readonly attribute unsigned long class; // array of type DOMString[] [Throws] readonly attribute any uuids; // array of type DOMString[] [Throws] readonly attribute any services; };
Implementation Specifics
For communicating with the bluetooth adapter and devices on Firefox OS, we will be using the DBus message system. This allows us to easily access all parts of the bluetooth system on Firefox OS based platforms, without having to worry about GPL licensing issues.
DBus Usage and Licensing
Bluetooth on Linux and B2G is accessed via the Bluez bluetooth stack. This stack is GPL, and the libraries that come with it to access bluetooth sockets are also GPL. To remove the licensing issues involved with this, the DBus communications layer is used to provide an IPC route for bluetooth related code. The WebBluetooth API (on Linux and Firefox OS) will use DBus to keep the code compatible with the MPL.
DBus on Linux and Android
There are many ways to access DBus from code. On linux, gecko already uses the glib bindings for battery information on linux (UPowerClient.cpp). Android uses the low level DBus bindings, mainly made for writing language binding systems. This tends to create very complicated code, which even the DBus maintainers warn developers off of (See DBus API Documentation). Even so, due to the dbus-c++ library depending on exceptions (though the Chromium project is working on fixing that) and not wanting to fold in glib to Firefox OS, we'll be using the low-level DBus API for Firefox OS's WebBluetooth layer.
Links
Introduction
Bugzilla
External
- DBus Intro
- Android Bluetooth Manual
- Android Bluetooth Architecture
- Bluetool C++ Bluez Interaction Code
- Android Bluetooth FAQ