aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bluetoothdevice.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/bluetoothdevice.rs')
-rw-r--r--components/script/dom/bluetoothdevice.rs156
1 files changed, 132 insertions, 24 deletions
diff --git a/components/script/dom/bluetoothdevice.rs b/components/script/dom/bluetoothdevice.rs
index b257b82f343..d56970c0d98 100644
--- a/components/script/dom/bluetoothdevice.rs
+++ b/components/script/dom/bluetoothdevice.rs
@@ -2,17 +2,20 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-use bluetooth_traits::{BluetoothCharacteristicMsg, BluetoothDescriptorMsg, BluetoothServiceMsg};
+use bluetooth_traits::{BluetoothCharacteristicMsg, BluetoothDescriptorMsg};
+use bluetooth_traits::{BluetoothRequest, BluetoothResponse, BluetoothServiceMsg};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::BluetoothDeviceBinding;
use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
-use dom::bindings::js::{JS, Root, MutHeap, MutNullableHeap};
+use dom::bindings::error::Error;
+use dom::bindings::error::ErrorResult;
+use dom::bindings::inheritance::Castable;
+use dom::bindings::js::{MutJS, MutNullableJS, Root};
use dom::bindings::reflector::{DomObject, reflect_dom_object};
use dom::bindings::str::DOMString;
-use dom::bluetooth::Bluetooth;
-use dom::bluetoothadvertisingdata::BluetoothAdvertisingData;
+use dom::bluetooth::{AsyncBluetoothListener, Bluetooth, response_async};
use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties;
use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic;
use dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor;
@@ -20,8 +23,12 @@ use dom::bluetoothremotegattserver::BluetoothRemoteGATTServer;
use dom::bluetoothremotegattservice::BluetoothRemoteGATTService;
use dom::eventtarget::EventTarget;
use dom::globalscope::GlobalScope;
+use dom::promise::Promise;
+use ipc_channel::ipc::{self, IpcSender};
+use js::jsapi::JSContext;
+use std::cell::Cell;
use std::collections::HashMap;
-
+use std::rc::Rc;
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothdevice
#[dom_struct]
@@ -29,47 +36,48 @@ pub struct BluetoothDevice {
eventtarget: EventTarget,
id: DOMString,
name: Option<DOMString>,
- ad_data: MutHeap<JS<BluetoothAdvertisingData>>,
- gatt: MutNullableHeap<JS<BluetoothRemoteGATTServer>>,
- context: MutHeap<JS<Bluetooth>>,
- attribute_instance_map: (DOMRefCell<HashMap<String, MutHeap<JS<BluetoothRemoteGATTService>>>>,
- DOMRefCell<HashMap<String, MutHeap<JS<BluetoothRemoteGATTCharacteristic>>>>,
- DOMRefCell<HashMap<String, MutHeap<JS<BluetoothRemoteGATTDescriptor>>>>),
+ gatt: MutNullableJS<BluetoothRemoteGATTServer>,
+ context: MutJS<Bluetooth>,
+ attribute_instance_map: (DOMRefCell<HashMap<String, MutJS<BluetoothRemoteGATTService>>>,
+ DOMRefCell<HashMap<String, MutJS<BluetoothRemoteGATTCharacteristic>>>,
+ DOMRefCell<HashMap<String, MutJS<BluetoothRemoteGATTDescriptor>>>),
+ watching_advertisements: Cell<bool>,
}
impl BluetoothDevice {
pub fn new_inherited(id: DOMString,
name: Option<DOMString>,
- ad_data: &BluetoothAdvertisingData,
context: &Bluetooth)
-> BluetoothDevice {
BluetoothDevice {
eventtarget: EventTarget::new_inherited(),
id: id,
name: name,
- ad_data: MutHeap::new(ad_data),
gatt: Default::default(),
- context: MutHeap::new(context),
+ context: MutJS::new(context),
attribute_instance_map: (DOMRefCell::new(HashMap::new()),
DOMRefCell::new(HashMap::new()),
DOMRefCell::new(HashMap::new())),
+ watching_advertisements: Cell::new(false),
}
}
pub fn new(global: &GlobalScope,
id: DOMString,
name: Option<DOMString>,
- adData: &BluetoothAdvertisingData,
context: &Bluetooth)
-> Root<BluetoothDevice> {
reflect_dom_object(box BluetoothDevice::new_inherited(id,
name,
- adData,
context),
global,
BluetoothDeviceBinding::Wrap)
}
+ fn get_context(&self) -> Root<Bluetooth> {
+ self.context.get()
+ }
+
pub fn get_or_create_service(&self,
service: &BluetoothServiceMsg,
server: &BluetoothRemoteGATTServer)
@@ -84,7 +92,7 @@ impl BluetoothDevice {
DOMString::from(service.uuid.clone()),
service.is_primary,
service.instance_id.clone());
- service_map.insert(service.instance_id.clone(), MutHeap::new(&bt_service));
+ service_map.insert(service.instance_id.clone(), MutJS::new(&bt_service));
return bt_service;
}
@@ -113,10 +121,17 @@ impl BluetoothDevice {
DOMString::from(characteristic.uuid.clone()),
&properties,
characteristic.instance_id.clone());
- characteristic_map.insert(characteristic.instance_id.clone(), MutHeap::new(&bt_characteristic));
+ characteristic_map.insert(characteristic.instance_id.clone(), MutJS::new(&bt_characteristic));
return bt_characteristic;
}
+ pub fn is_represented_device_null(&self) -> bool {
+ let (sender, receiver) = ipc::channel().unwrap();
+ self.get_bluetooth_thread().send(
+ BluetoothRequest::IsRepresentedDeviceNull(self.Id().to_string(), sender)).unwrap();
+ receiver.recv().unwrap()
+ }
+
pub fn get_or_create_descriptor(&self,
descriptor: &BluetoothDescriptorMsg,
characteristic: &BluetoothRemoteGATTCharacteristic)
@@ -130,9 +145,67 @@ impl BluetoothDevice {
characteristic,
DOMString::from(descriptor.uuid.clone()),
descriptor.instance_id.clone());
- descriptor_map.insert(descriptor.instance_id.clone(), MutHeap::new(&bt_descriptor));
+ descriptor_map.insert(descriptor.instance_id.clone(), MutJS::new(&bt_descriptor));
return bt_descriptor;
}
+
+ fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
+ self.global().as_window().bluetooth_thread()
+ }
+
+ // https://webbluetoothcg.github.io/web-bluetooth/#clean-up-the-disconnected-device
+ #[allow(unrooted_must_root)]
+ pub fn clean_up_disconnected_device(&self) {
+ // Step 1.
+ self.Gatt().set_connected(false);
+
+ // TODO: Step 2: Implement activeAlgorithms internal slot for BluetoothRemoteGATTServer.
+
+ // Step 3: We don't need `context`, we get the attributeInstanceMap from the device.
+ // https://github.com/WebBluetoothCG/web-bluetooth/issues/330
+
+ // Step 4.
+ let mut service_map = self.attribute_instance_map.0.borrow_mut();
+ let service_ids = service_map.drain().map(|(id, _)| id).collect();
+
+ let mut characteristic_map = self.attribute_instance_map.1.borrow_mut();
+ let characteristic_ids = characteristic_map.drain().map(|(id, _)| id).collect();
+
+ let mut descriptor_map = self.attribute_instance_map.2.borrow_mut();
+ let descriptor_ids = descriptor_map.drain().map(|(id, _)| id).collect();
+
+ // Step 5, 6.4, 7.
+ // TODO: Step 6: Implement `active notification context set` for BluetoothRemoteGATTCharacteristic.
+ let _ = self.get_bluetooth_thread().send(
+ BluetoothRequest::SetRepresentedToNull(service_ids, characteristic_ids, descriptor_ids));
+
+ // Step 8.
+ self.upcast::<EventTarget>().fire_bubbling_event(atom!("gattserverdisconnected"));
+ }
+
+ // https://webbluetoothcg.github.io/web-bluetooth/#garbage-collect-the-connection
+ #[allow(unrooted_must_root)]
+ pub fn garbage_collect_the_connection(&self) -> ErrorResult {
+ // Step 1: TODO: Check if other systems using this device.
+
+ // Step 2.
+ let context = self.get_context();
+ for (id, device) in context.get_device_map().borrow().iter() {
+ // Step 2.1 - 2.2.
+ if id == &self.Id().to_string() {
+ if device.get().Gatt().Connected() {
+ return Ok(());
+ }
+ // TODO: Step 2.3: Implement activeAlgorithms internal slot for BluetoothRemoteGATTServer.
+ }
+ }
+
+ // Step 3.
+ let (sender, receiver) = ipc::channel().unwrap();
+ self.get_bluetooth_thread().send(
+ BluetoothRequest::GATTServerDisconnect(String::from(self.Id()), sender)).unwrap();
+ receiver.recv().unwrap().map_err(Error::from)
+ }
}
impl BluetoothDeviceMethods for BluetoothDevice {
@@ -146,11 +219,6 @@ impl BluetoothDeviceMethods for BluetoothDevice {
self.name.clone()
}
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-addata
- fn AdData(&self) -> Root<BluetoothAdvertisingData> {
- self.ad_data.get()
- }
-
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-gatt
fn Gatt(&self) -> Root<BluetoothRemoteGATTServer> {
// TODO: Step 1 - 2: Implement the Permission API.
@@ -159,6 +227,46 @@ impl BluetoothDeviceMethods for BluetoothDevice {
})
}
+ #[allow(unrooted_must_root)]
+ // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-watchadvertisements
+ fn WatchAdvertisements(&self) -> Rc<Promise> {
+ let p = Promise::new(&self.global());
+ let sender = response_async(&p, self);
+ // TODO: Step 1.
+ // Note: Steps 2 - 3 are implemented in components/bluetooth/lib.rs in watch_advertisements function
+ // and in handle_response function.
+ self.get_bluetooth_thread().send(
+ BluetoothRequest::WatchAdvertisements(String::from(self.Id()), sender)).unwrap();
+ return p;
+ }
+
+ // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-unwatchadvertisements
+ fn UnwatchAdvertisements(&self) -> () {
+ // Step 1.
+ self.watching_advertisements.set(false)
+ // TODO: Step 2.
+ }
+
+ // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-watchingadvertisements
+ fn WatchingAdvertisements(&self) -> bool {
+ self.watching_advertisements.get()
+ }
+
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdeviceeventhandlers-ongattserverdisconnected
event_handler!(gattserverdisconnected, GetOngattserverdisconnected, SetOngattserverdisconnected);
}
+
+impl AsyncBluetoothListener for BluetoothDevice {
+ fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc<Promise>) {
+ match response {
+ // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-unwatchadvertisements
+ BluetoothResponse::WatchAdvertisements(_result) => {
+ // Step 3.1.
+ self.watching_advertisements.set(true);
+ // Step 3.2.
+ promise.resolve_native(promise_cx, &());
+ },
+ _ => promise.reject_error(promise_cx, Error::Type("Something went wrong...".to_owned())),
+ }
+ }
+}