diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs index aa2c4c4639af..61a9588dfabe 100644 --- a/components/script/dom/bluetooth.rs +++ b/components/script/dom/bluetooth.rs @@ -21,9 +21,6 @@ use dom::bindings::reflector::{Reflectable, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::bluetoothadvertisingdata::BluetoothAdvertisingData; use dom::bluetoothdevice::BluetoothDevice; -use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic; -use dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor; -use dom::bluetoothremotegattservice::BluetoothRemoteGATTService; use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID}; use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; @@ -90,9 +87,6 @@ impl BluetoothResponseListener f pub struct Bluetooth { eventtarget: EventTarget, device_instance_map: DOMRefCell>>>, - service_instance_map: DOMRefCell>>>, - characteristic_instance_map: DOMRefCell>>>, - descriptor_instance_map: DOMRefCell>>>, } impl Bluetooth { @@ -100,9 +94,6 @@ impl Bluetooth { Bluetooth { eventtarget: EventTarget::new_inherited(), device_instance_map: DOMRefCell::new(HashMap::new()), - service_instance_map: DOMRefCell::new(HashMap::new()), - characteristic_instance_map: DOMRefCell::new(HashMap::new()), - descriptor_instance_map: DOMRefCell::new(HashMap::new()), } } @@ -112,19 +103,6 @@ impl Bluetooth { BluetoothBinding::Wrap) } - pub fn get_service_map(&self) -> &DOMRefCell>>> { - &self.service_instance_map - } - - pub fn get_characteristic_map(&self) - -> &DOMRefCell>>> { - &self.characteristic_instance_map - } - - pub fn get_descriptor_map(&self) -> &DOMRefCell>>> { - &self.descriptor_instance_map - } - fn get_bluetooth_thread(&self) -> IpcSender { self.global().as_window().bluetooth_thread() } diff --git a/components/script/dom/bluetoothdevice.rs b/components/script/dom/bluetoothdevice.rs index 4af6b2a4f592..5bd3bd8233d3 100644 --- a/components/script/dom/bluetoothdevice.rs +++ b/components/script/dom/bluetoothdevice.rs @@ -2,17 +2,26 @@ * 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 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::reflector::{Reflectable, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::bluetooth::Bluetooth; use dom::bluetoothadvertisingdata::BluetoothAdvertisingData; +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 std::collections::HashMap; + // https://webbluetoothcg.github.io/web-bluetooth/#bluetoothdevice #[dom_struct] @@ -23,6 +32,9 @@ pub struct BluetoothDevice { ad_data: MutHeap>, gatt: MutNullableHeap>, context: MutHeap>, + attribute_instance_map: (DOMRefCell>>>, + DOMRefCell>>>, + DOMRefCell>>>), } impl BluetoothDevice { @@ -38,6 +50,9 @@ impl BluetoothDevice { ad_data: MutHeap::new(ad_data), gatt: Default::default(), context: MutHeap::new(context), + attribute_instance_map: (DOMRefCell::new(HashMap::new()), + DOMRefCell::new(HashMap::new()), + DOMRefCell::new(HashMap::new())), } } @@ -55,8 +70,68 @@ impl BluetoothDevice { BluetoothDeviceBinding::Wrap) } - pub fn get_context(&self) -> Root { - self.context.get() + pub fn get_or_create_service(&self, + service: &BluetoothServiceMsg, + server: &BluetoothRemoteGATTServer) + -> Root { + 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 existing_service.get(); + } + 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(), MutHeap::new(&bt_service)); + return bt_service; + } + + pub fn get_or_create_characteristic(&self, + characteristic: &BluetoothCharacteristicMsg, + service: &BluetoothRemoteGATTService) + -> Root { + 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 existing_characteristic.get(); + } + 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(), MutHeap::new(&bt_characteristic)); + return bt_characteristic; + } + + pub fn get_or_create_descriptor(&self, + descriptor: &BluetoothDescriptorMsg, + characteristic: &BluetoothRemoteGATTCharacteristic) + -> Root { + 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 existing_descriptor.get(); + } + let bt_descriptor = BluetoothRemoteGATTDescriptor::new(&characteristic.global(), + characteristic, + DOMString::from(descriptor.uuid.clone()), + descriptor.instance_id.clone()); + descriptor_map.insert(descriptor.instance_id.clone(), MutHeap::new(&bt_descriptor)); + return bt_descriptor; } } diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs index 3c3c86001fb6..ecbb77b64a26 100644 --- a/components/script/dom/bluetoothremotegattcharacteristic.rs +++ b/components/script/dom/bluetoothremotegattcharacteristic.rs @@ -21,7 +21,6 @@ use dom::bindings::reflector::{Reflectable, reflect_dom_object}; use dom::bindings::str::{ByteString, DOMString}; use dom::bluetooth::{AsyncBluetoothListener, response_async}; use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties; -use dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor; use dom::bluetoothremotegattservice::BluetoothRemoteGATTService; use dom::bluetoothuuid::{BluetoothDescriptorUUID, BluetoothUUID}; use dom::eventtarget::EventTarget; @@ -330,21 +329,13 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic { fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc) { + let device = self.Service().Device(); match response { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren // Step 7. BluetoothResponse::GetDescriptor(descriptor) => { - let context = self.service.get().get_device().get_context(); - let mut descriptor_map = context.get_descriptor_map().borrow_mut(); - if let Some(existing_descriptor) = descriptor_map.get(&descriptor.instance_id) { - return promise.resolve_native(promise_cx, &existing_descriptor.get()); - } - let bt_descriptor = BluetoothRemoteGATTDescriptor::new(&self.global(), - self, - DOMString::from(descriptor.uuid), - descriptor.instance_id.clone()); - descriptor_map.insert(descriptor.instance_id, MutHeap::new(&bt_descriptor)); + let bt_descriptor = device.get_or_create_descriptor(&descriptor, &self); promise.resolve_native(promise_cx, &bt_descriptor); }, // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors @@ -352,21 +343,8 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic { // Step 7. BluetoothResponse::GetDescriptors(descriptors_vec) => { let mut descriptors = vec!(); - let context = self.service.get().get_device().get_context(); - let mut descriptor_map = context.get_descriptor_map().borrow_mut(); for descriptor in descriptors_vec { - let bt_descriptor = match descriptor_map.get(&descriptor.instance_id) { - Some(existing_descriptor) => existing_descriptor.get(), - None => { - BluetoothRemoteGATTDescriptor::new(&self.global(), - self, - DOMString::from(descriptor.uuid), - descriptor.instance_id.clone()) - }, - }; - if !descriptor_map.contains_key(&descriptor.instance_id) { - descriptor_map.insert(descriptor.instance_id, MutHeap::new(&bt_descriptor)); - } + let bt_descriptor = device.get_or_create_descriptor(&descriptor, &self); descriptors.push(bt_descriptor); } promise.resolve_native(promise_cx, &descriptors); diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs index 275c7ff9841b..f325414e2304 100644 --- a/components/script/dom/bluetoothremotegattserver.rs +++ b/components/script/dom/bluetoothremotegattserver.rs @@ -11,10 +11,8 @@ use dom::bindings::error::Error::{self, Network, Security}; use dom::bindings::error::ErrorResult; use dom::bindings::js::{JS, MutHeap, Root}; use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; -use dom::bindings::str::DOMString; use dom::bluetooth::{AsyncBluetoothListener, response_async}; use dom::bluetoothdevice::BluetoothDevice; -use dom::bluetoothremotegattservice::BluetoothRemoteGATTService; use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID}; use dom::globalscope::GlobalScope; use dom::promise::Promise; @@ -200,6 +198,7 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { impl AsyncBluetoothListener for BluetoothRemoteGATTServer { fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc) { + let device = self.Device(); match response { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect BluetoothResponse::GATTServerConnect(connected) => { @@ -213,17 +212,7 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTServer { // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren // Step 7. BluetoothResponse::GetPrimaryService(service) => { - let context = self.device.get().get_context(); - let mut service_map = context.get_service_map().borrow_mut(); - if let Some(existing_service) = service_map.get(&service.instance_id) { - promise.resolve_native(promise_cx, &existing_service.get()); - } - let bt_service = BluetoothRemoteGATTService::new(&self.global(), - &self.device.get(), - DOMString::from(service.uuid), - service.is_primary, - service.instance_id.clone()); - service_map.insert(service.instance_id, MutHeap::new(&bt_service)); + let bt_service = device.get_or_create_service(&service, &self); promise.resolve_native(promise_cx, &bt_service); }, // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices @@ -231,22 +220,8 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTServer { // Step 7. BluetoothResponse::GetPrimaryServices(services_vec) => { let mut services = vec!(); - let context = self.device.get().get_context(); - let mut service_map = context.get_service_map().borrow_mut(); for service in services_vec { - let bt_service = match service_map.get(&service.instance_id) { - Some(existing_service) => existing_service.get(), - None => { - BluetoothRemoteGATTService::new(&self.global(), - &self.device.get(), - DOMString::from(service.uuid), - service.is_primary, - service.instance_id.clone()) - }, - }; - if !service_map.contains_key(&service.instance_id) { - service_map.insert(service.instance_id, MutHeap::new(&bt_service)); - } + let bt_service = device.get_or_create_service(&service, &self); services.push(bt_service); } promise.resolve_native(promise_cx, &services); diff --git a/components/script/dom/bluetoothremotegattservice.rs b/components/script/dom/bluetoothremotegattservice.rs index ef922e9b3851..60fcc694ed86 100644 --- a/components/script/dom/bluetoothremotegattservice.rs +++ b/components/script/dom/bluetoothremotegattservice.rs @@ -14,9 +14,7 @@ use dom::bindings::js::{JS, MutHeap, Root}; use dom::bindings::reflector::{Reflectable, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::bluetooth::{AsyncBluetoothListener, response_async}; -use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties; use dom::bluetoothdevice::BluetoothDevice; -use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic; use dom::bluetoothuuid::{BluetoothCharacteristicUUID, BluetoothServiceUUID, BluetoothUUID}; use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; @@ -64,10 +62,6 @@ impl BluetoothRemoteGATTService { BluetoothRemoteGATTServiceBinding::Wrap) } - pub fn get_device(&self) -> Root { - self.device.get() - } - fn get_bluetooth_thread(&self) -> IpcSender { self.global().as_window().bluetooth_thread() } @@ -276,33 +270,13 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { impl AsyncBluetoothListener for BluetoothRemoteGATTService { fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc) { + let device = self.Device(); match response { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren // Step 7. BluetoothResponse::GetCharacteristic(characteristic) => { - let context = self.device.get().get_context(); - let mut characteristic_map = context.get_characteristic_map().borrow_mut(); - if let Some(existing_characteristic) = characteristic_map.get(&characteristic.instance_id) { - return promise.resolve_native(promise_cx, &existing_characteristic.get()); - } - let properties = - BluetoothCharacteristicProperties::new(&self.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(&self.global(), - self, - DOMString::from(characteristic.uuid), - &properties, - characteristic.instance_id.clone()); - characteristic_map.insert(characteristic.instance_id, MutHeap::new(&bt_characteristic)); + let bt_characteristic = device.get_or_create_characteristic(&characteristic, &self); promise.resolve_native(promise_cx, &bt_characteristic); }, // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics @@ -310,34 +284,8 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTService { // Step 7. BluetoothResponse::GetCharacteristics(characteristics_vec) => { let mut characteristics = vec!(); - let context = self.device.get().get_context(); - let mut characteristic_map = context.get_characteristic_map().borrow_mut(); for characteristic in characteristics_vec { - let bt_characteristic = match characteristic_map.get(&characteristic.instance_id) { - Some(existing_characteristic) => existing_characteristic.get(), - None => { - let properties = - BluetoothCharacteristicProperties::new(&self.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); - - BluetoothRemoteGATTCharacteristic::new(&self.global(), - self, - DOMString::from(characteristic.uuid), - &properties, - characteristic.instance_id.clone()) - }, - }; - if !characteristic_map.contains_key(&characteristic.instance_id) { - characteristic_map.insert(characteristic.instance_id, MutHeap::new(&bt_characteristic)); - } + let bt_characteristic = device.get_or_create_characteristic(&characteristic, &self); characteristics.push(bt_characteristic); } promise.resolve_native(promise_cx, &characteristics);