aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/bluetooth.rs173
-rw-r--r--components/script/dom/bluetoothremotegattcharacteristic.rs283
-rw-r--r--components/script/dom/bluetoothremotegattdescriptor.rs109
-rw-r--r--components/script/dom/bluetoothremotegattserver.rs194
-rw-r--r--components/script/dom/bluetoothremotegattservice.rs377
-rw-r--r--components/script/dom/testrunner.rs6
-rw-r--r--components/script/dom/window.rs8
7 files changed, 586 insertions, 564 deletions
diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs
index 7080a38668b..1f5fd15c49f 100644
--- a/components/script/dom/bluetooth.rs
+++ b/components/script/dom/bluetooth.rs
@@ -2,7 +2,8 @@
* 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, BluetoothMethodMsg};
+use bluetooth_traits::{BluetoothError, BluetoothRequest};
+use bluetooth_traits::{BluetoothResponse, BluetoothResponseListener, BluetoothResponseResult};
use bluetooth_traits::blacklist::{Blacklist, uuid_is_blacklisted};
use bluetooth_traits::scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence};
use bluetooth_traits::scanfilter::{RequestDeviceoptions, ServiceUUIDSequence};
@@ -13,6 +14,7 @@ use dom::bindings::codegen::Bindings::BluetoothBinding::RequestDeviceOptions;
use dom::bindings::error::Error::{self, NotFound, Security, Type};
use dom::bindings::error::Fallible;
use dom::bindings::js::{JS, MutHeap, Root};
+use dom::bindings::refcounted::{Trusted, TrustedPromise};
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
use dom::bluetoothadvertisingdata::BluetoothAdvertisingData;
@@ -24,9 +26,12 @@ use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID};
use dom::globalscope::GlobalScope;
use dom::promise::Promise;
use ipc_channel::ipc::{self, IpcSender};
-use js::conversions::ToJSValConvertible;
+use ipc_channel::router::ROUTER;
+use js::jsapi::{JSAutoCompartment, JSContext};
+use network_listener::{NetworkListener, PreInvoke};
use std::collections::HashMap;
use std::rc::Rc;
+use std::sync::{Arc, Mutex};
const FILTER_EMPTY_ERROR: &'static str = "'filters' member, if present, must be nonempty to find any devices.";
const FILTER_ERROR: &'static str = "A filter must restrict the devices in some way.";
@@ -43,6 +48,33 @@ const SERVICE_ERROR: &'static str = "'services', if present, must contain at lea
const OPTIONS_ERROR: &'static str = "Fields of 'options' conflict with each other.
Either 'acceptAllDevices' member must be true, or 'filters' member must be set to a value.";
+struct BluetoothContext<T: AsyncBluetoothListener + Reflectable> {
+ promise: Option<TrustedPromise>,
+ receiver: Trusted<T>,
+}
+
+pub trait AsyncBluetoothListener {
+ fn handle_response(&self, result: BluetoothResponse, cx: *mut JSContext, promise: &Rc<Promise>);
+}
+
+impl<Listener: AsyncBluetoothListener + Reflectable> PreInvoke for BluetoothContext<Listener> {}
+
+impl<Listener: AsyncBluetoothListener + Reflectable> BluetoothResponseListener for BluetoothContext<Listener> {
+ #[allow(unrooted_must_root)]
+ fn response(&mut self, response: BluetoothResponseResult) {
+ let promise = self.promise.take().expect("bt promise is missing").root();
+ let promise_cx = promise.global().get_cx();
+
+ // JSAutoCompartment needs to be manually made.
+ // Otherwise, Servo will crash.
+ let _ac = JSAutoCompartment::new(promise_cx, promise.reflector().get_jsobject().get());
+ match response {
+ Ok(response) => self.receiver.root().handle_response(response, promise_cx, &promise),
+ Err(error) => promise.reject_error(promise_cx, Error::from(error)),
+ }
+ }
+}
+
// https://webbluetoothcg.github.io/web-bluetooth/#bluetooth
#[dom_struct]
pub struct Bluetooth {
@@ -83,75 +115,55 @@ impl Bluetooth {
&self.descriptor_instance_map
}
- fn get_bluetooth_thread(&self) -> IpcSender<BluetoothMethodMsg> {
+ fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
self.global().as_window().bluetooth_thread()
}
- fn request_device(&self, option: &RequestDeviceOptions) -> Fallible<Root<BluetoothDevice>> {
- // Step 1.
- // TODO(#4282): Reject promise.
- if (option.filters.is_some() && option.acceptAllDevices) ||
- (option.filters.is_none() && !option.acceptAllDevices) {
- return Err(Type(OPTIONS_ERROR.to_owned()));
- }
- // Step 2.
- if !option.acceptAllDevices {
- return self.request_bluetooth_devices(&option.filters, &option.optionalServices);
- }
-
- self.request_bluetooth_devices(&None, &option.optionalServices)
- // TODO(#4282): Step 3-5: Reject and resolve promise.
- }
-
// https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices
fn request_bluetooth_devices(&self,
+ p: &Rc<Promise>,
filters: &Option<Vec<BluetoothRequestDeviceFilter>>,
- optional_services: &Option<Vec<BluetoothServiceUUID>>)
- -> Fallible<Root<BluetoothDevice>> {
+ optional_services: &Option<Vec<BluetoothServiceUUID>>) {
// TODO: Step 1: Triggered by user activation.
// Step 2.
- let option = try!(convert_request_device_options(filters, optional_services));
+ let option = match convert_request_device_options(filters, optional_services) {
+ Ok(o) => o,
+ Err(e) => {
+ p.reject_error(p.global().get_cx(), e);
+ return;
+ }
+ };
// TODO: Step 3-5: Implement the permission API.
// Note: Steps 6-8 are implemented in
// components/net/bluetooth_thread.rs in request_device function.
- let (sender, receiver) = ipc::channel().unwrap();
- self.get_bluetooth_thread().send(BluetoothMethodMsg::RequestDevice(option, sender)).unwrap();
- let device = receiver.recv().unwrap();
-
- // TODO: Step 9-10: Implement the permission API.
-
- // Step 11: This step is optional.
-
- // Step 12-13.
- match device {
- Ok(device) => {
- let mut device_instance_map = self.device_instance_map.borrow_mut();
- if let Some(existing_device) = device_instance_map.get(&device.id.clone()) {
- return Ok(existing_device.get());
- }
- let ad_data = BluetoothAdvertisingData::new(&self.global(),
- device.appearance,
- device.tx_power,
- device.rssi);
- let bt_device = BluetoothDevice::new(&self.global(),
- DOMString::from(device.id.clone()),
- device.name.map(DOMString::from),
- &ad_data,
- &self);
- device_instance_map.insert(device.id, MutHeap::new(&bt_device));
- Ok(bt_device)
- },
- Err(error) => {
- Err(Error::from(error))
- },
- }
-
+ let sender = response_async(p, self);
+ self.get_bluetooth_thread().send(BluetoothRequest::RequestDevice(option, sender)).unwrap();
}
}
+pub fn response_async<T: AsyncBluetoothListener + Reflectable + 'static>(
+ promise: &Rc<Promise>,
+ receiver: &T) -> IpcSender<BluetoothResponseResult> {
+ let (action_sender, action_receiver) = ipc::channel().unwrap();
+ let chan = receiver.global().networking_task_source();
+ let context = Arc::new(Mutex::new(BluetoothContext {
+ promise: Some(TrustedPromise::new(promise.clone())),
+ receiver: Trusted::new(receiver),
+ }));
+ let listener = NetworkListener {
+ context: context,
+ script_chan: chan,
+ wrapper: None,
+ };
+ ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
+ listener.notify_response(message.to().unwrap());
+ });
+ action_sender
+}
+
// https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices
fn convert_request_device_options(filters: &Option<Vec<BluetoothRequestDeviceFilter>>,
optional_services: &Option<Vec<BluetoothServiceUUID>>)
@@ -300,18 +312,6 @@ fn canonicalize_filter(filter: &BluetoothRequestDeviceFilter) -> Fallible<Blueto
service_data_uuid))
}
-#[allow(unrooted_must_root)]
-pub fn result_to_promise<T: ToJSValConvertible>(global: &GlobalScope,
- bluetooth_result: Fallible<T>)
- -> Rc<Promise> {
- let p = Promise::new(global);
- match bluetooth_result {
- Ok(v) => p.resolve_native(p.global().get_cx(), &v),
- Err(e) => p.reject_error(p.global().get_cx(), e),
- }
- p
-}
-
impl From<BluetoothError> for Error {
fn from(error: BluetoothError) -> Self {
match error {
@@ -329,6 +329,45 @@ impl BluetoothMethods for Bluetooth {
#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice
fn RequestDevice(&self, option: &RequestDeviceOptions) -> Rc<Promise> {
- result_to_promise(&self.global(), self.request_device(option))
+ let p = Promise::new(&self.global());
+ // Step 1.
+ if (option.filters.is_some() && option.acceptAllDevices) ||
+ (option.filters.is_none() && !option.acceptAllDevices) {
+ p.reject_error(p.global().get_cx(), Error::Type(OPTIONS_ERROR.to_owned()));
+ return p;
+ }
+ // Step 2.
+ if !option.acceptAllDevices {
+ self.request_bluetooth_devices(&p, &option.filters, &option.optionalServices);
+ } else {
+ self.request_bluetooth_devices(&p, &None, &option.optionalServices);
+ }
+ // TODO(#4282): Step 3-5: Reject and resolve promise.
+ return p;
+ }
+}
+
+impl AsyncBluetoothListener for Bluetooth {
+ fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc<Promise>) {
+ match response {
+ BluetoothResponse::RequestDevice(device) => {
+ let mut device_instance_map = self.device_instance_map.borrow_mut();
+ if let Some(existing_device) = device_instance_map.get(&device.id.clone()) {
+ return promise.resolve_native(promise_cx, &existing_device.get());
+ }
+ let ad_data = BluetoothAdvertisingData::new(&self.global(),
+ device.appearance,
+ device.tx_power,
+ device.rssi);
+ let bt_device = BluetoothDevice::new(&self.global(),
+ DOMString::from(device.id.clone()),
+ device.name.map(DOMString::from),
+ &ad_data,
+ &self);
+ device_instance_map.insert(device.id, MutHeap::new(&bt_device));
+ promise.resolve_native(promise_cx, &bt_device);
+ },
+ _ => promise.reject_error(promise_cx, Error::Type("Something went wrong...".to_owned())),
+ }
}
}
diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs
index 1b2a16c1a4b..d5ff56853ce 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::BluetoothMethodMsg;
+use bluetooth_traits::{BluetoothRequest, BluetoothResponse};
use bluetooth_traits::blacklist::{Blacklist, uuid_is_blacklisted};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::BluetoothCharacteristicPropertiesBinding::
@@ -13,19 +13,19 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding::
BluetoothRemoteGATTCharacteristicMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
-use dom::bindings::error::{ErrorResult, Fallible};
use dom::bindings::error::Error::{self, InvalidModification, Network, NotSupported, Security};
use dom::bindings::js::{JS, MutHeap, Root};
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::str::{ByteString, DOMString};
-use dom::bluetooth::result_to_promise;
+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::globalscope::GlobalScope;
use dom::promise::Promise;
-use ipc_channel::ipc::{self, IpcSender};
+use ipc_channel::ipc::IpcSender;
+use js::jsapi::JSContext;
use std::rc::Rc;
// Maximum length of an attribute value.
@@ -73,196 +73,197 @@ impl BluetoothRemoteGATTCharacteristic {
BluetoothRemoteGATTCharacteristicBinding::Wrap)
}
- fn get_bluetooth_thread(&self) -> IpcSender<BluetoothMethodMsg> {
+ fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
self.global().as_window().bluetooth_thread()
}
fn get_instance_id(&self) -> String {
self.instance_id.clone()
}
+}
+
+impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteristic {
+ // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-properties
+ fn Properties(&self) -> Root<BluetoothCharacteristicProperties> {
+ self.properties.get()
+ }
+
+ // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-service
+ fn Service(&self) -> Root<BluetoothRemoteGATTService> {
+ self.service.get()
+ }
+ // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-uuid
+ fn Uuid(&self) -> DOMString {
+ self.uuid.clone()
+ }
+
+ #[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor
- fn get_descriptor(&self, descriptor: BluetoothDescriptorUUID) -> Fallible<Root<BluetoothRemoteGATTDescriptor>> {
- let uuid = try!(BluetoothUUID::descriptor(descriptor)).to_string();
+ fn GetDescriptor(&self, descriptor: BluetoothDescriptorUUID) -> Rc<Promise> {
+ let p = Promise::new(&self.global());
+ let p_cx = p.global().get_cx();
+ let uuid = match BluetoothUUID::descriptor(descriptor) {
+ Ok(uuid) => uuid.to_string(),
+ Err(e) => {
+ p.reject_error(p_cx, e);
+ return p;
+ }
+ };
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
- return Err(Security)
+ p.reject_error(p_cx, Security);
+ return p;
}
if !self.Service().Device().Gatt().Connected() {
- return Err(Network)
+ p.reject_error(p_cx, Network);
+ return p;
}
- let (sender, receiver) = ipc::channel().unwrap();
+ let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
- BluetoothMethodMsg::GetDescriptor(self.get_instance_id(), uuid, sender)).unwrap();
- let descriptor = receiver.recv().unwrap();
- match descriptor {
- Ok(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 Ok(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));
- Ok(bt_descriptor)
- },
- Err(error) => {
- Err(Error::from(error))
- },
- }
+ BluetoothRequest::GetDescriptor(self.get_instance_id(), uuid, sender)).unwrap();
+ return p;
}
+ #[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors
- fn get_descriptors(&self,
- descriptor: Option<BluetoothDescriptorUUID>)
- -> Fallible<Vec<Root<BluetoothRemoteGATTDescriptor>>> {
+ fn GetDescriptors(&self,
+ descriptor: Option<BluetoothDescriptorUUID>)
+ -> Rc<Promise> {
+ let p = Promise::new(&self.global());
+ let p_cx = p.global().get_cx();
let mut uuid: Option<String> = None;
if let Some(d) = descriptor {
- uuid = Some(try!(BluetoothUUID::descriptor(d)).to_string());
+ 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 {
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
- return Err(Security)
+ p.reject_error(p_cx, Security);
+ return p;
}
}
};
if !self.Service().Device().Gatt().Connected() {
- return Err(Network)
+ p.reject_error(p_cx, Network);
+ return p;
}
- let mut descriptors = vec!();
- let (sender, receiver) = ipc::channel().unwrap();
+ let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
- BluetoothMethodMsg::GetDescriptors(self.get_instance_id(), uuid, sender)).unwrap();
- let descriptors_vec = receiver.recv().unwrap();
- match descriptors_vec {
- Ok(descriptor_vec) => {
- let context = self.service.get().get_device().get_context();
- let mut descriptor_map = context.get_descriptor_map().borrow_mut();
- for descriptor in descriptor_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));
- }
- descriptors.push(bt_descriptor);
- }
- Ok(descriptors)
- },
- Err(error) => {
- Err(Error::from(error))
- },
- }
+ BluetoothRequest::GetDescriptors(self.get_instance_id(), uuid, sender)).unwrap();
+ return p;
}
+ // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-value
+ fn GetValue(&self) -> Option<ByteString> {
+ self.value.borrow().clone()
+ }
+
+ #[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue
- fn read_value(&self) -> Fallible<ByteString> {
+ fn ReadValue(&self) -> Rc<Promise> {
+ let p = Promise::new(&self.global());
+ let p_cx = p.global().get_cx();
if uuid_is_blacklisted(self.uuid.as_ref(), Blacklist::Reads) {
- return Err(Security)
+ p.reject_error(p_cx, Security);
+ return p;
}
- let (sender, receiver) = ipc::channel().unwrap();
if !self.Service().Device().Gatt().Connected() {
- return Err(Network)
+ p.reject_error(p_cx, Network);
+ return p;
}
if !self.Properties().Read() {
- return Err(NotSupported)
+ p.reject_error(p_cx, NotSupported);
+ return p;
}
+ let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
- BluetoothMethodMsg::ReadValue(self.get_instance_id(), sender)).unwrap();
- let result = receiver.recv().unwrap();
- let value = match result {
- Ok(val) => {
- ByteString::new(val)
- },
- Err(error) => {
- return Err(Error::from(error))
- },
- };
- *self.value.borrow_mut() = Some(value.clone());
- Ok(value)
+ BluetoothRequest::ReadValue(self.get_instance_id(), sender)).unwrap();
+ return p;
}
+ #[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue
- fn write_value(&self, value: Vec<u8>) -> ErrorResult {
+ fn WriteValue(&self, value: Vec<u8>) -> Rc<Promise> {
+ let p = Promise::new(&self.global());
+ let p_cx = p.global().get_cx();
if uuid_is_blacklisted(self.uuid.as_ref(), Blacklist::Writes) {
- return Err(Security)
+ p.reject_error(p_cx, Security);
+ return p;
}
if value.len() > MAXIMUM_ATTRIBUTE_LENGTH {
- return Err(InvalidModification)
+ p.reject_error(p_cx, InvalidModification);
+ return p;
}
if !self.Service().Device().Gatt().Connected() {
- return Err(Network)
+ p.reject_error(p_cx, Network);
+ return p;
}
if !(self.Properties().Write() ||
self.Properties().WriteWithoutResponse() ||
self.Properties().AuthenticatedSignedWrites()) {
- return Err(NotSupported)
+ p.reject_error(p_cx, NotSupported);
+ return p;
}
- let (sender, receiver) = ipc::channel().unwrap();
+ let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
- BluetoothMethodMsg::WriteValue(self.get_instance_id(), value.clone(), sender)).unwrap();
- let result = receiver.recv().unwrap();
- match result {
- Ok(_) => Ok(*self.value.borrow_mut() = Some(ByteString::new(value))),
- Err(error) => {
- Err(Error::from(error))
- },
- }
+ BluetoothRequest::WriteValue(self.get_instance_id(), value, sender)).unwrap();
+ return p;
}
}
-impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteristic {
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-properties
- fn Properties(&self) -> Root<BluetoothCharacteristicProperties> {
- self.properties.get()
- }
-
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-service
- fn Service(&self) -> Root<BluetoothRemoteGATTService> {
- self.service.get()
- }
-
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-uuid
- fn Uuid(&self) -> DOMString {
- self.uuid.clone()
- }
-
- #[allow(unrooted_must_root)]
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor
- fn GetDescriptor(&self, descriptor: BluetoothDescriptorUUID) -> Rc<Promise> {
- result_to_promise(&self.global(), self.get_descriptor(descriptor))
- }
-
- #[allow(unrooted_must_root)]
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors
- fn GetDescriptors(&self,
- descriptor: Option<BluetoothDescriptorUUID>)
- -> Rc<Promise> {
- result_to_promise(&self.global(), self.get_descriptors(descriptor))
- }
-
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-value
- fn GetValue(&self) -> Option<ByteString> {
- self.value.borrow().clone()
- }
-
- #[allow(unrooted_must_root)]
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue
- fn ReadValue(&self) -> Rc<Promise> {
- result_to_promise(&self.global(), self.read_value())
- }
-
- #[allow(unrooted_must_root)]
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue
- fn WriteValue(&self, value: Vec<u8>) -> Rc<Promise> {
- result_to_promise(&self.global(), self.write_value(value))
+impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic {
+ fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc<Promise>) {
+ match response {
+ 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));
+ promise.resolve_native(promise_cx, &bt_descriptor);
+ },
+ 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));
+ }
+ descriptors.push(bt_descriptor);
+ }
+ promise.resolve_native(promise_cx, &descriptors);
+ },
+ BluetoothResponse::ReadValue(result) => {
+ let value = ByteString::new(result);
+ *self.value.borrow_mut() = Some(value.clone());
+ promise.resolve_native(promise_cx, &value);
+ },
+ BluetoothResponse::WriteValue(result) => {
+ let value = ByteString::new(result);
+ *self.value.borrow_mut() = Some(value.clone());
+ promise.resolve_native(promise_cx, &value);
+ },
+ _ => promise.reject_error(promise_cx, Error::Type("Something went wrong...".to_owned())),
+ }
}
}
diff --git a/components/script/dom/bluetoothremotegattdescriptor.rs b/components/script/dom/bluetoothremotegattdescriptor.rs
index 30886baf473..4305b98c3a7 100644
--- a/components/script/dom/bluetoothremotegattdescriptor.rs
+++ b/components/script/dom/bluetoothremotegattdescriptor.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::BluetoothMethodMsg;
+use bluetooth_traits::{BluetoothRequest, BluetoothResponse};
use bluetooth_traits::blacklist::{Blacklist, uuid_is_blacklisted};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
@@ -12,16 +12,16 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTDescriptorBinding;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTDescriptorBinding::BluetoothRemoteGATTDescriptorMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
-use dom::bindings::error::{ErrorResult, Fallible};
use dom::bindings::error::Error::{self, InvalidModification, Network, Security};
use dom::bindings::js::{JS, MutHeap, Root};
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::str::{ByteString, DOMString};
-use dom::bluetooth::result_to_promise;
+use dom::bluetooth::{AsyncBluetoothListener, response_async};
use dom::bluetoothremotegattcharacteristic::{BluetoothRemoteGATTCharacteristic, MAXIMUM_ATTRIBUTE_LENGTH};
use dom::globalscope::GlobalScope;
use dom::promise::Promise;
-use ipc_channel::ipc::{self, IpcSender};
+use ipc_channel::ipc::IpcSender;
+use js::jsapi::JSContext;
use std::rc::Rc;
// http://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattdescriptor
@@ -60,60 +60,13 @@ impl BluetoothRemoteGATTDescriptor {
BluetoothRemoteGATTDescriptorBinding::Wrap)
}
- fn get_bluetooth_thread(&self) -> IpcSender<BluetoothMethodMsg> {
+ fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
self.global().as_window().bluetooth_thread()
}
fn get_instance_id(&self) -> String {
self.instance_id.clone()
}
-
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue
- fn read_value(&self) -> Fallible<ByteString> {
- if uuid_is_blacklisted(self.uuid.as_ref(), Blacklist::Reads) {
- return Err(Security)
- }
- let (sender, receiver) = ipc::channel().unwrap();
- if !self.Characteristic().Service().Device().Gatt().Connected() {
- return Err(Network)
- }
- self.get_bluetooth_thread().send(
- BluetoothMethodMsg::ReadValue(self.get_instance_id(), sender)).unwrap();
- let result = receiver.recv().unwrap();
- let value = match result {
- Ok(val) => {
- ByteString::new(val)
- },
- Err(error) => {
- return Err(Error::from(error))
- },
- };
- *self.value.borrow_mut() = Some(value.clone());
- Ok(value)
- }
-
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue
- fn write_value(&self, value: Vec<u8>) -> ErrorResult {
- if uuid_is_blacklisted(self.uuid.as_ref(), Blacklist::Writes) {
- return Err(Security)
- }
- if value.len() > MAXIMUM_ATTRIBUTE_LENGTH {
- return Err(InvalidModification)
- }
- if !self.Characteristic().Service().Device().Gatt().Connected() {
- return Err(Network)
- }
- let (sender, receiver) = ipc::channel().unwrap();
- self.get_bluetooth_thread().send(
- BluetoothMethodMsg::WriteValue(self.get_instance_id(), value.clone(), sender)).unwrap();
- let result = receiver.recv().unwrap();
- match result {
- Ok(_) => Ok(*self.value.borrow_mut() = Some(ByteString::new(value))),
- Err(error) => {
- Err(Error::from(error))
- },
- }
- }
}
impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
@@ -135,12 +88,60 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue
fn ReadValue(&self) -> Rc<Promise> {
- result_to_promise(&self.global(), self.read_value())
+ let p = Promise::new(&self.global());
+ let p_cx = p.global().get_cx();
+ if uuid_is_blacklisted(self.uuid.as_ref(), Blacklist::Reads) {
+ p.reject_error(p_cx, Security);
+ return p;
+ }
+ if !self.Characteristic().Service().Device().Gatt().Connected() {
+ p.reject_error(p_cx, Network);
+ return p;
+ }
+ let sender = response_async(&p, self);
+ self.get_bluetooth_thread().send(
+ BluetoothRequest::ReadValue(self.get_instance_id(), sender)).unwrap();
+ return p;
}
#[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue
fn WriteValue(&self, value: Vec<u8>) -> Rc<Promise> {
- result_to_promise(&self.global(), self.write_value(value))
+ let p = Promise::new(&self.global());
+ let p_cx = p.global().get_cx();
+ if uuid_is_blacklisted(self.uuid.as_ref(), Blacklist::Writes) {
+ p.reject_error(p_cx, Security);
+ return p;
+ }
+ if value.len() > MAXIMUM_ATTRIBUTE_LENGTH {
+ p.reject_error(p_cx, InvalidModification);
+ return p;
+ }
+ if !self.Characteristic().Service().Device().Gatt().Connected() {
+ p.reject_error(p_cx, Network);
+ return p;
+ }
+ let sender = response_async(&p, self);
+ self.get_bluetooth_thread().send(
+ BluetoothRequest::WriteValue(self.get_instance_id(), value, sender)).unwrap();
+ return p;
+ }
+}
+
+impl AsyncBluetoothListener for BluetoothRemoteGATTDescriptor {
+ fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc<Promise>) {
+ match response {
+ BluetoothResponse::ReadValue(result) => {
+ let value = ByteString::new(result);
+ *self.value.borrow_mut() = Some(value.clone());
+ promise.resolve_native(promise_cx, &value);
+ },
+ BluetoothResponse::WriteValue(result) => {
+ let value = ByteString::new(result);
+ *self.value.borrow_mut() = Some(value.clone());
+ promise.resolve_native(promise_cx, &value);
+ },
+ _ => promise.reject_error(promise_cx, Error::Type("Something went wrong...".to_owned())),
+ }
}
}
diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs
index 9ac1ca4c4f4..327062d063e 100644
--- a/components/script/dom/bluetoothremotegattserver.rs
+++ b/components/script/dom/bluetoothremotegattserver.rs
@@ -2,23 +2,24 @@
* 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::BluetoothMethodMsg;
+use bluetooth_traits::{BluetoothRequest, BluetoothResponse};
use bluetooth_traits::blacklist::{Blacklist, uuid_is_blacklisted};
use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding;
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
-use dom::bindings::error::{ErrorResult, Fallible};
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::result_to_promise;
+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;
use ipc_channel::ipc::{self, IpcSender};
+use js::jsapi::JSContext;
use std::cell::Cell;
use std::rc::Rc;
@@ -45,20 +46,42 @@ impl BluetoothRemoteGATTServer {
BluetoothRemoteGATTServerBinding::Wrap)
}
- fn get_bluetooth_thread(&self) -> IpcSender<BluetoothMethodMsg> {
+ fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
self.global().as_window().bluetooth_thread()
}
+}
+
+impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
+ // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-device
+ fn Device(&self) -> Root<BluetoothDevice> {
+ self.device.get()
+ }
+ // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connected
+ fn Connected(&self) -> bool {
+ self.connected.get()
+ }
+
+ #[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect
- fn connect(&self) -> Fallible<Root<BluetoothRemoteGATTServer>> {
+ fn Connect(&self) -> Rc<Promise> {
+ let p = Promise::new(&self.global());
+ let sender = response_async(&p, self);
+ self.get_bluetooth_thread().send(
+ BluetoothRequest::GATTServerConnect(String::from(self.Device().Id()), sender)).unwrap();
+ return p;
+ }
+
+ // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-disconnect
+ fn Disconnect(&self) -> ErrorResult {
let (sender, receiver) = ipc::channel().unwrap();
self.get_bluetooth_thread().send(
- BluetoothMethodMsg::GATTServerConnect(String::from(self.Device().Id()), sender)).unwrap();
+ BluetoothRequest::GATTServerDisconnect(String::from(self.Device().Id()), sender)).unwrap();
let server = receiver.recv().unwrap();
match server {
Ok(connected) => {
self.connected.set(connected);
- Ok(Root::from_ref(self))
+ Ok(())
},
Err(error) => {
Err(Error::from(error))
@@ -66,66 +89,90 @@ impl BluetoothRemoteGATTServer {
}
}
+ #[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice
- fn get_primary_service(&self, service: BluetoothServiceUUID) -> Fallible<Root<BluetoothRemoteGATTService>> {
- let uuid = try!(BluetoothUUID::service(service)).to_string();
+ fn GetPrimaryService(&self, service: BluetoothServiceUUID) -> Rc<Promise> {
+ let p = Promise::new(&self.global());
+ let p_cx = p.global().get_cx();
+ let uuid = match BluetoothUUID::service(service) {
+ Ok(uuid) => uuid.to_string(),
+ Err(e) => {
+ p.reject_error(p_cx, e);
+ return p;
+ }
+ };
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
- return Err(Security)
+ p.reject_error(p_cx, Security);
+ return p;
}
if !self.Device().Gatt().Connected() {
- return Err(Network)
+ p.reject_error(p_cx, Network);
+ return p;
}
- let (sender, receiver) = ipc::channel().unwrap();
+ let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
- BluetoothMethodMsg::GetPrimaryService(String::from(self.Device().Id()), uuid, sender)).unwrap();
- let service = receiver.recv().unwrap();
- match service {
- Ok(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) {
- return Ok(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));
- Ok(bt_service)
- },
- Err(error) => {
- Err(Error::from(error))
- },
- }
+ BluetoothRequest::GetPrimaryService(String::from(self.Device().Id()), uuid, sender)).unwrap();
+ return p;
}
+ #[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices
- fn get_primary_services(&self,
- service: Option<BluetoothServiceUUID>)
- -> Fallible<Vec<Root<BluetoothRemoteGATTService>>> {
+ fn GetPrimaryServices(&self, service: Option<BluetoothServiceUUID>) -> Rc<Promise> {
+ let p = Promise::new(&self.global());
+ let p_cx = p.global().get_cx();
let mut uuid: Option<String> = None;
if let Some(s) = service {
- uuid = Some(try!(BluetoothUUID::service(s)).to_string());
+ 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 {
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
- return Err(Security)
+ p.reject_error(p_cx, Security);
+ return p;
}
}
};
if !self.Device().Gatt().Connected() {
- return Err(Network)
+ p.reject_error(p_cx, Network);
+ return p;
}
- let mut services = vec!();
- let (sender, receiver) = ipc::channel().unwrap();
+ let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
- BluetoothMethodMsg::GetPrimaryServices(String::from(self.Device().Id()), uuid, sender)).unwrap();
- let services_vec = receiver.recv().unwrap();
- match services_vec {
- Ok(service_vec) => {
+ 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<Promise>) {
+ match response {
+ BluetoothResponse::GATTServerConnect(connected) => {
+ self.connected.set(connected);
+ promise.resolve_native(promise_cx, self);
+ },
+ 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));
+ promise.resolve_native(promise_cx, &bt_service);
+ },
+ 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 service_vec {
+ for service in services_vec {
let bt_service = match service_map.get(&service.instance_id) {
Some(existing_service) => existing_service.get(),
None => {
@@ -141,60 +188,9 @@ impl BluetoothRemoteGATTServer {
}
services.push(bt_service);
}
- Ok(services)
- },
- Err(error) => {
- Err(Error::from(error))
- },
- }
- }
-}
-
-impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-device
- fn Device(&self) -> Root<BluetoothDevice> {
- self.device.get()
- }
-
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connected
- fn Connected(&self) -> bool {
- self.connected.get()
- }
-
- #[allow(unrooted_must_root)]
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect
- fn Connect(&self) -> Rc<Promise> {
- result_to_promise(&self.global(), self.connect())
- }
-
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-disconnect
- fn Disconnect(&self) -> ErrorResult {
- let (sender, receiver) = ipc::channel().unwrap();
- self.get_bluetooth_thread().send(
- BluetoothMethodMsg::GATTServerDisconnect(String::from(self.Device().Id()), sender)).unwrap();
- let server = receiver.recv().unwrap();
- match server {
- Ok(connected) => {
- self.connected.set(connected);
- Ok(())
- },
- Err(error) => {
- Err(Error::from(error))
+ promise.resolve_native(promise_cx, &services);
},
+ _ => promise.reject_error(promise_cx, Error::Type("Something went wrong...".to_owned())),
}
}
-
- #[allow(unrooted_must_root)]
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice
- fn GetPrimaryService(&self, service: BluetoothServiceUUID) -> Rc<Promise> {
- result_to_promise(&self.global(), self.get_primary_service(service))
- }
-
- #[allow(unrooted_must_root)]
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices
- fn GetPrimaryServices(&self,
- service: Option<BluetoothServiceUUID>)
- -> Rc<Promise> {
- result_to_promise(&self.global(), self.get_primary_services(service))
- }
}
diff --git a/components/script/dom/bluetoothremotegattservice.rs b/components/script/dom/bluetoothremotegattservice.rs
index c597338e1ba..d979b9959c5 100644
--- a/components/script/dom/bluetoothremotegattservice.rs
+++ b/components/script/dom/bluetoothremotegattservice.rs
@@ -2,25 +2,25 @@
* 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::BluetoothMethodMsg;
+use bluetooth_traits::{BluetoothRequest, BluetoothResponse};
use bluetooth_traits::blacklist::{Blacklist, uuid_is_blacklisted};
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::error::Error::{self, Network, Security};
-use dom::bindings::error::Fallible;
use dom::bindings::js::{JS, MutHeap, Root};
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
-use dom::bluetooth::result_to_promise;
+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::globalscope::GlobalScope;
use dom::promise::Promise;
-use ipc_channel::ipc::{self, IpcSender};
+use ipc_channel::ipc::IpcSender;
+use js::jsapi::JSContext;
use std::rc::Rc;
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattservice
@@ -66,257 +66,242 @@ impl BluetoothRemoteGATTService {
self.device.get()
}
- fn get_bluetooth_thread(&self) -> IpcSender<BluetoothMethodMsg> {
+ fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
self.global().as_window().bluetooth_thread()
}
fn get_instance_id(&self) -> String {
self.instance_id.clone()
}
+}
+
+impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
+ // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-device
+ fn Device(&self) -> Root<BluetoothDevice> {
+ self.device.get()
+ }
+
+ // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-isprimary
+ fn IsPrimary(&self) -> bool {
+ self.is_primary
+ }
+
+ // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-uuid
+ fn Uuid(&self) -> DOMString {
+ self.uuid.clone()
+ }
+ #[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic
- fn get_characteristic(&self,
- characteristic: BluetoothCharacteristicUUID)
- -> Fallible<Root<BluetoothRemoteGATTCharacteristic>> {
- let uuid = try!(BluetoothUUID::characteristic(characteristic)).to_string();
+ fn GetCharacteristic(&self,
+ characteristic: BluetoothCharacteristicUUID)
+ -> Rc<Promise> {
+ let p = Promise::new(&self.global());
+ let p_cx = p.global().get_cx();
+ let uuid = match BluetoothUUID::characteristic(characteristic) {
+ Ok(uuid) => uuid.to_string(),
+ Err(e) => {
+ p.reject_error(p_cx, e);
+ return p;
+ }
+ };
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
- return Err(Security)
+ p.reject_error(p_cx, Security);
+ return p;
}
if !self.Device().Gatt().Connected() {
- return Err(Network)
+ p.reject_error(p_cx, Network);
+ return p;
}
- let (sender, receiver) = ipc::channel().unwrap();
+ let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
- BluetoothMethodMsg::GetCharacteristic(self.get_instance_id(), uuid, sender)).unwrap();
- let characteristic = receiver.recv().unwrap();
- match characteristic {
- Ok(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 Ok(existing_characteristic.get());
- }
- let global = self.global();
- let properties = BluetoothCharacteristicProperties::new(&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(&global,
- self,
- DOMString::from(characteristic.uuid),
- &properties,
- characteristic.instance_id.clone());
- characteristic_map.insert(characteristic.instance_id, MutHeap::new(&bt_characteristic));
- Ok(bt_characteristic)
- },
- Err(error) => {
- Err(Error::from(error))
- },
- }
+ BluetoothRequest::GetCharacteristic(self.get_instance_id(), uuid, sender)).unwrap();
+ return p;
}
+ #[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics
- fn get_characteristics(&self,
- characteristic: Option<BluetoothCharacteristicUUID>)
- -> Fallible<Vec<Root<BluetoothRemoteGATTCharacteristic>>> {
+ fn GetCharacteristics(&self,
+ characteristic: Option<BluetoothCharacteristicUUID>)
+ -> Rc<Promise> {
+ let p = Promise::new(&self.global());
+ let p_cx = p.global().get_cx();
let mut uuid: Option<String> = None;
if let Some(c) = characteristic {
- uuid = Some(try!(BluetoothUUID::characteristic(c)).to_string());
+ 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 {
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
- return Err(Security)
+ p.reject_error(p_cx, Security);
+ return p;
}
}
};
if !self.Device().Gatt().Connected() {
- return Err(Network)
+ p.reject_error(p_cx, Network);
+ return p;
}
- let mut characteristics = vec!();
- let (sender, receiver) = ipc::channel().unwrap();
+ let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
- BluetoothMethodMsg::GetCharacteristics(self.get_instance_id(), uuid, sender)).unwrap();
- let characteristics_vec = receiver.recv().unwrap();
- match characteristics_vec {
- Ok(characteristic_vec) => {
- let context = self.device.get().get_context();
- let mut characteristic_map = context.get_characteristic_map().borrow_mut();
- for characteristic in characteristic_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));
- }
- characteristics.push(bt_characteristic);
- }
- Ok(characteristics)
- },
- Err(error) => {
- Err(Error::from(error))
- },
- }
+ BluetoothRequest::GetCharacteristics(self.get_instance_id(), uuid, sender)).unwrap();
+ return p;
}
+ #[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservice
- fn get_included_service(&self,
- service: BluetoothServiceUUID)
- -> Fallible<Root<BluetoothRemoteGATTService>> {
- let uuid = try!(BluetoothUUID::service(service)).to_string();
+ fn GetIncludedService(&self,
+ service: BluetoothServiceUUID)
+ -> Rc<Promise> {
+ let p = Promise::new(&self.global());
+ let p_cx = p.global().get_cx();
+ let uuid = match BluetoothUUID::service(service) {
+ Ok(uuid) => uuid.to_string(),
+ Err(e) => {
+ p.reject_error(p_cx, e);
+ return p;
+ }
+ };
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
- return Err(Security)
+ p.reject_error(p_cx, Security);
+ return p;
}
if !self.Device().Gatt().Connected() {
- return Err(Network)
+ p.reject_error(p_cx, Network);
+ return p;
}
- let (sender, receiver) = ipc::channel().unwrap();
+ let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
- BluetoothMethodMsg::GetIncludedService(self.get_instance_id(),
+ BluetoothRequest::GetIncludedService(self.get_instance_id(),
uuid,
sender)).unwrap();
- let service = receiver.recv().unwrap();
- match service {
- Ok(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) {
- return Ok(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));
- Ok(bt_service)
- },
- Err(error) => {
- Err(Error::from(error))
- },
- }
+ return p;
}
+
+ #[allow(unrooted_must_root)]
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices
- fn get_included_services(&self,
- service: Option<BluetoothServiceUUID>)
- -> Fallible<Vec<Root<BluetoothRemoteGATTService>>> {
+ fn GetIncludedServices(&self,
+ service: Option<BluetoothServiceUUID>)
+ -> Rc<Promise> {
+ let p = Promise::new(&self.global());
+ let p_cx = p.global().get_cx();
let mut uuid: Option<String> = None;
if let Some(s) = service {
- uuid = Some(try!(BluetoothUUID::service(s)).to_string());
+ 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 {
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
- return Err(Security)
+ p.reject_error(p_cx, Security);
+ return p;
}
}
};
if !self.Device().Gatt().Connected() {
- return Err(Network)
+ p.reject_error(p_cx, Network);
+ return p;
}
- let (sender, receiver) = ipc::channel().unwrap();
+ let sender = response_async(&p, self);
self.get_bluetooth_thread().send(
- BluetoothMethodMsg::GetIncludedServices(self.get_instance_id(),
+ BluetoothRequest::GetIncludedServices(self.get_instance_id(),
uuid,
sender)).unwrap();
- let services_vec = receiver.recv().unwrap();
- let mut services = vec!();
- match services_vec {
- Ok(service_vec) => {
+ return p;
+ }
+}
+
+impl AsyncBluetoothListener for BluetoothRemoteGATTService {
+ fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc<Promise>) {
+ match response {
+ 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));
+ promise.resolve_native(promise_cx, &bt_characteristic);
+ },
+ BluetoothResponse::GetCharacteristics(characteristics_vec) => {
+ let mut characteristics = vec!();
let context = self.device.get().get_context();
- let mut service_map = context.get_service_map().borrow_mut();
- for service in service_vec {
- let bt_service = match service_map.get(&service.instance_id) {
- Some(existing_service) => existing_service.get(),
+ 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 => {
- BluetoothRemoteGATTService::new(&self.global(),
- &self.device.get(),
- DOMString::from(service.uuid),
- service.is_primary,
- service.instance_id.clone())
+ 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 !service_map.contains_key(&service.instance_id) {
- service_map.insert(service.instance_id, MutHeap::new(&bt_service));
+ if !characteristic_map.contains_key(&characteristic.instance_id) {
+ characteristic_map.insert(characteristic.instance_id, MutHeap::new(&bt_characteristic));
}
- services.push(bt_service);
+ characteristics.push(bt_characteristic);
}
- Ok(services)
+ promise.resolve_native(promise_cx, &characteristics);
+ },
+ 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);
},
- Err(error) => {
- Err(Error::from(error))
+ BluetoothResponse::GetIncludedServices(services_vec) => {
+ let s: Vec<Root<BluetoothRemoteGATTService>> =
+ 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);
},
+ _ => promise.reject_error(promise_cx, Error::Type("Something went wrong...".to_owned())),
}
}
}
-
-impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-device
- fn Device(&self) -> Root<BluetoothDevice> {
- self.device.get()
- }
-
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-isprimary
- fn IsPrimary(&self) -> bool {
- self.is_primary
- }
-
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-uuid
- fn Uuid(&self) -> DOMString {
- self.uuid.clone()
- }
-
- #[allow(unrooted_must_root)]
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic
- fn GetCharacteristic(&self,
- characteristic: BluetoothCharacteristicUUID)
- -> Rc<Promise> {
- result_to_promise(&self.global(), self.get_characteristic(characteristic))
- }
-
- #[allow(unrooted_must_root)]
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics
- fn GetCharacteristics(&self,
- characteristic: Option<BluetoothCharacteristicUUID>)
- -> Rc<Promise> {
- result_to_promise(&self.global(), self.get_characteristics(characteristic))
- }
-
- #[allow(unrooted_must_root)]
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservice
- fn GetIncludedService(&self,
- service: BluetoothServiceUUID)
- -> Rc<Promise> {
- result_to_promise(&self.global(), self.get_included_service(service))
- }
-
- #[allow(unrooted_must_root)]
- // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices
- fn GetIncludedServices(&self,
- service: Option<BluetoothServiceUUID>)
- -> Rc<Promise> {
- result_to_promise(&self.global(), self.get_included_services(service))
- }
-}
diff --git a/components/script/dom/testrunner.rs b/components/script/dom/testrunner.rs
index f96ab6dbf65..0bae004c90c 100644
--- a/components/script/dom/testrunner.rs
+++ b/components/script/dom/testrunner.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::BluetoothMethodMsg;
+use bluetooth_traits::BluetoothRequest;
use dom::bindings::codegen::Bindings::TestRunnerBinding;
use dom::bindings::codegen::Bindings::TestRunnerBinding::TestRunnerMethods;
use dom::bindings::error::{Error, ErrorResult};
@@ -31,7 +31,7 @@ impl TestRunner {
TestRunnerBinding::Wrap)
}
- fn get_bluetooth_thread(&self) -> IpcSender<BluetoothMethodMsg> {
+ fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
self.global().as_window().bluetooth_thread()
}
}
@@ -40,7 +40,7 @@ impl TestRunnerMethods for TestRunner {
// https://webbluetoothcg.github.io/web-bluetooth/tests#setBluetoothMockDataSet
fn SetBluetoothMockDataSet(&self, dataSetName: DOMString) -> ErrorResult {
let (sender, receiver) = ipc::channel().unwrap();
- self.get_bluetooth_thread().send(BluetoothMethodMsg::Test(String::from(dataSetName), sender)).unwrap();
+ self.get_bluetooth_thread().send(BluetoothRequest::Test(String::from(dataSetName), sender)).unwrap();
match receiver.recv().unwrap().into() {
Ok(()) => {
Ok(())
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 3d3d7dde2a7..a78dcda8893 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use app_units::Au;
-use bluetooth_traits::BluetoothMethodMsg;
+use bluetooth_traits::BluetoothRequest;
use cssparser::Parser;
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
use dom::bindings::callback::ExceptionHandling;
@@ -203,7 +203,7 @@ pub struct Window {
/// A handle for communicating messages to the bluetooth thread.
#[ignore_heap_size_of = "channels are hard"]
- bluetooth_thread: IpcSender<BluetoothMethodMsg>,
+ bluetooth_thread: IpcSender<BluetoothRequest>,
/// Pending scroll to fragment event, if any
fragment_name: DOMRefCell<Option<String>>,
@@ -304,7 +304,7 @@ impl Window {
self.browsing_context.get().unwrap()
}
- pub fn bluetooth_thread(&self) -> IpcSender<BluetoothMethodMsg> {
+ pub fn bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
self.bluetooth_thread.clone()
}
@@ -1521,7 +1521,7 @@ impl Window {
image_cache_chan: ImageCacheChan,
image_cache_thread: ImageCacheThread,
resource_threads: ResourceThreads,
- bluetooth_thread: IpcSender<BluetoothMethodMsg>,
+ bluetooth_thread: IpcSender<BluetoothRequest>,
mem_profiler_chan: mem::ProfilerChan,
time_profiler_chan: ProfilerChan,
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,