diff options
Diffstat (limited to 'components/script/dom/bluetoothdevice.rs')
-rw-r--r-- | components/script/dom/bluetoothdevice.rs | 281 |
1 files changed, 163 insertions, 118 deletions
diff --git a/components/script/dom/bluetoothdevice.rs b/components/script/dom/bluetoothdevice.rs index d3e742678bc..bff2e0871ff 100644 --- a/components/script/dom/bluetoothdevice.rs +++ b/components/script/dom/bluetoothdevice.rs @@ -1,32 +1,31 @@ /* 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/. */ + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use crate::dom::bindings::cell::DomRefCell; +use crate::dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods; +use crate::dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; +use crate::dom::bindings::error::Error; +use crate::dom::bindings::error::ErrorResult; +use crate::dom::bindings::inheritance::Castable; +use crate::dom::bindings::reflector::{reflect_dom_object, DomObject}; +use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom}; +use crate::dom::bindings::str::DOMString; +use crate::dom::bluetooth::{response_async, AsyncBluetoothListener, Bluetooth}; +use crate::dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties; +use crate::dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic; +use crate::dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor; +use crate::dom::bluetoothremotegattserver::BluetoothRemoteGATTServer; +use crate::dom::bluetoothremotegattservice::BluetoothRemoteGATTService; +use crate::dom::eventtarget::EventTarget; +use crate::dom::globalscope::GlobalScope; +use crate::dom::promise::Promise; +use crate::realms::InRealm; 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::error::Error; -use dom::bindings::error::ErrorResult; -use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableJS, Root}; -use dom::bindings::reflector::{DomObject, reflect_dom_object}; -use dom::bindings::str::DOMString; -use dom::bluetooth::{AsyncBluetoothListener, Bluetooth, response_async}; -use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties; -use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic; -use dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor; -use dom::bluetoothremotegattserver::BluetoothRemoteGATTServer; -use dom::bluetoothremotegattservice::BluetoothRemoteGATTService; -use dom::eventtarget::EventTarget; -use dom::globalscope::GlobalScope; -use dom::promise::Promise; use dom_struct::dom_struct; -use ipc_channel::ipc::{self, IpcSender}; -use js::jsapi::JSContext; +use ipc_channel::ipc::IpcSender; +use profile_traits::ipc; use std::cell::Cell; use std::collections::HashMap; use std::rc::Rc; @@ -37,122 +36,146 @@ pub struct BluetoothDevice { eventtarget: EventTarget, id: DOMString, name: Option<DOMString>, - gatt: MutNullableJS<BluetoothRemoteGATTServer>, - context: JS<Bluetooth>, - attribute_instance_map: (DOMRefCell<HashMap<String, JS<BluetoothRemoteGATTService>>>, - DOMRefCell<HashMap<String, JS<BluetoothRemoteGATTCharacteristic>>>, - DOMRefCell<HashMap<String, JS<BluetoothRemoteGATTDescriptor>>>), + gatt: MutNullableDom<BluetoothRemoteGATTServer>, + context: Dom<Bluetooth>, + attribute_instance_map: ( + DomRefCell<HashMap<String, Dom<BluetoothRemoteGATTService>>>, + DomRefCell<HashMap<String, Dom<BluetoothRemoteGATTCharacteristic>>>, + DomRefCell<HashMap<String, Dom<BluetoothRemoteGATTDescriptor>>>, + ), watching_advertisements: Cell<bool>, } impl BluetoothDevice { - pub fn new_inherited(id: DOMString, - name: Option<DOMString>, - context: &Bluetooth) - -> BluetoothDevice { + pub fn new_inherited( + id: DOMString, + name: Option<DOMString>, + context: &Bluetooth, + ) -> BluetoothDevice { BluetoothDevice { eventtarget: EventTarget::new_inherited(), id: id, name: name, gatt: Default::default(), - context: JS::from_ref(context), - attribute_instance_map: (DOMRefCell::new(HashMap::new()), - DOMRefCell::new(HashMap::new()), - DOMRefCell::new(HashMap::new())), + context: Dom::from_ref(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>, - context: &Bluetooth) - -> Root<BluetoothDevice> { - reflect_dom_object(box BluetoothDevice::new_inherited(id, - name, - context), - global, - BluetoothDeviceBinding::Wrap) + pub fn new( + global: &GlobalScope, + id: DOMString, + name: Option<DOMString>, + context: &Bluetooth, + ) -> DomRoot<BluetoothDevice> { + reflect_dom_object( + Box::new(BluetoothDevice::new_inherited(id, name, context)), + global, + ) } - pub fn get_gatt(&self) -> Root<BluetoothRemoteGATTServer> { - self.gatt.or_init(|| { - BluetoothRemoteGATTServer::new(&self.global(), self) - }) + pub fn get_gatt(&self) -> DomRoot<BluetoothRemoteGATTServer> { + self.gatt + .or_init(|| BluetoothRemoteGATTServer::new(&self.global(), self)) } - fn get_context(&self) -> Root<Bluetooth> { - Root::from_ref(&self.context) + fn get_context(&self) -> DomRoot<Bluetooth> { + DomRoot::from_ref(&self.context) } - pub fn get_or_create_service(&self, - service: &BluetoothServiceMsg, - server: &BluetoothRemoteGATTServer) - -> Root<BluetoothRemoteGATTService> { + pub fn get_or_create_service( + &self, + service: &BluetoothServiceMsg, + server: &BluetoothRemoteGATTServer, + ) -> DomRoot<BluetoothRemoteGATTService> { let (ref service_map_ref, _, _) = self.attribute_instance_map; let mut service_map = service_map_ref.borrow_mut(); if let Some(existing_service) = service_map.get(&service.instance_id) { - return Root::from_ref(&existing_service); + return DomRoot::from_ref(&existing_service); } - let bt_service = BluetoothRemoteGATTService::new(&server.global(), - &server.Device(), - DOMString::from(service.uuid.clone()), - service.is_primary, - service.instance_id.clone()); - service_map.insert(service.instance_id.clone(), JS::from_ref(&bt_service)); + let bt_service = BluetoothRemoteGATTService::new( + &server.global(), + &server.Device(), + DOMString::from(service.uuid.clone()), + service.is_primary, + service.instance_id.clone(), + ); + service_map.insert(service.instance_id.clone(), Dom::from_ref(&bt_service)); return bt_service; } - pub fn get_or_create_characteristic(&self, - characteristic: &BluetoothCharacteristicMsg, - service: &BluetoothRemoteGATTService) - -> Root<BluetoothRemoteGATTCharacteristic> { + pub fn get_or_create_characteristic( + &self, + characteristic: &BluetoothCharacteristicMsg, + service: &BluetoothRemoteGATTService, + ) -> DomRoot<BluetoothRemoteGATTCharacteristic> { let (_, ref characteristic_map_ref, _) = self.attribute_instance_map; let mut characteristic_map = characteristic_map_ref.borrow_mut(); if let Some(existing_characteristic) = characteristic_map.get(&characteristic.instance_id) { - return Root::from_ref(&existing_characteristic); + return DomRoot::from_ref(&existing_characteristic); } - let properties = - BluetoothCharacteristicProperties::new(&service.global(), - characteristic.broadcast, - characteristic.read, - characteristic.write_without_response, - characteristic.write, - characteristic.notify, - characteristic.indicate, - characteristic.authenticated_signed_writes, - characteristic.reliable_write, - characteristic.writable_auxiliaries); - let bt_characteristic = BluetoothRemoteGATTCharacteristic::new(&service.global(), - service, - DOMString::from(characteristic.uuid.clone()), - &properties, - characteristic.instance_id.clone()); - characteristic_map.insert(characteristic.instance_id.clone(), JS::from_ref(&bt_characteristic)); + let properties = BluetoothCharacteristicProperties::new( + &service.global(), + characteristic.broadcast, + characteristic.read, + characteristic.write_without_response, + characteristic.write, + characteristic.notify, + characteristic.indicate, + characteristic.authenticated_signed_writes, + characteristic.reliable_write, + characteristic.writable_auxiliaries, + ); + let bt_characteristic = BluetoothRemoteGATTCharacteristic::new( + &service.global(), + service, + DOMString::from(characteristic.uuid.clone()), + &properties, + characteristic.instance_id.clone(), + ); + characteristic_map.insert( + characteristic.instance_id.clone(), + Dom::from_ref(&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(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).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) - -> Root<BluetoothRemoteGATTDescriptor> { + pub fn get_or_create_descriptor( + &self, + descriptor: &BluetoothDescriptorMsg, + characteristic: &BluetoothRemoteGATTCharacteristic, + ) -> DomRoot<BluetoothRemoteGATTDescriptor> { let (_, _, ref descriptor_map_ref) = self.attribute_instance_map; let mut descriptor_map = descriptor_map_ref.borrow_mut(); if let Some(existing_descriptor) = descriptor_map.get(&descriptor.instance_id) { - return Root::from_ref(&existing_descriptor); + return DomRoot::from_ref(&existing_descriptor); } - let bt_descriptor = BluetoothRemoteGATTDescriptor::new(&characteristic.global(), - characteristic, - DOMString::from(descriptor.uuid.clone()), - descriptor.instance_id.clone()); - descriptor_map.insert(descriptor.instance_id.clone(), JS::from_ref(&bt_descriptor)); + let bt_descriptor = BluetoothRemoteGATTDescriptor::new( + &characteristic.global(), + characteristic, + DOMString::from(descriptor.uuid.clone()), + descriptor.instance_id.clone(), + ); + descriptor_map.insert( + descriptor.instance_id.clone(), + Dom::from_ref(&bt_descriptor), + ); return bt_descriptor; } @@ -183,11 +206,17 @@ impl BluetoothDevice { // 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)); + let _ = self + .get_bluetooth_thread() + .send(BluetoothRequest::SetRepresentedToNull( + service_ids, + characteristic_ids, + descriptor_ids, + )); // Step 8. - self.upcast::<EventTarget>().fire_bubbling_event(atom!("gattserverdisconnected")); + self.upcast::<EventTarget>() + .fire_bubbling_event(atom!("gattserverdisconnected")); } // https://webbluetoothcg.github.io/web-bluetooth/#garbage-collect-the-connection @@ -208,15 +237,19 @@ impl BluetoothDevice { } // Step 3. - let (sender, receiver) = ipc::channel().unwrap(); - self.get_bluetooth_thread().send( - BluetoothRequest::GATTServerDisconnect(String::from(self.Id()), sender)).unwrap(); + let (sender, receiver) = ipc::channel(self.global().time_profiler_chan().clone()).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 { - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-id + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-id fn Id(&self) -> DOMString { self.id.clone() } @@ -227,26 +260,34 @@ impl BluetoothDeviceMethods for BluetoothDevice { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-gatt - fn GetGatt(&self) -> Option<Root<BluetoothRemoteGATTServer>> { + fn GetGatt(&self) -> Option<DomRoot<BluetoothRemoteGATTServer>> { // Step 1. - if self.global().as_window().bluetooth_extra_permission_data() - .allowed_devices_contains_id(self.id.clone()) && !self.is_represented_device_null() { - return Some(self.get_gatt()) + if self + .global() + .as_window() + .bluetooth_extra_permission_data() + .allowed_devices_contains_id(self.id.clone()) && + !self.is_represented_device_null() + { + return Some(self.get_gatt()); } // Step 2. None } - #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-watchadvertisements - fn WatchAdvertisements(&self) -> Rc<Promise> { - let p = Promise::new(&self.global()); + fn WatchAdvertisements(&self, comp: InRealm) -> Rc<Promise> { + let p = Promise::new_in_current_realm(&self.global(), comp); 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(); + self.get_bluetooth_thread() + .send(BluetoothRequest::WatchAdvertisements( + String::from(self.Id()), + sender, + )) + .unwrap(); return p; } @@ -263,20 +304,24 @@ impl BluetoothDeviceMethods for BluetoothDevice { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdeviceeventhandlers-ongattserverdisconnected - event_handler!(gattserverdisconnected, GetOngattserverdisconnected, SetOngattserverdisconnected); + event_handler!( + gattserverdisconnected, + GetOngattserverdisconnected, + SetOngattserverdisconnected + ); } impl AsyncBluetoothListener for BluetoothDevice { - fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc<Promise>) { + fn handle_response(&self, response: BluetoothResponse, 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.resolve_native(&()); }, - _ => promise.reject_error(promise_cx, Error::Type("Something went wrong...".to_owned())), + _ => promise.reject_error(Error::Type("Something went wrong...".to_owned())), } } } |