From b0103682fa2cd5147778e70b065ad4ee051684fd Mon Sep 17 00:00:00 2001 From: Attila Dusnoki Date: Thu, 15 Dec 2016 08:06:42 +0100 Subject: [PATCH] Implement GetGATTChildren --- components/bluetooth/lib.rs | 493 +++++------------- components/bluetooth_traits/lib.rs | 29 +- components/script/dom/bluetooth.rs | 57 +- .../dom/bluetoothremotegattcharacteristic.rs | 87 +--- .../script/dom/bluetoothremotegattserver.rs | 92 +--- .../script/dom/bluetoothremotegattservice.rs | 205 ++------ 6 files changed, 258 insertions(+), 705 deletions(-) diff --git a/components/bluetooth/lib.rs b/components/bluetooth/lib.rs index c90a7e44c781..2d542868e022 100644 --- a/components/bluetooth/lib.rs +++ b/components/bluetooth/lib.rs @@ -15,7 +15,7 @@ extern crate uuid; pub mod test; use bluetooth_traits::{BluetoothCharacteristicMsg, BluetoothDescriptorMsg, BluetoothServiceMsg}; -use bluetooth_traits::{BluetoothDeviceMsg, BluetoothRequest, BluetoothResponse}; +use bluetooth_traits::{BluetoothDeviceMsg, BluetoothRequest, BluetoothResponse, GATTType}; use bluetooth_traits::{BluetoothError, BluetoothResponseResult, BluetoothResult}; use bluetooth_traits::blocklist::{uuid_is_blocklisted, Blocklist}; use bluetooth_traits::scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence, RequestDeviceoptions}; @@ -229,29 +229,8 @@ impl BluetoothManager { BluetoothRequest::GATTServerDisconnect(device_id, sender) => { let _ = sender.send(self.gatt_server_disconnect(device_id)); }, - BluetoothRequest::GetPrimaryService(device_id, uuid, sender) => { - let _ = sender.send(self.get_primary_service(device_id, uuid)); - }, - BluetoothRequest::GetPrimaryServices(device_id, uuid, sender) => { - let _ = sender.send(self.get_primary_services(device_id, uuid)); - }, - BluetoothRequest::GetIncludedService(service_id, uuid, sender) => { - let _ = sender.send(self.get_included_service(service_id, uuid)); - }, - BluetoothRequest::GetIncludedServices(service_id, uuid, sender) => { - let _ = sender.send(self.get_included_services(service_id, uuid)); - }, - BluetoothRequest::GetCharacteristic(service_id, uuid, sender) => { - let _ = sender.send(self.get_characteristic(service_id, uuid)); - }, - BluetoothRequest::GetCharacteristics(service_id, uuid, sender) => { - let _ = sender.send(self.get_characteristics(service_id, uuid)); - }, - BluetoothRequest::GetDescriptor(characteristic_id, uuid, sender) => { - let _ = sender.send(self.get_descriptor(characteristic_id, uuid)); - }, - BluetoothRequest::GetDescriptors(characteristic_id, uuid, sender) => { - let _ = sender.send(self.get_descriptors(characteristic_id, uuid)); + BluetoothRequest::GetGATTChildren(id, uuid, single, child_type, sender) => { + let _ = sender.send(self.get_gatt_children(id, uuid, single, child_type)); }, BluetoothRequest::ReadValue(id, sender) => { let _ = sender.send(self.read_value(id)); @@ -450,15 +429,6 @@ impl BluetoothManager { None } - fn get_gatt_services_by_uuid(&mut self, - adapter: &mut BluetoothAdapter, - device_id: &str, - service_uuid: &str) - -> Vec { - let services = self.get_and_cache_gatt_services(adapter, device_id); - services.into_iter().filter(|s| s.get_uuid().ok() == Some(service_uuid.to_string())).collect() - } - fn service_is_cached(&self, service_id: &str) -> bool { self.cached_services.contains_key(service_id) && self.service_to_device.contains_key(service_id) } @@ -496,17 +466,6 @@ impl BluetoothManager { None } - fn get_gatt_characteristics_by_uuid(&mut self, - adapter: &mut BluetoothAdapter, - service_id: &str, - characteristic_uuid: &str) - -> Vec { - let characteristics = self.get_and_cache_gatt_characteristics(adapter, service_id); - characteristics.into_iter() - .filter(|c| c.get_uuid().ok() == Some(characteristic_uuid.to_string())) - .collect() - } - fn get_characteristic_properties(&self, characteristic: &BluetoothGATTCharacteristic) -> Flags { let mut props: Flags = Flags::empty(); let flags = characteristic.get_flags().unwrap_or(vec!()); @@ -565,17 +524,6 @@ impl BluetoothManager { None } - fn get_gatt_descriptors_by_uuid(&mut self, - adapter: &mut BluetoothAdapter, - characteristic_id: &str, - descriptor_uuid: &str) - -> Vec { - let descriptors = self.get_and_cache_gatt_descriptors(adapter, characteristic_id); - descriptors.into_iter() - .filter(|d| d.get_uuid().ok() == Some(descriptor_uuid.to_string())) - .collect() - } - // Methods // https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices @@ -687,325 +635,158 @@ impl BluetoothManager { } } - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - fn get_primary_service(&mut self, - device_id: String, - uuid: String) - -> BluetoothResponseResult { - // Step 5. - if !self.device_is_cached(&device_id) { - return Err(BluetoothError::InvalidState); - } - + fn get_gatt_children(&mut self, + id: String, + uuid: Option, + single: bool, + child_type: GATTType) + -> BluetoothResponseResult { let mut adapter = try!(self.get_adapter()); - if !self.allowed_services.get(&device_id).map_or(false, |s| s.contains(&uuid)) { - return Err(BluetoothError::Security); - } - let services = self.get_gatt_services_by_uuid(&mut adapter, &device_id, &uuid); - - // Step 6. - for service in services { - if service.is_primary().unwrap_or(false) { - if let Ok(uuid) = service.get_uuid() { - return Ok(BluetoothResponse::GetPrimaryService( - BluetoothServiceMsg { - uuid: uuid, - is_primary: true, - instance_id: service.get_id(), - } - )); + match child_type { + GATTType::PrimaryService => { + // Step 5. + if !self.device_is_cached(&id) { + return Err(BluetoothError::InvalidState); } - } - } - // Step 7. - return Err(BluetoothError::NotFound); - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - fn get_primary_services(&mut self, - device_id: String, - uuid: Option) - -> BluetoothResponseResult { - // Step 5. - if !self.device_is_cached(&device_id) { - return Err(BluetoothError::InvalidState); - } - - let mut adapter = try!(self.get_adapter()); - let services = match uuid { - Some(ref id) => { - if !self.allowed_services.get(&device_id).map_or(false, |s| s.contains(id)) { - return Err(BluetoothError::Security) + // Step 6. + if let Some(ref uuid) = uuid { + if !self.allowed_services.get(&id).map_or(false, |s| s.contains(uuid)) { + return Err(BluetoothError::Security); + } } - self.get_gatt_services_by_uuid(&mut adapter, &device_id, id) - }, - None => self.get_and_cache_gatt_services(&mut adapter, &device_id), - }; - - // Step 6. - let mut services_vec = vec!(); - for service in services { - if service.is_primary().unwrap_or(false) { - if let Ok(uuid) = service.get_uuid() { - services_vec.push( - BluetoothServiceMsg { - uuid: uuid, - is_primary: true, - instance_id: service.get_id(), - } - ); + let mut services = self.get_and_cache_gatt_services(&mut adapter, &id); + if let Some(uuid) = uuid { + services.retain(|ref e| e.get_uuid().unwrap_or(String::new()) == uuid); } - } - } - - // Step 7. - if services_vec.is_empty() { - return Err(BluetoothError::NotFound); - } - - return Ok(BluetoothResponse::GetPrimaryServices(services_vec)); - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservice - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - fn get_included_service(&mut self, - service_id: String, - uuid: String) - -> BluetoothResponseResult { - // Step 5. - if !self.service_is_cached(&service_id) { - return Err(BluetoothError::InvalidState); - } - - let mut adapter = try!(self.get_adapter()); - let device = match self.device_from_service_id(&service_id) { - Some(device) => device, - None => return Err(BluetoothError::NotFound), - }; - let primary_service = match self.get_gatt_service(&mut adapter, &service_id) { - Some(s) => s, - None => return Err(BluetoothError::NotFound), - }; - let services = primary_service.get_includes(device).unwrap_or(vec!()); - - // Step 6. - for service in services { - if let Ok(service_uuid) = service.get_uuid() { - if uuid == service_uuid { - return Ok(BluetoothResponse::GetIncludedService( - BluetoothServiceMsg { - uuid: uuid, - is_primary: service.is_primary().unwrap_or(false), - instance_id: service.get_id(), + let mut services_vec = vec!(); + for service in services { + if service.is_primary().unwrap_or(false) { + if let Ok(uuid) = service.get_uuid() { + services_vec.push( + BluetoothServiceMsg { + uuid: uuid, + is_primary: true, + instance_id: service.get_id(), + } + ); } - )); + } + } + // Step 7. + if services_vec.is_empty() { + return Err(BluetoothError::NotFound); } - } - } - // Step 7. - return Err(BluetoothError::NotFound); - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - fn get_included_services(&mut self, - service_id: String, - uuid: Option) - -> BluetoothResponseResult { - // Step 5. - if !self.service_is_cached(&service_id) { - return Err(BluetoothError::InvalidState); - } - - let mut adapter = try!(self.get_adapter()); - let device = match self.device_from_service_id(&service_id) { - Some(device) => device, - None => return Err(BluetoothError::NotFound), - }; - let primary_service = match self.get_gatt_service(&mut adapter, &service_id) { - Some(s) => s, - None => return Err(BluetoothError::NotFound), - }; - let services = primary_service.get_includes(device).unwrap_or(vec!()); - // Step 6. - let mut services_vec = vec!(); - for service in services { - if let Ok(service_uuid) = service.get_uuid() { - services_vec.push( - BluetoothServiceMsg { - uuid: service_uuid, - is_primary: service.is_primary().unwrap_or(false), - instance_id: service.get_id(), + return Ok(BluetoothResponse::GetPrimaryServices(services_vec, single)); + }, + GATTType::Characteristic => { + // Step 5. + if !self.service_is_cached(&id) { + return Err(BluetoothError::InvalidState); + } + // Step 6. + let mut characteristics = self.get_and_cache_gatt_characteristics(&mut adapter, &id); + if let Some(uuid) = uuid { + characteristics.retain(|ref e| e.get_uuid().unwrap_or(String::new()) == uuid); + } + let mut characteristics_vec = vec!(); + for characteristic in characteristics { + if let Ok(uuid) = characteristic.get_uuid() { + let properties = self.get_characteristic_properties(&characteristic); + characteristics_vec.push( + BluetoothCharacteristicMsg { + uuid: uuid, + instance_id: characteristic.get_id(), + broadcast: properties.contains(BROADCAST), + read: properties.contains(READ), + write_without_response: properties.contains(WRITE_WITHOUT_RESPONSE), + write: properties.contains(WRITE), + notify: properties.contains(NOTIFY), + indicate: properties.contains(INDICATE), + authenticated_signed_writes: properties.contains(AUTHENTICATED_SIGNED_WRITES), + reliable_write: properties.contains(RELIABLE_WRITE), + writable_auxiliaries: properties.contains(WRITABLE_AUXILIARIES), + } + ); } - ); - } - } - if let Some(uuid) = uuid { - services_vec.retain(|ref s| s.uuid == uuid); - } - services_vec.retain(|s| !uuid_is_blocklisted(&s.uuid, Blocklist::All)); - - // Step 7. - if services_vec.is_empty() { - return Err(BluetoothError::NotFound); - } - - return Ok(BluetoothResponse::GetIncludedServices(services_vec)); - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - fn get_characteristic(&mut self, - service_id: String, - uuid: String) - -> BluetoothResponseResult { - // Step 5. - if !self.service_is_cached(&service_id) { - return Err(BluetoothError::InvalidState); - } + } - let mut adapter = try!(self.get_adapter()); - let characteristics = self.get_gatt_characteristics_by_uuid(&mut adapter, &service_id, &uuid); + // Step 7. + if characteristics_vec.is_empty() { + return Err(BluetoothError::NotFound); + } - // Step 6. - for characteristic in characteristics { - if let Ok(uuid) = characteristic.get_uuid() { - let properties = self.get_characteristic_properties(&characteristic); - let message = BluetoothCharacteristicMsg { - uuid: uuid, - instance_id: characteristic.get_id(), - broadcast: properties.contains(BROADCAST), - read: properties.contains(READ), - write_without_response: properties.contains(WRITE_WITHOUT_RESPONSE), - write: properties.contains(WRITE), - notify: properties.contains(NOTIFY), - indicate: properties.contains(INDICATE), - authenticated_signed_writes: properties.contains(AUTHENTICATED_SIGNED_WRITES), - reliable_write: properties.contains(RELIABLE_WRITE), - writable_auxiliaries: properties.contains(WRITABLE_AUXILIARIES), + return Ok(BluetoothResponse::GetCharacteristics(characteristics_vec, single)); + }, + GATTType::IncludedService => { + // Step 5. + if !self.service_is_cached(&id) { + return Err(BluetoothError::InvalidState); + } + // Step 6. + let device = match self.device_from_service_id(&id) { + Some(device) => device, + None => return Err(BluetoothError::NotFound), }; - return Ok(BluetoothResponse::GetCharacteristic(message)); - } - } - // Step 7. - return Err(BluetoothError::NotFound); - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - fn get_characteristics(&mut self, - service_id: String, - uuid: Option) - -> BluetoothResponseResult { - // Step 5. - if !self.service_is_cached(&service_id) { - return Err(BluetoothError::InvalidState); - } - - let mut adapter = try!(self.get_adapter()); - let characteristics = match uuid { - Some(id) => self.get_gatt_characteristics_by_uuid(&mut adapter, &service_id, &id), - None => self.get_and_cache_gatt_characteristics(&mut adapter, &service_id), - }; - - // Step 6. - let mut characteristics_vec = vec!(); - for characteristic in characteristics { - if let Ok(uuid) = characteristic.get_uuid() { - let properties = self.get_characteristic_properties(&characteristic); - characteristics_vec.push( - BluetoothCharacteristicMsg { - uuid: uuid, - instance_id: characteristic.get_id(), - broadcast: properties.contains(BROADCAST), - read: properties.contains(READ), - write_without_response: properties.contains(WRITE_WITHOUT_RESPONSE), - write: properties.contains(WRITE), - notify: properties.contains(NOTIFY), - indicate: properties.contains(INDICATE), - authenticated_signed_writes: properties.contains(AUTHENTICATED_SIGNED_WRITES), - reliable_write: properties.contains(RELIABLE_WRITE), - writable_auxiliaries: properties.contains(WRITABLE_AUXILIARIES), - } - ); - } - } - - // Step 7. - if characteristics_vec.is_empty() { - return Err(BluetoothError::NotFound); - } - - return Ok(BluetoothResponse::GetCharacteristics(characteristics_vec)); - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - fn get_descriptor(&mut self, - characteristic_id: String, - uuid: String) - -> BluetoothResponseResult { - // Step 5. - if !self.characteristic_is_cached(&characteristic_id) { - return Err(BluetoothError::InvalidState); - } - - let mut adapter = try!(self.get_adapter()); - let descriptors = self.get_gatt_descriptors_by_uuid(&mut adapter, &characteristic_id, &uuid); - - // Step 6. - for descriptor in descriptors { - if let Ok(uuid) = descriptor.get_uuid() { - return Ok(BluetoothResponse::GetDescriptor( - BluetoothDescriptorMsg { - uuid: uuid, - instance_id: descriptor.get_id(), + let primary_service = match self.get_gatt_service(&mut adapter, &id) { + Some(s) => s, + None => return Err(BluetoothError::NotFound), + }; + let services = primary_service.get_includes(device).unwrap_or(vec!()); + let mut services_vec = vec!(); + for service in services { + if let Ok(service_uuid) = service.get_uuid() { + services_vec.push( + BluetoothServiceMsg { + uuid: service_uuid, + is_primary: service.is_primary().unwrap_or(false), + instance_id: service.get_id(), + } + ); } - )); - } - } - // Step 7. - return Err(BluetoothError::NotFound); - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - fn get_descriptors(&mut self, - characteristic_id: String, - uuid: Option) - -> BluetoothResponseResult { - // Step 5. - if !self.characteristic_is_cached(&characteristic_id) { - return Err(BluetoothError::InvalidState); - } + } + if let Some(uuid) = uuid { + services_vec.retain(|ref s| s.uuid == uuid); + } + services_vec.retain(|s| !uuid_is_blocklisted(&s.uuid, Blocklist::All)); - let mut adapter = try!(self.get_adapter()); - let descriptors = match uuid { - Some(id) => self.get_gatt_descriptors_by_uuid(&mut adapter, &characteristic_id, &id), - None => self.get_and_cache_gatt_descriptors(&mut adapter, &characteristic_id), - }; + // Step 7. + if services_vec.is_empty() { + return Err(BluetoothError::NotFound); + } - // Step 6. - let mut descriptors_vec = vec!(); - for descriptor in descriptors { - if let Ok(uuid) = descriptor.get_uuid() { - descriptors_vec.push( - BluetoothDescriptorMsg { - uuid: uuid, - instance_id: descriptor.get_id(), + return Ok(BluetoothResponse::GetIncludedServices(services_vec, single)); + }, + GATTType::Descriptor => { + // Step 5. + if !self.characteristic_is_cached(&id) { + return Err(BluetoothError::InvalidState); + } + // Step 6. + let mut descriptors = self.get_and_cache_gatt_descriptors(&mut adapter, &id); + if let Some(uuid) = uuid { + descriptors.retain(|ref e| e.get_uuid().unwrap_or(String::new()) == uuid); + } + let mut descriptors_vec = vec!(); + for descriptor in descriptors { + if let Ok(uuid) = descriptor.get_uuid() { + descriptors_vec.push( + BluetoothDescriptorMsg { + uuid: uuid, + instance_id: descriptor.get_id(), + } + ); } - ); - } - } + } - // Step 7. - if descriptors_vec.is_empty() { - return Err(BluetoothError::NotFound); + // Step 7. + if descriptors_vec.is_empty() { + return Err(BluetoothError::NotFound); + } + return Ok(BluetoothResponse::GetDescriptors(descriptors_vec, single)); + }, } - return Ok(BluetoothResponse::GetDescriptors(descriptors_vec)); } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue diff --git a/components/bluetooth_traits/lib.rs b/components/bluetooth_traits/lib.rs index 81f224ab3bd3..ede1c8ecdba3 100644 --- a/components/bluetooth_traits/lib.rs +++ b/components/bluetooth_traits/lib.rs @@ -26,6 +26,14 @@ pub enum BluetoothError { InvalidState, } +#[derive(Deserialize, Serialize)] +pub enum GATTType { + PrimaryService, + Characteristic, + IncludedService, + Descriptor, +} + #[derive(Deserialize, Serialize)] pub struct BluetoothDeviceMsg { // Bluetooth Device properties @@ -78,14 +86,7 @@ pub enum BluetoothRequest { RequestDevice(RequestDeviceoptions, IpcSender), GATTServerConnect(String, IpcSender), GATTServerDisconnect(String, IpcSender>), - GetPrimaryService(String, String, IpcSender), - GetPrimaryServices(String, Option, IpcSender), - GetIncludedService(String, String, IpcSender), - GetIncludedServices(String, Option, IpcSender), - GetCharacteristic(String, String, IpcSender), - GetCharacteristics(String, Option, IpcSender), - GetDescriptor(String, String, IpcSender), - GetDescriptors(String, Option, IpcSender), + GetGATTChildren(String, Option, bool, GATTType, IpcSender), ReadValue(String, IpcSender), WriteValue(String, Vec, IpcSender), EnableNotification(String, bool, IpcSender), @@ -98,14 +99,10 @@ pub enum BluetoothRequest { pub enum BluetoothResponse { RequestDevice(BluetoothDeviceMsg), GATTServerConnect(bool), - GetPrimaryService(BluetoothServiceMsg), - GetPrimaryServices(BluetoothServicesMsg), - GetIncludedService(BluetoothServiceMsg), - GetIncludedServices(BluetoothServicesMsg), - GetCharacteristic(BluetoothCharacteristicMsg), - GetCharacteristics(BluetoothCharacteristicsMsg), - GetDescriptor(BluetoothDescriptorMsg), - GetDescriptors(BluetoothDescriptorsMsg), + GetPrimaryServices(BluetoothServicesMsg, bool), + GetIncludedServices(BluetoothServicesMsg, bool), + GetCharacteristics(BluetoothCharacteristicsMsg, bool), + GetDescriptors(BluetoothDescriptorsMsg, bool), ReadValue(Vec), WriteValue(Vec), EnableNotification(()), diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs index 440ee882c66c..d2b3ced25feb 100644 --- a/components/script/dom/bluetooth.rs +++ b/components/script/dom/bluetooth.rs @@ -2,7 +2,7 @@ * 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::{BluetoothError, BluetoothRequest}; +use bluetooth_traits::{BluetoothError, BluetoothRequest, GATTType}; use bluetooth_traits::{BluetoothResponse, BluetoothResponseListener, BluetoothResponseResult}; use bluetooth_traits::blocklist::{Blocklist, uuid_is_blocklisted}; use bluetooth_traits::scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence}; @@ -13,14 +13,14 @@ use dom::bindings::codegen::Bindings::BluetoothBinding::{self, BluetoothDataFilt use dom::bindings::codegen::Bindings::BluetoothBinding::{BluetoothMethods, RequestDeviceOptions}; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::UnionTypes::StringOrUnsignedLong; -use dom::bindings::error::Error::{self, NotFound, Security, Type}; +use dom::bindings::error::Error::{self, Network, NotFound, Security, Type}; use dom::bindings::error::Fallible; use dom::bindings::js::{MutJS, Root}; use dom::bindings::refcounted::{Trusted, TrustedPromise}; use dom::bindings::reflector::{DomObject, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::bluetoothdevice::BluetoothDevice; -use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID}; +use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID, UUID}; use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; use dom::promise::Promise; @@ -193,6 +193,57 @@ pub fn response_async( action_sender } +#[allow(unrooted_must_root)] +// https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren +pub fn get_gatt_children ( + attribute: &T, + single: bool, + uuid_canonicalizer: F, + uuid: Option, + instance_id: String, + connected: bool, + child_type: GATTType) + -> Rc + where T: AsyncBluetoothListener + DomObject + 'static, + F: FnOnce(StringOrUnsignedLong) -> Fallible { + let p = Promise::new(&attribute.global()); + let p_cx = p.global().get_cx(); + + let result_uuid = if let Some(u) = uuid { + // Step 1. + let canonicalized = match uuid_canonicalizer(u) { + Ok(canonicalized_uuid) => canonicalized_uuid.to_string(), + Err(e) => { + p.reject_error(p_cx, e); + return p; + } + }; + // Step 2. + if uuid_is_blocklisted(canonicalized.as_ref(), Blocklist::All) { + p.reject_error(p_cx, Security); + return p; + } + Some(canonicalized) + } else { + None + }; + + // Step 3 - 4. + if !connected { + p.reject_error(p_cx, Network); + return p; + } + + // TODO: Step 5: Implement representedDevice internal slot for BluetoothDevice. + + // Note: Steps 6 - 7 are implemented in components/bluetooth/lib.rs in get_descriptor function + // and in handle_response function. + let sender = response_async(&p, attribute); + attribute.global().as_window().bluetooth_thread().send( + BluetoothRequest::GetGATTChildren(instance_id, result_uuid, single, child_type, sender)).unwrap(); + return p; +} + // https://webbluetoothcg.github.io/web-bluetooth/#bluetoothlescanfilterinit-canonicalizing fn canonicalize_filter(filter: &BluetoothLEScanFilterInit) -> Fallible { // Step 1. diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs index a1de986b7147..b4b9941343bd 100644 --- a/components/script/dom/bluetoothremotegattcharacteristic.rs +++ b/components/script/dom/bluetoothremotegattcharacteristic.rs @@ -2,7 +2,7 @@ * 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::{BluetoothRequest, BluetoothResponse}; +use bluetooth_traits::{BluetoothRequest, BluetoothResponse, GATTType}; use bluetooth_traits::blocklist::{Blocklist, uuid_is_blocklisted}; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::BluetoothCharacteristicPropertiesBinding:: @@ -19,7 +19,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::js::{MutJS, Root}; use dom::bindings::reflector::{DomObject, reflect_dom_object}; use dom::bindings::str::{ByteString, DOMString}; -use dom::bluetooth::{AsyncBluetoothListener, response_async}; +use dom::bluetooth::{AsyncBluetoothListener, get_gatt_children, response_async}; use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties; use dom::bluetoothremotegattservice::BluetoothRemoteGATTService; use dom::bluetoothuuid::{BluetoothDescriptorUUID, BluetoothUUID}; @@ -102,79 +102,18 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren fn GetDescriptor(&self, descriptor: BluetoothDescriptorUUID) -> Rc { - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - - // Step 1. - let uuid = match BluetoothUUID::descriptor(descriptor) { - Ok(uuid) => uuid.to_string(), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - - // Step 3 - 4. - if !self.Service().Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } - - // Note: Steps 5 - 7 are implemented in components/bluetooth/lib.rs in get_descriptor function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetDescriptor(self.get_instance_id(), uuid, sender)).unwrap(); - return p; + get_gatt_children(self, true, BluetoothUUID::descriptor, Some(descriptor), self.get_instance_id(), + self.Service().Device().Gatt().Connected(), GATTType::Descriptor) } #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren fn GetDescriptors(&self, descriptor: Option) -> Rc { - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - let mut uuid: Option = None; - if let Some(d) = descriptor { - // Step 1. - uuid = match BluetoothUUID::descriptor(d) { - Ok(uuid) => Some(uuid.to_string()), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - if let Some(ref uuid) = uuid { - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - } - }; - - // Step 3 - 4. - if !self.Service().Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } - - // Note: Steps 5 - 7 are implemented in components/bluetooth/lib.rs in get_descriptors function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetDescriptors(self.get_instance_id(), uuid, sender)).unwrap(); - return p; + get_gatt_children(self, false, BluetoothUUID::descriptor, descriptor, self.get_instance_id(), + self.Service().Device().Gatt().Connected(), GATTType::Descriptor) } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-value @@ -320,17 +259,13 @@ 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 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 - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - // Step 7. - BluetoothResponse::GetDescriptors(descriptors_vec) => { + BluetoothResponse::GetDescriptors(descriptors_vec, single) => { + if single { + promise.resolve_native(promise_cx, &device.get_or_create_descriptor(&descriptors_vec[0], &self)); + return; + } let mut descriptors = vec!(); for descriptor in descriptors_vec { let bt_descriptor = device.get_or_create_descriptor(&descriptor, &self); diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs index 307c3b87f660..ad7833af908f 100644 --- a/components/script/dom/bluetoothremotegattserver.rs +++ b/components/script/dom/bluetoothremotegattserver.rs @@ -2,16 +2,15 @@ * 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::{BluetoothRequest, BluetoothResponse}; -use bluetooth_traits::blocklist::{Blocklist, uuid_is_blocklisted}; +use bluetooth_traits::{BluetoothRequest, BluetoothResponse, GATTType}; use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; -use dom::bindings::error::Error::{self, Network, Security}; +use dom::bindings::error::Error; use dom::bindings::error::ErrorResult; use dom::bindings::js::{MutJS, Root}; use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; -use dom::bluetooth::{AsyncBluetoothListener, response_async}; +use dom::bluetooth::{AsyncBluetoothListener, get_gatt_children, response_async}; use dom::bluetoothdevice::BluetoothDevice; use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID}; use dom::globalscope::GlobalScope; @@ -114,84 +113,24 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice fn GetPrimaryService(&self, service: BluetoothServiceUUID) -> Rc { // TODO: Step 1: Implement the Permission API and the allowedServices BluetoothDevice internal slot. - // Subsequent steps are relative to https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - - // Step 1. - let uuid = match BluetoothUUID::service(service) { - Ok(uuid) => uuid.to_string(), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - - // Step 3 - 4. - if !self.Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } - - // Note: Steps 5 - 7 are implemented in components/bluetooth/lib.rs in get_primary_service function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetPrimaryService(String::from(self.Device().Id()), uuid, sender)).unwrap(); - return p; + get_gatt_children(self, true, BluetoothUUID::service, Some(service), String::from(self.Device().Id()), + self.Device().Gatt().Connected(), GATTType::PrimaryService) } #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices fn GetPrimaryServices(&self, service: Option) -> Rc { // TODO: Step 1: Implement the Permission API and the allowedServices BluetoothDevice internal slot. - // Subsequent steps are relative to https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - - let mut uuid: Option = None; - if let Some(s) = service { - // Step 1. - uuid = match BluetoothUUID::service(s) { - Ok(uuid) => Some(uuid.to_string()), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - if let Some(ref uuid) = uuid { - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - } - }; - - // Step 3 - 4. - if !self.Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } + // Step 2. + get_gatt_children(self, false, BluetoothUUID::service, service, String::from(self.Device().Id()), + self.Connected(), GATTType::PrimaryService) - // Note: Steps 5 - 7 are implemented in components/bluetooth/lib.rs in get_primary_services function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetPrimaryServices(String::from(self.Device().Id()), uuid, sender)).unwrap(); - return p; } } 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) => { @@ -201,17 +140,14 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTServer { // Step 5.2.5. promise.resolve_native(promise_cx, self); }, - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - // Step 7. - BluetoothResponse::GetPrimaryService(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 // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren // Step 7. - BluetoothResponse::GetPrimaryServices(services_vec) => { + BluetoothResponse::GetPrimaryServices(services_vec, single) => { + let device = self.Device(); + if single { + promise.resolve_native(promise_cx, &device.get_or_create_service(&services_vec[0], &self)); + return; + } let mut services = vec!(); for service in services_vec { let bt_service = device.get_or_create_service(&service, &self); diff --git a/components/script/dom/bluetoothremotegattservice.rs b/components/script/dom/bluetoothremotegattservice.rs index 83f1a7f30401..304cbb7d5b9f 100644 --- a/components/script/dom/bluetoothremotegattservice.rs +++ b/components/script/dom/bluetoothremotegattservice.rs @@ -2,24 +2,22 @@ * 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::{BluetoothRequest, BluetoothResponse}; -use bluetooth_traits::blocklist::{Blocklist, uuid_is_blocklisted}; +use bluetooth_traits::{BluetoothResponse, GATTType}; use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; -use dom::bindings::error::Error::{self, Network, Security}; +use dom::bindings::error::Error; use dom::bindings::js::{MutJS, Root}; -use dom::bindings::reflector::{DomObject, reflect_dom_object}; +use dom::bindings::reflector::reflect_dom_object; use dom::bindings::str::DOMString; -use dom::bluetooth::{AsyncBluetoothListener, response_async}; +use dom::bluetooth::{AsyncBluetoothListener, get_gatt_children}; use dom::bluetoothdevice::BluetoothDevice; use dom::bluetoothuuid::{BluetoothCharacteristicUUID, BluetoothServiceUUID, BluetoothUUID}; use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; use dom::promise::Promise; -use ipc_channel::ipc::IpcSender; use js::jsapi::JSContext; use std::rc::Rc; @@ -62,10 +60,6 @@ impl BluetoothRemoteGATTService { BluetoothRemoteGATTServiceBinding::Wrap) } - fn get_bluetooth_thread(&self) -> IpcSender { - self.global().as_window().bluetooth_thread() - } - fn get_instance_id(&self) -> String { self.instance_id.clone() } @@ -89,165 +83,39 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren fn GetCharacteristic(&self, characteristic: BluetoothCharacteristicUUID) -> Rc { - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - - // Step 1. - let uuid = match BluetoothUUID::characteristic(characteristic) { - Ok(uuid) => uuid.to_string(), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - - // Step 3 - 4. - if !self.Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } - - // Note: Steps 5 - 7 are implemented is components/bluetooth/lib.rs in get_characteristic function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetCharacteristic(self.get_instance_id(), uuid, sender)).unwrap(); - return p; + get_gatt_children(self, true, BluetoothUUID::characteristic, Some(characteristic), self.get_instance_id(), + self.Device().Gatt().Connected(), GATTType::Characteristic) } #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren fn GetCharacteristics(&self, characteristic: Option) -> Rc { - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - let mut uuid: Option = None; - if let Some(c) = characteristic { - // Step 1. - uuid = match BluetoothUUID::characteristic(c) { - Ok(uuid) => Some(uuid.to_string()), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - if let Some(ref uuid) = uuid { - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - } - }; - - // Step 3 - 4. - if !self.Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } - - // Note: Steps 5 - 7 are implemented is components/bluetooth/lib.rs in get_characteristics function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetCharacteristics(self.get_instance_id(), uuid, sender)).unwrap(); - return p; + get_gatt_children(self, false, BluetoothUUID::characteristic, characteristic, self.get_instance_id(), + self.Device().Gatt().Connected(), GATTType::Characteristic) } #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservice - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren fn GetIncludedService(&self, service: BluetoothServiceUUID) -> Rc { - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - - // Step 1. - let uuid = match BluetoothUUID::service(service) { - Ok(uuid) => uuid.to_string(), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - - // Step 3 - 4. - if !self.Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } - - // Note: Steps 5 - 7 are implemented is components/bluetooth/lib.rs in get_included_service function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetIncludedService(self.get_instance_id(), - uuid, - sender)).unwrap(); - return p; + get_gatt_children(self, false, BluetoothUUID::service, Some(service), self.get_instance_id(), + self.Device().Gatt().Connected(), GATTType::IncludedService) } #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren fn GetIncludedServices(&self, service: Option) -> Rc { - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - let mut uuid: Option = None; - if let Some(s) = service { - // Step 1. - uuid = match BluetoothUUID::service(s) { - Ok(uuid) => Some(uuid.to_string()), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - if let Some(ref uuid) = uuid { - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - } - }; - - // Step 3 - 4. - if !self.Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } - - // Note: Steps 5 - 7 are implemented is components/bluetooth/lib.rs in get_included_services function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetIncludedServices(self.get_instance_id(), - uuid, - sender)).unwrap(); - return p; + get_gatt_children(self, false, BluetoothUUID::service, service, self.get_instance_id(), + self.Device().Gatt().Connected(), GATTType::IncludedService) } // https://webbluetoothcg.github.io/web-bluetooth/#dom-serviceeventhandlers-onserviceadded @@ -264,17 +132,14 @@ 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 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 // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren // Step 7. - BluetoothResponse::GetCharacteristics(characteristics_vec) => { + BluetoothResponse::GetCharacteristics(characteristics_vec, single) => { + if single { + promise.resolve_native(promise_cx, + &device.get_or_create_characteristic(&characteristics_vec[0], &self)); + return; + } let mut characteristics = vec!(); for characteristic in characteristics_vec { let bt_characteristic = device.get_or_create_characteristic(&characteristic, &self); @@ -282,31 +147,19 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTService { } promise.resolve_native(promise_cx, &characteristics); }, - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservice - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - // Step 7. - BluetoothResponse::GetIncludedService(service) => { - let s = - BluetoothRemoteGATTService::new(&self.global(), - &self.device.get(), - DOMString::from(service.uuid), - service.is_primary, - service.instance_id); - promise.resolve_native(promise_cx, &s); - }, - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren // Step 7. - BluetoothResponse::GetIncludedServices(services_vec) => { - let s: Vec> = - services_vec.into_iter() - .map(|service| BluetoothRemoteGATTService::new(&self.global(), - &self.device.get(), - DOMString::from(service.uuid), - service.is_primary, - service.instance_id)) - .collect(); - promise.resolve_native(promise_cx, &s); + BluetoothResponse::GetIncludedServices(services_vec, single) => { + if single { + promise.resolve_native(promise_cx, &device.get_or_create_service(&services_vec[0], &device.Gatt())); + return; + } + let mut services = vec!(); + for service in services_vec { + let bt_service = device.get_or_create_service(&service, &device.Gatt()); + services.push(bt_service); + } + promise.resolve_native(promise_cx, &services); }, _ => promise.reject_error(promise_cx, Error::Type("Something went wrong...".to_owned())), }