mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Webbluetooth Async behaviour
This commit is contained in:
parent
4a7ea72429
commit
e7e7c74c9e
19 changed files with 806 additions and 729 deletions
|
@ -15,10 +15,9 @@ extern crate uuid;
|
||||||
|
|
||||||
pub mod test;
|
pub mod test;
|
||||||
|
|
||||||
use bluetooth_traits::{BluetoothCharacteristicMsg, BluetoothCharacteristicsMsg};
|
use bluetooth_traits::{BluetoothCharacteristicMsg, BluetoothDescriptorMsg, BluetoothServiceMsg};
|
||||||
use bluetooth_traits::{BluetoothDescriptorMsg, BluetoothDescriptorsMsg};
|
use bluetooth_traits::{BluetoothDeviceMsg, BluetoothRequest, BluetoothResponse};
|
||||||
use bluetooth_traits::{BluetoothDeviceMsg, BluetoothError, BluetoothMethodMsg};
|
use bluetooth_traits::{BluetoothError, BluetoothResponseResult, BluetoothResult};
|
||||||
use bluetooth_traits::{BluetoothResult, BluetoothServiceMsg, BluetoothServicesMsg};
|
|
||||||
use bluetooth_traits::blacklist::{uuid_is_blacklisted, Blacklist};
|
use bluetooth_traits::blacklist::{uuid_is_blacklisted, Blacklist};
|
||||||
use bluetooth_traits::scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence, RequestDeviceoptions};
|
use bluetooth_traits::scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence, RequestDeviceoptions};
|
||||||
use device::bluetooth::{BluetoothAdapter, BluetoothDevice, BluetoothGATTCharacteristic};
|
use device::bluetooth::{BluetoothAdapter, BluetoothDevice, BluetoothGATTCharacteristic};
|
||||||
|
@ -85,8 +84,8 @@ pub trait BluetoothThreadFactory {
|
||||||
fn new() -> Self;
|
fn new() -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BluetoothThreadFactory for IpcSender<BluetoothMethodMsg> {
|
impl BluetoothThreadFactory for IpcSender<BluetoothRequest> {
|
||||||
fn new() -> IpcSender<BluetoothMethodMsg> {
|
fn new() -> IpcSender<BluetoothRequest> {
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
let (sender, receiver) = ipc::channel().unwrap();
|
||||||
let adapter = BluetoothAdapter::init().ok();
|
let adapter = BluetoothAdapter::init().ok();
|
||||||
spawn_named("BluetoothThread".to_owned(), move || {
|
spawn_named("BluetoothThread".to_owned(), move || {
|
||||||
|
@ -167,7 +166,7 @@ fn is_mock_adapter(adapter: &BluetoothAdapter) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BluetoothManager {
|
pub struct BluetoothManager {
|
||||||
receiver: IpcReceiver<BluetoothMethodMsg>,
|
receiver: IpcReceiver<BluetoothRequest>,
|
||||||
adapter: Option<BluetoothAdapter>,
|
adapter: Option<BluetoothAdapter>,
|
||||||
address_to_id: HashMap<String, String>,
|
address_to_id: HashMap<String, String>,
|
||||||
service_to_device: HashMap<String, String>,
|
service_to_device: HashMap<String, String>,
|
||||||
|
@ -181,7 +180,7 @@ pub struct BluetoothManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BluetoothManager {
|
impl BluetoothManager {
|
||||||
pub fn new(receiver: IpcReceiver<BluetoothMethodMsg>, adapter: Option<BluetoothAdapter>) -> BluetoothManager {
|
pub fn new(receiver: IpcReceiver<BluetoothRequest>, adapter: Option<BluetoothAdapter>) -> BluetoothManager {
|
||||||
BluetoothManager {
|
BluetoothManager {
|
||||||
receiver: receiver,
|
receiver: receiver,
|
||||||
adapter: adapter,
|
adapter: adapter,
|
||||||
|
@ -200,49 +199,49 @@ impl BluetoothManager {
|
||||||
fn start(&mut self) {
|
fn start(&mut self) {
|
||||||
while let Ok(msg) = self.receiver.recv() {
|
while let Ok(msg) = self.receiver.recv() {
|
||||||
match msg {
|
match msg {
|
||||||
BluetoothMethodMsg::RequestDevice(options, sender) => {
|
BluetoothRequest::RequestDevice(options, sender) => {
|
||||||
self.request_device(options, sender)
|
self.request_device(options, sender)
|
||||||
},
|
},
|
||||||
BluetoothMethodMsg::GATTServerConnect(device_id, sender) => {
|
BluetoothRequest::GATTServerConnect(device_id, sender) => {
|
||||||
self.gatt_server_connect(device_id, sender)
|
self.gatt_server_connect(device_id, sender)
|
||||||
},
|
},
|
||||||
BluetoothMethodMsg::GATTServerDisconnect(device_id, sender) => {
|
BluetoothRequest::GATTServerDisconnect(device_id, sender) => {
|
||||||
self.gatt_server_disconnect(device_id, sender)
|
self.gatt_server_disconnect(device_id, sender)
|
||||||
},
|
},
|
||||||
BluetoothMethodMsg::GetPrimaryService(device_id, uuid, sender) => {
|
BluetoothRequest::GetPrimaryService(device_id, uuid, sender) => {
|
||||||
self.get_primary_service(device_id, uuid, sender)
|
self.get_primary_service(device_id, uuid, sender)
|
||||||
},
|
},
|
||||||
BluetoothMethodMsg::GetPrimaryServices(device_id, uuid, sender) => {
|
BluetoothRequest::GetPrimaryServices(device_id, uuid, sender) => {
|
||||||
self.get_primary_services(device_id, uuid, sender)
|
self.get_primary_services(device_id, uuid, sender)
|
||||||
},
|
},
|
||||||
BluetoothMethodMsg::GetIncludedService(service_id, uuid, sender) => {
|
BluetoothRequest::GetIncludedService(service_id, uuid, sender) => {
|
||||||
self.get_included_service(service_id, uuid, sender)
|
self.get_included_service(service_id, uuid, sender)
|
||||||
},
|
},
|
||||||
BluetoothMethodMsg::GetIncludedServices(service_id, uuid, sender) => {
|
BluetoothRequest::GetIncludedServices(service_id, uuid, sender) => {
|
||||||
self.get_included_services(service_id, uuid, sender)
|
self.get_included_services(service_id, uuid, sender)
|
||||||
},
|
},
|
||||||
BluetoothMethodMsg::GetCharacteristic(service_id, uuid, sender) => {
|
BluetoothRequest::GetCharacteristic(service_id, uuid, sender) => {
|
||||||
self.get_characteristic(service_id, uuid, sender)
|
self.get_characteristic(service_id, uuid, sender)
|
||||||
},
|
},
|
||||||
BluetoothMethodMsg::GetCharacteristics(service_id, uuid, sender) => {
|
BluetoothRequest::GetCharacteristics(service_id, uuid, sender) => {
|
||||||
self.get_characteristics(service_id, uuid, sender)
|
self.get_characteristics(service_id, uuid, sender)
|
||||||
},
|
},
|
||||||
BluetoothMethodMsg::GetDescriptor(characteristic_id, uuid, sender) => {
|
BluetoothRequest::GetDescriptor(characteristic_id, uuid, sender) => {
|
||||||
self.get_descriptor(characteristic_id, uuid, sender)
|
self.get_descriptor(characteristic_id, uuid, sender)
|
||||||
},
|
},
|
||||||
BluetoothMethodMsg::GetDescriptors(characteristic_id, uuid, sender) => {
|
BluetoothRequest::GetDescriptors(characteristic_id, uuid, sender) => {
|
||||||
self.get_descriptors(characteristic_id, uuid, sender)
|
self.get_descriptors(characteristic_id, uuid, sender)
|
||||||
},
|
},
|
||||||
BluetoothMethodMsg::ReadValue(id, sender) => {
|
BluetoothRequest::ReadValue(id, sender) => {
|
||||||
self.read_value(id, sender)
|
self.read_value(id, sender)
|
||||||
},
|
},
|
||||||
BluetoothMethodMsg::WriteValue(id, value, sender) => {
|
BluetoothRequest::WriteValue(id, value, sender) => {
|
||||||
self.write_value(id, value, sender)
|
self.write_value(id, value, sender)
|
||||||
},
|
},
|
||||||
BluetoothMethodMsg::Test(data_set_name, sender) => {
|
BluetoothRequest::Test(data_set_name, sender) => {
|
||||||
self.test(data_set_name, sender)
|
self.test(data_set_name, sender)
|
||||||
}
|
}
|
||||||
BluetoothMethodMsg::Exit => {
|
BluetoothRequest::Exit => {
|
||||||
break
|
break
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -527,7 +526,7 @@ impl BluetoothManager {
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices
|
// https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices
|
||||||
fn request_device(&mut self,
|
fn request_device(&mut self,
|
||||||
options: RequestDeviceoptions,
|
options: RequestDeviceoptions,
|
||||||
sender: IpcSender<BluetoothResult<BluetoothDeviceMsg>>) {
|
sender: IpcSender<BluetoothResponseResult>) {
|
||||||
let mut adapter = get_adapter_or_return_error!(self, sender);
|
let mut adapter = get_adapter_or_return_error!(self, sender);
|
||||||
if let Ok(ref session) = adapter.create_discovery_session() {
|
if let Ok(ref session) = adapter.create_discovery_session() {
|
||||||
if session.start_discovery().is_ok() {
|
if session.start_discovery().is_ok() {
|
||||||
|
@ -561,31 +560,30 @@ impl BluetoothManager {
|
||||||
}
|
}
|
||||||
self.allowed_services.insert(device_id.clone(), services);
|
self.allowed_services.insert(device_id.clone(), services);
|
||||||
if let Some(device) = self.get_device(&mut adapter, &device_id) {
|
if let Some(device) = self.get_device(&mut adapter, &device_id) {
|
||||||
let message = Ok(BluetoothDeviceMsg {
|
let message = BluetoothDeviceMsg {
|
||||||
id: device_id,
|
id: device_id,
|
||||||
name: device.get_name().ok(),
|
name: device.get_name().ok(),
|
||||||
appearance: device.get_appearance().ok(),
|
appearance: device.get_appearance().ok(),
|
||||||
tx_power: device.get_tx_power().ok().map(|p| p as i8),
|
tx_power: device.get_tx_power().ok().map(|p| p as i8),
|
||||||
rssi: device.get_rssi().ok().map(|p| p as i8),
|
rssi: device.get_rssi().ok().map(|p| p as i8),
|
||||||
});
|
};
|
||||||
return drop(sender.send(message));
|
return drop(sender.send(Ok(BluetoothResponse::RequestDevice(message))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return drop(sender.send(Err(BluetoothError::NotFound)));
|
return drop(sender.send(Err(BluetoothError::NotFound)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gatt_server_connect(&mut self, device_id: String, sender: IpcSender<BluetoothResult<bool>>) {
|
fn gatt_server_connect(&mut self, device_id: String, sender: IpcSender<BluetoothResponseResult>) {
|
||||||
let mut adapter = get_adapter_or_return_error!(self, sender);
|
let mut adapter = get_adapter_or_return_error!(self, sender);
|
||||||
|
|
||||||
match self.get_device(&mut adapter, &device_id) {
|
match self.get_device(&mut adapter, &device_id) {
|
||||||
Some(d) => {
|
Some(d) => {
|
||||||
if d.is_connected().unwrap_or(false) {
|
if d.is_connected().unwrap_or(false) {
|
||||||
return drop(sender.send(Ok(true)));
|
return drop(sender.send(Ok(BluetoothResponse::GATTServerConnect(true))));
|
||||||
}
|
}
|
||||||
let _ = d.connect();
|
let _ = d.connect();
|
||||||
for _ in 0..MAXIMUM_TRANSACTION_TIME {
|
for _ in 0..MAXIMUM_TRANSACTION_TIME {
|
||||||
match d.is_connected().unwrap_or(false) {
|
match d.is_connected().unwrap_or(false) {
|
||||||
true => return drop(sender.send(Ok(true))),
|
true => return drop(sender.send(Ok(BluetoothResponse::GATTServerConnect(true)))),
|
||||||
false => {
|
false => {
|
||||||
if is_mock_adapter(&adapter) {
|
if is_mock_adapter(&adapter) {
|
||||||
break;
|
break;
|
||||||
|
@ -624,7 +622,7 @@ impl BluetoothManager {
|
||||||
fn get_primary_service(&mut self,
|
fn get_primary_service(&mut self,
|
||||||
device_id: String,
|
device_id: String,
|
||||||
uuid: String,
|
uuid: String,
|
||||||
sender: IpcSender<BluetoothResult<BluetoothServiceMsg>>) {
|
sender: IpcSender<BluetoothResponseResult>) {
|
||||||
if !self.cached_devices.contains_key(&device_id) {
|
if !self.cached_devices.contains_key(&device_id) {
|
||||||
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
||||||
}
|
}
|
||||||
|
@ -639,11 +637,15 @@ impl BluetoothManager {
|
||||||
for service in services {
|
for service in services {
|
||||||
if service.is_primary().unwrap_or(false) {
|
if service.is_primary().unwrap_or(false) {
|
||||||
if let Ok(uuid) = service.get_uuid() {
|
if let Ok(uuid) = service.get_uuid() {
|
||||||
return drop(sender.send(Ok(BluetoothServiceMsg {
|
return drop(sender.send(
|
||||||
uuid: uuid,
|
Ok(BluetoothResponse::GetPrimaryService(
|
||||||
is_primary: true,
|
BluetoothServiceMsg {
|
||||||
instance_id: service.get_id(),
|
uuid: uuid,
|
||||||
})));
|
is_primary: true,
|
||||||
|
instance_id: service.get_id(),
|
||||||
|
}
|
||||||
|
))
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -653,7 +655,7 @@ impl BluetoothManager {
|
||||||
fn get_primary_services(&mut self,
|
fn get_primary_services(&mut self,
|
||||||
device_id: String,
|
device_id: String,
|
||||||
uuid: Option<String>,
|
uuid: Option<String>,
|
||||||
sender: IpcSender<BluetoothResult<BluetoothServicesMsg>>) {
|
sender: IpcSender<BluetoothResponseResult>) {
|
||||||
if !self.cached_devices.contains_key(&device_id) {
|
if !self.cached_devices.contains_key(&device_id) {
|
||||||
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
||||||
}
|
}
|
||||||
|
@ -674,11 +676,13 @@ impl BluetoothManager {
|
||||||
for service in services {
|
for service in services {
|
||||||
if service.is_primary().unwrap_or(false) {
|
if service.is_primary().unwrap_or(false) {
|
||||||
if let Ok(uuid) = service.get_uuid() {
|
if let Ok(uuid) = service.get_uuid() {
|
||||||
services_vec.push(BluetoothServiceMsg {
|
services_vec.push(
|
||||||
uuid: uuid,
|
BluetoothServiceMsg {
|
||||||
is_primary: true,
|
uuid: uuid,
|
||||||
instance_id: service.get_id(),
|
is_primary: true,
|
||||||
});
|
instance_id: service.get_id(),
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -690,20 +694,17 @@ impl BluetoothManager {
|
||||||
return drop(sender.send(Err(BluetoothError::NotFound)));
|
return drop(sender.send(Err(BluetoothError::NotFound)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = sender.send(Ok(services_vec));
|
return drop(sender.send(Ok(BluetoothResponse::GetPrimaryServices(services_vec))));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_included_service(&mut self,
|
fn get_included_service(&mut self,
|
||||||
service_id: String,
|
service_id: String,
|
||||||
uuid: String,
|
uuid: String,
|
||||||
sender: IpcSender<BluetoothResult<BluetoothServiceMsg>>) {
|
sender: IpcSender<BluetoothResponseResult>) {
|
||||||
if !self.cached_services.contains_key(&service_id) {
|
if !self.cached_services.contains_key(&service_id) {
|
||||||
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
||||||
}
|
}
|
||||||
let mut adapter = match self.get_or_create_adapter() {
|
let mut adapter = get_adapter_or_return_error!(self, sender);
|
||||||
Some(a) => a,
|
|
||||||
None => return drop(sender.send(Err(BluetoothError::NotFound))),
|
|
||||||
};
|
|
||||||
let device = match self.device_from_service_id(&service_id) {
|
let device = match self.device_from_service_id(&service_id) {
|
||||||
Some(device) => device,
|
Some(device) => device,
|
||||||
None => return drop(sender.send(Err(BluetoothError::NotFound))),
|
None => return drop(sender.send(Err(BluetoothError::NotFound))),
|
||||||
|
@ -716,11 +717,15 @@ impl BluetoothManager {
|
||||||
for service in services {
|
for service in services {
|
||||||
if let Ok(service_uuid) = service.get_uuid() {
|
if let Ok(service_uuid) = service.get_uuid() {
|
||||||
if uuid == service_uuid {
|
if uuid == service_uuid {
|
||||||
return drop(sender.send(Ok(BluetoothServiceMsg {
|
return drop(sender.send(
|
||||||
uuid: uuid,
|
Ok(BluetoothResponse::GetIncludedService(
|
||||||
is_primary: service.is_primary().unwrap_or(false),
|
BluetoothServiceMsg {
|
||||||
instance_id: service.get_id(),
|
uuid: uuid,
|
||||||
})));
|
is_primary: service.is_primary().unwrap_or(false),
|
||||||
|
instance_id: service.get_id(),
|
||||||
|
}
|
||||||
|
))
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -730,14 +735,11 @@ impl BluetoothManager {
|
||||||
fn get_included_services(&mut self,
|
fn get_included_services(&mut self,
|
||||||
service_id: String,
|
service_id: String,
|
||||||
uuid: Option<String>,
|
uuid: Option<String>,
|
||||||
sender: IpcSender<BluetoothResult<BluetoothServicesMsg>>) {
|
sender: IpcSender<BluetoothResponseResult>) {
|
||||||
if !self.cached_services.contains_key(&service_id) {
|
if !self.cached_services.contains_key(&service_id) {
|
||||||
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
||||||
}
|
}
|
||||||
let mut adapter = match self.get_or_create_adapter() {
|
let mut adapter = get_adapter_or_return_error!(self, sender);
|
||||||
Some(a) => a,
|
|
||||||
None => return drop(sender.send(Err(BluetoothError::NotFound))),
|
|
||||||
};
|
|
||||||
let device = match self.device_from_service_id(&service_id) {
|
let device = match self.device_from_service_id(&service_id) {
|
||||||
Some(device) => device,
|
Some(device) => device,
|
||||||
None => return drop(sender.send(Err(BluetoothError::NotFound))),
|
None => return drop(sender.send(Err(BluetoothError::NotFound))),
|
||||||
|
@ -750,11 +752,13 @@ impl BluetoothManager {
|
||||||
let mut services_vec = vec!();
|
let mut services_vec = vec!();
|
||||||
for service in services {
|
for service in services {
|
||||||
if let Ok(service_uuid) = service.get_uuid() {
|
if let Ok(service_uuid) = service.get_uuid() {
|
||||||
services_vec.push(BluetoothServiceMsg {
|
services_vec.push(
|
||||||
uuid: service_uuid,
|
BluetoothServiceMsg {
|
||||||
is_primary: service.is_primary().unwrap_or(false),
|
uuid: service_uuid,
|
||||||
instance_id: service.get_id(),
|
is_primary: service.is_primary().unwrap_or(false),
|
||||||
});
|
instance_id: service.get_id(),
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(uuid) = uuid {
|
if let Some(uuid) = uuid {
|
||||||
|
@ -765,13 +769,13 @@ impl BluetoothManager {
|
||||||
return drop(sender.send(Err(BluetoothError::NotFound)));
|
return drop(sender.send(Err(BluetoothError::NotFound)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = sender.send(Ok(services_vec));
|
return drop(sender.send(Ok(BluetoothResponse::GetIncludedServices(services_vec))));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_characteristic(&mut self,
|
fn get_characteristic(&mut self,
|
||||||
service_id: String,
|
service_id: String,
|
||||||
uuid: String,
|
uuid: String,
|
||||||
sender: IpcSender<BluetoothResult<BluetoothCharacteristicMsg>>) {
|
sender: IpcSender<BluetoothResponseResult>) {
|
||||||
if !self.cached_services.contains_key(&service_id) {
|
if !self.cached_services.contains_key(&service_id) {
|
||||||
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
||||||
}
|
}
|
||||||
|
@ -783,20 +787,20 @@ impl BluetoothManager {
|
||||||
for characteristic in characteristics {
|
for characteristic in characteristics {
|
||||||
if let Ok(uuid) = characteristic.get_uuid() {
|
if let Ok(uuid) = characteristic.get_uuid() {
|
||||||
let properties = self.get_characteristic_properties(&characteristic);
|
let properties = self.get_characteristic_properties(&characteristic);
|
||||||
let message = Ok(BluetoothCharacteristicMsg {
|
let message = BluetoothCharacteristicMsg {
|
||||||
uuid: uuid,
|
uuid: uuid,
|
||||||
instance_id: characteristic.get_id(),
|
instance_id: characteristic.get_id(),
|
||||||
broadcast: properties.contains(BROADCAST),
|
broadcast: properties.contains(BROADCAST),
|
||||||
read: properties.contains(READ),
|
read: properties.contains(READ),
|
||||||
write_without_response: properties.contains(WRITE_WITHOUT_RESPONSE),
|
write_without_response: properties.contains(WRITE_WITHOUT_RESPONSE),
|
||||||
write: properties.contains(WRITE),
|
write: properties.contains(WRITE),
|
||||||
notify: properties.contains(NOTIFY),
|
notify: properties.contains(NOTIFY),
|
||||||
indicate: properties.contains(INDICATE),
|
indicate: properties.contains(INDICATE),
|
||||||
authenticated_signed_writes: properties.contains(AUTHENTICATED_SIGNED_WRITES),
|
authenticated_signed_writes: properties.contains(AUTHENTICATED_SIGNED_WRITES),
|
||||||
reliable_write: properties.contains(RELIABLE_WRITE),
|
reliable_write: properties.contains(RELIABLE_WRITE),
|
||||||
writable_auxiliaries: properties.contains(WRITABLE_AUXILIARIES),
|
writable_auxiliaries: properties.contains(WRITABLE_AUXILIARIES),
|
||||||
});
|
};
|
||||||
return drop(sender.send(message));
|
return drop(sender.send(Ok(BluetoothResponse::GetCharacteristic(message))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return drop(sender.send(Err(BluetoothError::NotFound)));
|
return drop(sender.send(Err(BluetoothError::NotFound)));
|
||||||
|
@ -805,7 +809,7 @@ impl BluetoothManager {
|
||||||
fn get_characteristics(&mut self,
|
fn get_characteristics(&mut self,
|
||||||
service_id: String,
|
service_id: String,
|
||||||
uuid: Option<String>,
|
uuid: Option<String>,
|
||||||
sender: IpcSender<BluetoothResult<BluetoothCharacteristicsMsg>>) {
|
sender: IpcSender<BluetoothResponseResult>) {
|
||||||
if !self.cached_services.contains_key(&service_id) {
|
if !self.cached_services.contains_key(&service_id) {
|
||||||
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
||||||
}
|
}
|
||||||
|
@ -822,19 +826,20 @@ impl BluetoothManager {
|
||||||
if let Ok(uuid) = characteristic.get_uuid() {
|
if let Ok(uuid) = characteristic.get_uuid() {
|
||||||
let properties = self.get_characteristic_properties(&characteristic);
|
let properties = self.get_characteristic_properties(&characteristic);
|
||||||
characteristics_vec.push(
|
characteristics_vec.push(
|
||||||
BluetoothCharacteristicMsg {
|
BluetoothCharacteristicMsg {
|
||||||
uuid: uuid,
|
uuid: uuid,
|
||||||
instance_id: characteristic.get_id(),
|
instance_id: characteristic.get_id(),
|
||||||
broadcast: properties.contains(BROADCAST),
|
broadcast: properties.contains(BROADCAST),
|
||||||
read: properties.contains(READ),
|
read: properties.contains(READ),
|
||||||
write_without_response: properties.contains(WRITE_WITHOUT_RESPONSE),
|
write_without_response: properties.contains(WRITE_WITHOUT_RESPONSE),
|
||||||
write: properties.contains(WRITE),
|
write: properties.contains(WRITE),
|
||||||
notify: properties.contains(NOTIFY),
|
notify: properties.contains(NOTIFY),
|
||||||
indicate: properties.contains(INDICATE),
|
indicate: properties.contains(INDICATE),
|
||||||
authenticated_signed_writes: properties.contains(AUTHENTICATED_SIGNED_WRITES),
|
authenticated_signed_writes: properties.contains(AUTHENTICATED_SIGNED_WRITES),
|
||||||
reliable_write: properties.contains(RELIABLE_WRITE),
|
reliable_write: properties.contains(RELIABLE_WRITE),
|
||||||
writable_auxiliaries: properties.contains(WRITABLE_AUXILIARIES),
|
writable_auxiliaries: properties.contains(WRITABLE_AUXILIARIES),
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
characteristics_vec.retain(|c| !uuid_is_blacklisted(&c.uuid, Blacklist::All));
|
characteristics_vec.retain(|c| !uuid_is_blacklisted(&c.uuid, Blacklist::All));
|
||||||
|
@ -842,13 +847,13 @@ impl BluetoothManager {
|
||||||
return drop(sender.send(Err(BluetoothError::NotFound)));
|
return drop(sender.send(Err(BluetoothError::NotFound)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = sender.send(Ok(characteristics_vec));
|
return drop(sender.send(Ok(BluetoothResponse::GetCharacteristics(characteristics_vec))));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_descriptor(&mut self,
|
fn get_descriptor(&mut self,
|
||||||
characteristic_id: String,
|
characteristic_id: String,
|
||||||
uuid: String,
|
uuid: String,
|
||||||
sender: IpcSender<BluetoothResult<BluetoothDescriptorMsg>>) {
|
sender: IpcSender<BluetoothResponseResult>) {
|
||||||
if !self.cached_characteristics.contains_key(&characteristic_id) {
|
if !self.cached_characteristics.contains_key(&characteristic_id) {
|
||||||
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
||||||
}
|
}
|
||||||
|
@ -859,10 +864,14 @@ impl BluetoothManager {
|
||||||
}
|
}
|
||||||
for descriptor in descriptors {
|
for descriptor in descriptors {
|
||||||
if let Ok(uuid) = descriptor.get_uuid() {
|
if let Ok(uuid) = descriptor.get_uuid() {
|
||||||
return drop(sender.send(Ok(BluetoothDescriptorMsg {
|
return drop(sender.send(
|
||||||
uuid: uuid,
|
Ok(BluetoothResponse::GetDescriptor(
|
||||||
instance_id: descriptor.get_id(),
|
BluetoothDescriptorMsg {
|
||||||
})));
|
uuid: uuid,
|
||||||
|
instance_id: descriptor.get_id(),
|
||||||
|
}
|
||||||
|
))
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return drop(sender.send(Err(BluetoothError::NotFound)));
|
return drop(sender.send(Err(BluetoothError::NotFound)));
|
||||||
|
@ -871,7 +880,7 @@ impl BluetoothManager {
|
||||||
fn get_descriptors(&mut self,
|
fn get_descriptors(&mut self,
|
||||||
characteristic_id: String,
|
characteristic_id: String,
|
||||||
uuid: Option<String>,
|
uuid: Option<String>,
|
||||||
sender: IpcSender<BluetoothResult<BluetoothDescriptorsMsg>>) {
|
sender: IpcSender<BluetoothResponseResult>) {
|
||||||
if !self.cached_characteristics.contains_key(&characteristic_id) {
|
if !self.cached_characteristics.contains_key(&characteristic_id) {
|
||||||
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
return drop(sender.send(Err(BluetoothError::InvalidState)));
|
||||||
}
|
}
|
||||||
|
@ -886,20 +895,22 @@ impl BluetoothManager {
|
||||||
let mut descriptors_vec = vec!();
|
let mut descriptors_vec = vec!();
|
||||||
for descriptor in descriptors {
|
for descriptor in descriptors {
|
||||||
if let Ok(uuid) = descriptor.get_uuid() {
|
if let Ok(uuid) = descriptor.get_uuid() {
|
||||||
descriptors_vec.push(BluetoothDescriptorMsg {
|
descriptors_vec.push(
|
||||||
uuid: uuid,
|
BluetoothDescriptorMsg {
|
||||||
instance_id: descriptor.get_id(),
|
uuid: uuid,
|
||||||
});
|
instance_id: descriptor.get_id(),
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
descriptors_vec.retain(|d| !uuid_is_blacklisted(&d.uuid, Blacklist::All));
|
descriptors_vec.retain(|d| !uuid_is_blacklisted(&d.uuid, Blacklist::All));
|
||||||
if descriptors_vec.is_empty() {
|
if descriptors_vec.is_empty() {
|
||||||
return drop(sender.send(Err(BluetoothError::NotFound)));
|
return drop(sender.send(Err(BluetoothError::NotFound)));
|
||||||
}
|
}
|
||||||
let _ = sender.send(Ok(descriptors_vec));
|
return drop(sender.send(Ok(BluetoothResponse::GetDescriptors(descriptors_vec))));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_value(&mut self, id: String, sender: IpcSender<BluetoothResult<Vec<u8>>>) {
|
fn read_value(&mut self, id: String, sender: IpcSender<BluetoothResponseResult>) {
|
||||||
let mut adapter = get_adapter_or_return_error!(self, sender);
|
let mut adapter = get_adapter_or_return_error!(self, sender);
|
||||||
let mut value = self.get_gatt_characteristic(&mut adapter, &id)
|
let mut value = self.get_gatt_characteristic(&mut adapter, &id)
|
||||||
.map(|c| c.read_value().unwrap_or(vec![]));
|
.map(|c| c.read_value().unwrap_or(vec![]));
|
||||||
|
@ -907,10 +918,13 @@ impl BluetoothManager {
|
||||||
value = self.get_gatt_descriptor(&mut adapter, &id)
|
value = self.get_gatt_descriptor(&mut adapter, &id)
|
||||||
.map(|d| d.read_value().unwrap_or(vec![]));
|
.map(|d| d.read_value().unwrap_or(vec![]));
|
||||||
}
|
}
|
||||||
let _ = sender.send(value.ok_or(BluetoothError::InvalidState));
|
match value {
|
||||||
|
Some(v) => return drop(sender.send(Ok(BluetoothResponse::ReadValue(v)))),
|
||||||
|
None => return drop(sender.send(Err(BluetoothError::InvalidState))),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_value(&mut self, id: String, value: Vec<u8>, sender: IpcSender<BluetoothResult<bool>>) {
|
fn write_value(&mut self, id: String, value: Vec<u8>, sender: IpcSender<BluetoothResponseResult>) {
|
||||||
let mut adapter = get_adapter_or_return_error!(self, sender);
|
let mut adapter = get_adapter_or_return_error!(self, sender);
|
||||||
let mut result = self.get_gatt_characteristic(&mut adapter, &id)
|
let mut result = self.get_gatt_characteristic(&mut adapter, &id)
|
||||||
.map(|c| c.write_value(value.clone()));
|
.map(|c| c.write_value(value.clone()));
|
||||||
|
@ -918,13 +932,12 @@ impl BluetoothManager {
|
||||||
result = self.get_gatt_descriptor(&mut adapter, &id)
|
result = self.get_gatt_descriptor(&mut adapter, &id)
|
||||||
.map(|d| d.write_value(value.clone()));
|
.map(|d| d.write_value(value.clone()));
|
||||||
}
|
}
|
||||||
let message = match result {
|
match result {
|
||||||
Some(v) => match v {
|
Some(v) => match v {
|
||||||
Ok(_) => Ok(true),
|
Ok(_) => return drop(sender.send(Ok(BluetoothResponse::WriteValue(value)))),
|
||||||
Err(_) => return drop(sender.send(Err(BluetoothError::NotSupported))),
|
Err(_) => return drop(sender.send(Err(BluetoothError::NotSupported))),
|
||||||
},
|
},
|
||||||
None => return drop(sender.send(Err(BluetoothError::InvalidState))),
|
None => return drop(sender.send(Err(BluetoothError::InvalidState))),
|
||||||
};
|
}
|
||||||
let _ = sender.send(message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,21 +75,43 @@ pub type BluetoothDescriptorsMsg = Vec<BluetoothDescriptorMsg>;
|
||||||
|
|
||||||
pub type BluetoothResult<T> = Result<T, BluetoothError>;
|
pub type BluetoothResult<T> = Result<T, BluetoothError>;
|
||||||
|
|
||||||
|
pub type BluetoothResponseResult = Result<BluetoothResponse, BluetoothError>;
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub enum BluetoothMethodMsg {
|
pub enum BluetoothRequest {
|
||||||
RequestDevice(RequestDeviceoptions, IpcSender<BluetoothResult<BluetoothDeviceMsg>>),
|
RequestDevice(RequestDeviceoptions, IpcSender<BluetoothResponseResult>),
|
||||||
GATTServerConnect(String, IpcSender<BluetoothResult<bool>>),
|
GATTServerConnect(String, IpcSender<BluetoothResponseResult>),
|
||||||
GATTServerDisconnect(String, IpcSender<BluetoothResult<bool>>),
|
GATTServerDisconnect(String, IpcSender<BluetoothResult<bool>>),
|
||||||
GetPrimaryService(String, String, IpcSender<BluetoothResult<BluetoothServiceMsg>>),
|
GetPrimaryService(String, String, IpcSender<BluetoothResponseResult>),
|
||||||
GetPrimaryServices(String, Option<String>, IpcSender<BluetoothResult<BluetoothServicesMsg>>),
|
GetPrimaryServices(String, Option<String>, IpcSender<BluetoothResponseResult>),
|
||||||
GetIncludedService(String, String, IpcSender<BluetoothResult<BluetoothServiceMsg>>),
|
GetIncludedService(String, String, IpcSender<BluetoothResponseResult>),
|
||||||
GetIncludedServices(String, Option<String>, IpcSender<BluetoothResult<BluetoothServicesMsg>>),
|
GetIncludedServices(String, Option<String>, IpcSender<BluetoothResponseResult>),
|
||||||
GetCharacteristic(String, String, IpcSender<BluetoothResult<BluetoothCharacteristicMsg>>),
|
GetCharacteristic(String, String, IpcSender<BluetoothResponseResult>),
|
||||||
GetCharacteristics(String, Option<String>, IpcSender<BluetoothResult<BluetoothCharacteristicsMsg>>),
|
GetCharacteristics(String, Option<String>, IpcSender<BluetoothResponseResult>),
|
||||||
GetDescriptor(String, String, IpcSender<BluetoothResult<BluetoothDescriptorMsg>>),
|
GetDescriptor(String, String, IpcSender<BluetoothResponseResult>),
|
||||||
GetDescriptors(String, Option<String>, IpcSender<BluetoothResult<BluetoothDescriptorsMsg>>),
|
GetDescriptors(String, Option<String>, IpcSender<BluetoothResponseResult>),
|
||||||
ReadValue(String, IpcSender<BluetoothResult<Vec<u8>>>),
|
ReadValue(String, IpcSender<BluetoothResponseResult>),
|
||||||
WriteValue(String, Vec<u8>, IpcSender<BluetoothResult<bool>>),
|
WriteValue(String, Vec<u8>, IpcSender<BluetoothResponseResult>),
|
||||||
Test(String, IpcSender<BluetoothResult<()>>),
|
Test(String, IpcSender<BluetoothResult<()>>),
|
||||||
Exit,
|
Exit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub enum BluetoothResponse {
|
||||||
|
RequestDevice(BluetoothDeviceMsg),
|
||||||
|
GATTServerConnect(bool),
|
||||||
|
GetPrimaryService(BluetoothServiceMsg),
|
||||||
|
GetPrimaryServices(BluetoothServicesMsg),
|
||||||
|
GetIncludedService(BluetoothServiceMsg),
|
||||||
|
GetIncludedServices(BluetoothServicesMsg),
|
||||||
|
GetCharacteristic(BluetoothCharacteristicMsg),
|
||||||
|
GetCharacteristics(BluetoothCharacteristicsMsg),
|
||||||
|
GetDescriptor(BluetoothDescriptorMsg),
|
||||||
|
GetDescriptors(BluetoothDescriptorsMsg),
|
||||||
|
ReadValue(Vec<u8>),
|
||||||
|
WriteValue(Vec<u8>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait BluetoothResponseListener {
|
||||||
|
fn response(&mut self, response: BluetoothResponseResult);
|
||||||
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
//! `LayoutThread`, and `PaintThread`.
|
//! `LayoutThread`, and `PaintThread`.
|
||||||
|
|
||||||
use backtrace::Backtrace;
|
use backtrace::Backtrace;
|
||||||
use bluetooth_traits::BluetoothMethodMsg;
|
use bluetooth_traits::BluetoothRequest;
|
||||||
use canvas::canvas_paint_thread::CanvasPaintThread;
|
use canvas::canvas_paint_thread::CanvasPaintThread;
|
||||||
use canvas::webgl_paint_thread::WebGLPaintThread;
|
use canvas::webgl_paint_thread::WebGLPaintThread;
|
||||||
use canvas_traits::CanvasMsg;
|
use canvas_traits::CanvasMsg;
|
||||||
|
@ -121,7 +121,7 @@ pub struct Constellation<Message, LTF, STF> {
|
||||||
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||||
|
|
||||||
/// A channel through which messages can be sent to the bluetooth thread.
|
/// A channel through which messages can be sent to the bluetooth thread.
|
||||||
bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
bluetooth_thread: IpcSender<BluetoothRequest>,
|
||||||
|
|
||||||
/// Sender to Service Worker Manager thread
|
/// Sender to Service Worker Manager thread
|
||||||
swmanager_chan: Option<IpcSender<ServiceWorkerMsg>>,
|
swmanager_chan: Option<IpcSender<ServiceWorkerMsg>>,
|
||||||
|
@ -199,7 +199,7 @@ pub struct InitialConstellationState {
|
||||||
/// A channel to the developer tools, if applicable.
|
/// A channel to the developer tools, if applicable.
|
||||||
pub devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
pub devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||||
/// A channel to the bluetooth thread.
|
/// A channel to the bluetooth thread.
|
||||||
pub bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
pub bluetooth_thread: IpcSender<BluetoothRequest>,
|
||||||
/// A channel to the image cache thread.
|
/// A channel to the image cache thread.
|
||||||
pub image_cache_thread: ImageCacheThread,
|
pub image_cache_thread: ImageCacheThread,
|
||||||
/// A channel to the font cache thread.
|
/// A channel to the font cache thread.
|
||||||
|
@ -1095,7 +1095,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Exiting bluetooth thread.");
|
debug!("Exiting bluetooth thread.");
|
||||||
if let Err(e) = self.bluetooth_thread.send(BluetoothMethodMsg::Exit) {
|
if let Err(e) = self.bluetooth_thread.send(BluetoothRequest::Exit) {
|
||||||
warn!("Exit bluetooth thread failed ({})", e);
|
warn!("Exit bluetooth thread failed ({})", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use bluetooth_traits::BluetoothMethodMsg;
|
use bluetooth_traits::BluetoothRequest;
|
||||||
use compositing::CompositionPipeline;
|
use compositing::CompositionPipeline;
|
||||||
use compositing::CompositorProxy;
|
use compositing::CompositorProxy;
|
||||||
use compositing::compositor_thread::Msg as CompositorMsg;
|
use compositing::compositor_thread::Msg as CompositorMsg;
|
||||||
|
@ -94,7 +94,7 @@ pub struct InitialPipelineState {
|
||||||
/// A channel to the developer tools, if applicable.
|
/// A channel to the developer tools, if applicable.
|
||||||
pub devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
pub devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||||
/// A channel to the bluetooth thread.
|
/// A channel to the bluetooth thread.
|
||||||
pub bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
pub bluetooth_thread: IpcSender<BluetoothRequest>,
|
||||||
/// A channel to the service worker manager thread
|
/// A channel to the service worker manager thread
|
||||||
pub swmanager_thread: IpcSender<SWManagerMsg>,
|
pub swmanager_thread: IpcSender<SWManagerMsg>,
|
||||||
/// A channel to the image cache thread.
|
/// A channel to the image cache thread.
|
||||||
|
@ -384,7 +384,7 @@ pub struct UnprivilegedPipelineContent {
|
||||||
layout_to_constellation_chan: IpcSender<LayoutMsg>,
|
layout_to_constellation_chan: IpcSender<LayoutMsg>,
|
||||||
scheduler_chan: IpcSender<TimerEventRequest>,
|
scheduler_chan: IpcSender<TimerEventRequest>,
|
||||||
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
||||||
bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
bluetooth_thread: IpcSender<BluetoothRequest>,
|
||||||
swmanager_thread: IpcSender<SWManagerMsg>,
|
swmanager_thread: IpcSender<SWManagerMsg>,
|
||||||
image_cache_thread: ImageCacheThread,
|
image_cache_thread: ImageCacheThread,
|
||||||
font_cache_thread: FontCacheThread,
|
font_cache_thread: FontCacheThread,
|
||||||
|
|
|
@ -10,6 +10,7 @@ name = "net_traits"
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
bluetooth_traits = {path = "../bluetooth_traits"}
|
||||||
util = {path = "../util"}
|
util = {path = "../util"}
|
||||||
msg = {path = "../msg"}
|
msg = {path = "../msg"}
|
||||||
ipc-channel = "0.5"
|
ipc-channel = "0.5"
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#![deny(unsafe_code)]
|
#![deny(unsafe_code)]
|
||||||
|
|
||||||
|
extern crate bluetooth_traits;
|
||||||
extern crate cookie as cookie_rs;
|
extern crate cookie as cookie_rs;
|
||||||
extern crate heapsize;
|
extern crate heapsize;
|
||||||
#[macro_use] extern crate heapsize_derive;
|
#[macro_use] extern crate heapsize_derive;
|
||||||
|
@ -32,6 +33,7 @@ extern crate uuid;
|
||||||
extern crate webrender_traits;
|
extern crate webrender_traits;
|
||||||
extern crate websocket;
|
extern crate websocket;
|
||||||
|
|
||||||
|
use bluetooth_traits::{BluetoothResponseListener, BluetoothResponseResult};
|
||||||
use cookie_rs::Cookie;
|
use cookie_rs::Cookie;
|
||||||
use filemanager_thread::FileManagerThreadMsg;
|
use filemanager_thread::FileManagerThreadMsg;
|
||||||
use heapsize::HeapSizeOf;
|
use heapsize::HeapSizeOf;
|
||||||
|
@ -291,6 +293,13 @@ impl<T: FetchResponseListener> Action<T> for FetchResponseMsg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: BluetoothResponseListener> Action<T> for BluetoothResponseResult {
|
||||||
|
/// Execute the default action on a provided listener.
|
||||||
|
fn process(self, listener: &mut T) {
|
||||||
|
listener.response(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A wrapper for a network load that can either be channel or event-based.
|
/// A wrapper for a network load that can either be channel or event-based.
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub enum LoadConsumer {
|
pub enum LoadConsumer {
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at 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::blacklist::{Blacklist, uuid_is_blacklisted};
|
||||||
use bluetooth_traits::scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence};
|
use bluetooth_traits::scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence};
|
||||||
use bluetooth_traits::scanfilter::{RequestDeviceoptions, ServiceUUIDSequence};
|
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::Error::{self, NotFound, Security, Type};
|
||||||
use dom::bindings::error::Fallible;
|
use dom::bindings::error::Fallible;
|
||||||
use dom::bindings::js::{JS, MutHeap, Root};
|
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::reflector::{Reflectable, Reflector, reflect_dom_object};
|
||||||
use dom::bindings::str::DOMString;
|
use dom::bindings::str::DOMString;
|
||||||
use dom::bluetoothadvertisingdata::BluetoothAdvertisingData;
|
use dom::bluetoothadvertisingdata::BluetoothAdvertisingData;
|
||||||
|
@ -24,9 +26,12 @@ use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID};
|
||||||
use dom::globalscope::GlobalScope;
|
use dom::globalscope::GlobalScope;
|
||||||
use dom::promise::Promise;
|
use dom::promise::Promise;
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
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::collections::HashMap;
|
||||||
use std::rc::Rc;
|
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_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.";
|
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.
|
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.";
|
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
|
// https://webbluetoothcg.github.io/web-bluetooth/#bluetooth
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct Bluetooth {
|
pub struct Bluetooth {
|
||||||
|
@ -83,75 +115,55 @@ impl Bluetooth {
|
||||||
&self.descriptor_instance_map
|
&self.descriptor_instance_map
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothMethodMsg> {
|
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
|
||||||
self.global().as_window().bluetooth_thread()
|
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
|
// https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices
|
||||||
fn request_bluetooth_devices(&self,
|
fn request_bluetooth_devices(&self,
|
||||||
|
p: &Rc<Promise>,
|
||||||
filters: &Option<Vec<BluetoothRequestDeviceFilter>>,
|
filters: &Option<Vec<BluetoothRequestDeviceFilter>>,
|
||||||
optional_services: &Option<Vec<BluetoothServiceUUID>>)
|
optional_services: &Option<Vec<BluetoothServiceUUID>>) {
|
||||||
-> Fallible<Root<BluetoothDevice>> {
|
|
||||||
// TODO: Step 1: Triggered by user activation.
|
// TODO: Step 1: Triggered by user activation.
|
||||||
|
|
||||||
// Step 2.
|
// 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.
|
// TODO: Step 3-5: Implement the permission API.
|
||||||
|
|
||||||
// Note: Steps 6-8 are implemented in
|
// Note: Steps 6-8 are implemented in
|
||||||
// components/net/bluetooth_thread.rs in request_device function.
|
// components/net/bluetooth_thread.rs in request_device function.
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
let sender = response_async(p, self);
|
||||||
self.get_bluetooth_thread().send(BluetoothMethodMsg::RequestDevice(option, sender)).unwrap();
|
self.get_bluetooth_thread().send(BluetoothRequest::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))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices
|
||||||
fn convert_request_device_options(filters: &Option<Vec<BluetoothRequestDeviceFilter>>,
|
fn convert_request_device_options(filters: &Option<Vec<BluetoothRequestDeviceFilter>>,
|
||||||
optional_services: &Option<Vec<BluetoothServiceUUID>>)
|
optional_services: &Option<Vec<BluetoothServiceUUID>>)
|
||||||
|
@ -300,18 +312,6 @@ fn canonicalize_filter(filter: &BluetoothRequestDeviceFilter) -> Fallible<Blueto
|
||||||
service_data_uuid))
|
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 {
|
impl From<BluetoothError> for Error {
|
||||||
fn from(error: BluetoothError) -> Self {
|
fn from(error: BluetoothError) -> Self {
|
||||||
match error {
|
match error {
|
||||||
|
@ -329,6 +329,45 @@ impl BluetoothMethods for Bluetooth {
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice
|
||||||
fn RequestDevice(&self, option: &RequestDeviceOptions) -> Rc<Promise> {
|
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())),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use bluetooth_traits::BluetoothMethodMsg;
|
use bluetooth_traits::{BluetoothRequest, BluetoothResponse};
|
||||||
use bluetooth_traits::blacklist::{Blacklist, uuid_is_blacklisted};
|
use bluetooth_traits::blacklist::{Blacklist, uuid_is_blacklisted};
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::BluetoothCharacteristicPropertiesBinding::
|
use dom::bindings::codegen::Bindings::BluetoothCharacteristicPropertiesBinding::
|
||||||
|
@ -13,19 +13,19 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding::
|
||||||
BluetoothRemoteGATTCharacteristicMethods;
|
BluetoothRemoteGATTCharacteristicMethods;
|
||||||
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
|
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
|
||||||
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
|
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::error::Error::{self, InvalidModification, Network, NotSupported, Security};
|
||||||
use dom::bindings::js::{JS, MutHeap, Root};
|
use dom::bindings::js::{JS, MutHeap, Root};
|
||||||
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
|
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
|
||||||
use dom::bindings::str::{ByteString, DOMString};
|
use dom::bindings::str::{ByteString, DOMString};
|
||||||
use dom::bluetooth::result_to_promise;
|
use dom::bluetooth::{AsyncBluetoothListener, response_async};
|
||||||
use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties;
|
use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties;
|
||||||
use dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor;
|
use dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor;
|
||||||
use dom::bluetoothremotegattservice::BluetoothRemoteGATTService;
|
use dom::bluetoothremotegattservice::BluetoothRemoteGATTService;
|
||||||
use dom::bluetoothuuid::{BluetoothDescriptorUUID, BluetoothUUID};
|
use dom::bluetoothuuid::{BluetoothDescriptorUUID, BluetoothUUID};
|
||||||
use dom::globalscope::GlobalScope;
|
use dom::globalscope::GlobalScope;
|
||||||
use dom::promise::Promise;
|
use dom::promise::Promise;
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::IpcSender;
|
||||||
|
use js::jsapi::JSContext;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
// Maximum length of an attribute value.
|
// Maximum length of an attribute value.
|
||||||
|
@ -73,150 +73,13 @@ impl BluetoothRemoteGATTCharacteristic {
|
||||||
BluetoothRemoteGATTCharacteristicBinding::Wrap)
|
BluetoothRemoteGATTCharacteristicBinding::Wrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothMethodMsg> {
|
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
|
||||||
self.global().as_window().bluetooth_thread()
|
self.global().as_window().bluetooth_thread()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_instance_id(&self) -> String {
|
fn get_instance_id(&self) -> String {
|
||||||
self.instance_id.clone()
|
self.instance_id.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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();
|
|
||||||
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
|
|
||||||
return Err(Security)
|
|
||||||
}
|
|
||||||
if !self.Service().Device().Gatt().Connected() {
|
|
||||||
return Err(Network)
|
|
||||||
}
|
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
|
||||||
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))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors
|
|
||||||
fn get_descriptors(&self,
|
|
||||||
descriptor: Option<BluetoothDescriptorUUID>)
|
|
||||||
-> Fallible<Vec<Root<BluetoothRemoteGATTDescriptor>>> {
|
|
||||||
let mut uuid: Option<String> = None;
|
|
||||||
if let Some(d) = descriptor {
|
|
||||||
uuid = Some(try!(BluetoothUUID::descriptor(d)).to_string());
|
|
||||||
if let Some(ref uuid) = uuid {
|
|
||||||
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
|
|
||||||
return Err(Security)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if !self.Service().Device().Gatt().Connected() {
|
|
||||||
return Err(Network)
|
|
||||||
}
|
|
||||||
let mut descriptors = vec!();
|
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
|
||||||
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))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-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.Service().Device().Gatt().Connected() {
|
|
||||||
return Err(Network)
|
|
||||||
}
|
|
||||||
if !self.Properties().Read() {
|
|
||||||
return Err(NotSupported)
|
|
||||||
}
|
|
||||||
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-bluetoothremotegattcharacteristic-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.Service().Device().Gatt().Connected() {
|
|
||||||
return Err(Network)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !(self.Properties().Write() ||
|
|
||||||
self.Properties().WriteWithoutResponse() ||
|
|
||||||
self.Properties().AuthenticatedSignedWrites()) {
|
|
||||||
return Err(NotSupported)
|
|
||||||
}
|
|
||||||
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 BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteristic {
|
impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteristic {
|
||||||
|
@ -238,7 +101,27 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor
|
||||||
fn GetDescriptor(&self, descriptor: BluetoothDescriptorUUID) -> Rc<Promise> {
|
fn GetDescriptor(&self, descriptor: BluetoothDescriptorUUID) -> Rc<Promise> {
|
||||||
result_to_promise(&self.global(), self.get_descriptor(descriptor))
|
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) {
|
||||||
|
p.reject_error(p_cx, Security);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
if !self.Service().Device().Gatt().Connected() {
|
||||||
|
p.reject_error(p_cx, Network);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
let sender = response_async(&p, self);
|
||||||
|
self.get_bluetooth_thread().send(
|
||||||
|
BluetoothRequest::GetDescriptor(self.get_instance_id(), uuid, sender)).unwrap();
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
|
@ -246,7 +129,32 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
|
||||||
fn GetDescriptors(&self,
|
fn GetDescriptors(&self,
|
||||||
descriptor: Option<BluetoothDescriptorUUID>)
|
descriptor: Option<BluetoothDescriptorUUID>)
|
||||||
-> Rc<Promise> {
|
-> Rc<Promise> {
|
||||||
result_to_promise(&self.global(), self.get_descriptors(descriptor))
|
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 = 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) {
|
||||||
|
p.reject_error(p_cx, Security);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if !self.Service().Device().Gatt().Connected() {
|
||||||
|
p.reject_error(p_cx, Network);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
let sender = response_async(&p, self);
|
||||||
|
self.get_bluetooth_thread().send(
|
||||||
|
BluetoothRequest::GetDescriptors(self.get_instance_id(), uuid, sender)).unwrap();
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-value
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-value
|
||||||
|
@ -257,12 +165,105 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue
|
||||||
fn ReadValue(&self) -> Rc<Promise> {
|
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.Service().Device().Gatt().Connected() {
|
||||||
|
p.reject_error(p_cx, Network);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
if !self.Properties().Read() {
|
||||||
|
p.reject_error(p_cx, NotSupported);
|
||||||
|
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)]
|
#[allow(unrooted_must_root)]
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue
|
||||||
fn WriteValue(&self, value: Vec<u8>) -> Rc<Promise> {
|
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.Service().Device().Gatt().Connected() {
|
||||||
|
p.reject_error(p_cx, Network);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !(self.Properties().Write() ||
|
||||||
|
self.Properties().WriteWithoutResponse() ||
|
||||||
|
self.Properties().AuthenticatedSignedWrites()) {
|
||||||
|
p.reject_error(p_cx, NotSupported);
|
||||||
|
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 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())),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use bluetooth_traits::BluetoothMethodMsg;
|
use bluetooth_traits::{BluetoothRequest, BluetoothResponse};
|
||||||
use bluetooth_traits::blacklist::{Blacklist, uuid_is_blacklisted};
|
use bluetooth_traits::blacklist::{Blacklist, uuid_is_blacklisted};
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
|
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::BluetoothRemoteGATTDescriptorBinding::BluetoothRemoteGATTDescriptorMethods;
|
||||||
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
|
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
|
||||||
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
|
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::error::Error::{self, InvalidModification, Network, Security};
|
||||||
use dom::bindings::js::{JS, MutHeap, Root};
|
use dom::bindings::js::{JS, MutHeap, Root};
|
||||||
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
|
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
|
||||||
use dom::bindings::str::{ByteString, DOMString};
|
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::bluetoothremotegattcharacteristic::{BluetoothRemoteGATTCharacteristic, MAXIMUM_ATTRIBUTE_LENGTH};
|
||||||
use dom::globalscope::GlobalScope;
|
use dom::globalscope::GlobalScope;
|
||||||
use dom::promise::Promise;
|
use dom::promise::Promise;
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::IpcSender;
|
||||||
|
use js::jsapi::JSContext;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
// http://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattdescriptor
|
// http://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattdescriptor
|
||||||
|
@ -60,60 +60,13 @@ impl BluetoothRemoteGATTDescriptor {
|
||||||
BluetoothRemoteGATTDescriptorBinding::Wrap)
|
BluetoothRemoteGATTDescriptorBinding::Wrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothMethodMsg> {
|
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
|
||||||
self.global().as_window().bluetooth_thread()
|
self.global().as_window().bluetooth_thread()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_instance_id(&self) -> String {
|
fn get_instance_id(&self) -> String {
|
||||||
self.instance_id.clone()
|
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 {
|
impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
|
||||||
|
@ -135,12 +88,60 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue
|
||||||
fn ReadValue(&self) -> Rc<Promise> {
|
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)]
|
#[allow(unrooted_must_root)]
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue
|
||||||
fn WriteValue(&self, value: Vec<u8>) -> Rc<Promise> {
|
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())),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,23 +2,24 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use bluetooth_traits::BluetoothMethodMsg;
|
use bluetooth_traits::{BluetoothRequest, BluetoothResponse};
|
||||||
use bluetooth_traits::blacklist::{Blacklist, uuid_is_blacklisted};
|
use bluetooth_traits::blacklist::{Blacklist, uuid_is_blacklisted};
|
||||||
use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
|
use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
|
||||||
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding;
|
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding;
|
||||||
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
|
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::Error::{self, Network, Security};
|
||||||
|
use dom::bindings::error::ErrorResult;
|
||||||
use dom::bindings::js::{JS, MutHeap, Root};
|
use dom::bindings::js::{JS, MutHeap, Root};
|
||||||
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
|
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
|
||||||
use dom::bindings::str::DOMString;
|
use dom::bindings::str::DOMString;
|
||||||
use dom::bluetooth::result_to_promise;
|
use dom::bluetooth::{AsyncBluetoothListener, response_async};
|
||||||
use dom::bluetoothdevice::BluetoothDevice;
|
use dom::bluetoothdevice::BluetoothDevice;
|
||||||
use dom::bluetoothremotegattservice::BluetoothRemoteGATTService;
|
use dom::bluetoothremotegattservice::BluetoothRemoteGATTService;
|
||||||
use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID};
|
use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID};
|
||||||
use dom::globalscope::GlobalScope;
|
use dom::globalscope::GlobalScope;
|
||||||
use dom::promise::Promise;
|
use dom::promise::Promise;
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
|
use js::jsapi::JSContext;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
@ -45,109 +46,9 @@ impl BluetoothRemoteGATTServer {
|
||||||
BluetoothRemoteGATTServerBinding::Wrap)
|
BluetoothRemoteGATTServerBinding::Wrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothMethodMsg> {
|
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
|
||||||
self.global().as_window().bluetooth_thread()
|
self.global().as_window().bluetooth_thread()
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect
|
|
||||||
fn connect(&self) -> Fallible<Root<BluetoothRemoteGATTServer>> {
|
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
|
||||||
self.get_bluetooth_thread().send(
|
|
||||||
BluetoothMethodMsg::GATTServerConnect(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))
|
|
||||||
},
|
|
||||||
Err(error) => {
|
|
||||||
Err(Error::from(error))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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();
|
|
||||||
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
|
|
||||||
return Err(Security)
|
|
||||||
}
|
|
||||||
if !self.Device().Gatt().Connected() {
|
|
||||||
return Err(Network)
|
|
||||||
}
|
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
|
||||||
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))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices
|
|
||||||
fn get_primary_services(&self,
|
|
||||||
service: Option<BluetoothServiceUUID>)
|
|
||||||
-> Fallible<Vec<Root<BluetoothRemoteGATTService>>> {
|
|
||||||
let mut uuid: Option<String> = None;
|
|
||||||
if let Some(s) = service {
|
|
||||||
uuid = Some(try!(BluetoothUUID::service(s)).to_string());
|
|
||||||
if let Some(ref uuid) = uuid {
|
|
||||||
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
|
|
||||||
return Err(Security)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if !self.Device().Gatt().Connected() {
|
|
||||||
return Err(Network)
|
|
||||||
}
|
|
||||||
let mut services = vec!();
|
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
|
||||||
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) => {
|
|
||||||
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(),
|
|
||||||
None => {
|
|
||||||
BluetoothRemoteGATTService::new(&self.global(),
|
|
||||||
&self.device.get(),
|
|
||||||
DOMString::from(service.uuid),
|
|
||||||
service.is_primary,
|
|
||||||
service.instance_id.clone())
|
|
||||||
},
|
|
||||||
};
|
|
||||||
if !service_map.contains_key(&service.instance_id) {
|
|
||||||
service_map.insert(service.instance_id, MutHeap::new(&bt_service));
|
|
||||||
}
|
|
||||||
services.push(bt_service);
|
|
||||||
}
|
|
||||||
Ok(services)
|
|
||||||
},
|
|
||||||
Err(error) => {
|
|
||||||
Err(Error::from(error))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
|
impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
|
||||||
|
@ -164,14 +65,18 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect
|
||||||
fn Connect(&self) -> Rc<Promise> {
|
fn Connect(&self) -> Rc<Promise> {
|
||||||
result_to_promise(&self.global(), self.connect())
|
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
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-disconnect
|
||||||
fn Disconnect(&self) -> ErrorResult {
|
fn Disconnect(&self) -> ErrorResult {
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
let (sender, receiver) = ipc::channel().unwrap();
|
||||||
self.get_bluetooth_thread().send(
|
self.get_bluetooth_thread().send(
|
||||||
BluetoothMethodMsg::GATTServerDisconnect(String::from(self.Device().Id()), sender)).unwrap();
|
BluetoothRequest::GATTServerDisconnect(String::from(self.Device().Id()), sender)).unwrap();
|
||||||
let server = receiver.recv().unwrap();
|
let server = receiver.recv().unwrap();
|
||||||
match server {
|
match server {
|
||||||
Ok(connected) => {
|
Ok(connected) => {
|
||||||
|
@ -187,14 +92,105 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice
|
||||||
fn GetPrimaryService(&self, service: BluetoothServiceUUID) -> Rc<Promise> {
|
fn GetPrimaryService(&self, service: BluetoothServiceUUID) -> Rc<Promise> {
|
||||||
result_to_promise(&self.global(), self.get_primary_service(service))
|
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) {
|
||||||
|
p.reject_error(p_cx, Security);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
if !self.Device().Gatt().Connected() {
|
||||||
|
p.reject_error(p_cx, Network);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
let sender = response_async(&p, self);
|
||||||
|
self.get_bluetooth_thread().send(
|
||||||
|
BluetoothRequest::GetPrimaryService(String::from(self.Device().Id()), uuid, sender)).unwrap();
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices
|
||||||
fn GetPrimaryServices(&self,
|
fn GetPrimaryServices(&self, service: Option<BluetoothServiceUUID>) -> Rc<Promise> {
|
||||||
service: Option<BluetoothServiceUUID>)
|
let p = Promise::new(&self.global());
|
||||||
-> Rc<Promise> {
|
let p_cx = p.global().get_cx();
|
||||||
result_to_promise(&self.global(), self.get_primary_services(service))
|
let mut uuid: Option<String> = None;
|
||||||
|
if let Some(s) = service {
|
||||||
|
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) {
|
||||||
|
p.reject_error(p_cx, Security);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if !self.Device().Gatt().Connected() {
|
||||||
|
p.reject_error(p_cx, Network);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
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<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 services_vec {
|
||||||
|
let bt_service = match service_map.get(&service.instance_id) {
|
||||||
|
Some(existing_service) => existing_service.get(),
|
||||||
|
None => {
|
||||||
|
BluetoothRemoteGATTService::new(&self.global(),
|
||||||
|
&self.device.get(),
|
||||||
|
DOMString::from(service.uuid),
|
||||||
|
service.is_primary,
|
||||||
|
service.instance_id.clone())
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if !service_map.contains_key(&service.instance_id) {
|
||||||
|
service_map.insert(service.instance_id, MutHeap::new(&bt_service));
|
||||||
|
}
|
||||||
|
services.push(bt_service);
|
||||||
|
}
|
||||||
|
promise.resolve_native(promise_cx, &services);
|
||||||
|
},
|
||||||
|
_ => promise.reject_error(promise_cx, Error::Type("Something went wrong...".to_owned())),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,25 +2,25 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use bluetooth_traits::BluetoothMethodMsg;
|
use bluetooth_traits::{BluetoothRequest, BluetoothResponse};
|
||||||
use bluetooth_traits::blacklist::{Blacklist, uuid_is_blacklisted};
|
use bluetooth_traits::blacklist::{Blacklist, uuid_is_blacklisted};
|
||||||
use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
|
use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
|
||||||
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
|
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
|
||||||
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding;
|
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding;
|
||||||
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
|
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
|
||||||
use dom::bindings::error::Error::{self, Network, Security};
|
use dom::bindings::error::Error::{self, Network, Security};
|
||||||
use dom::bindings::error::Fallible;
|
|
||||||
use dom::bindings::js::{JS, MutHeap, Root};
|
use dom::bindings::js::{JS, MutHeap, Root};
|
||||||
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
|
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
|
||||||
use dom::bindings::str::DOMString;
|
use dom::bindings::str::DOMString;
|
||||||
use dom::bluetooth::result_to_promise;
|
use dom::bluetooth::{AsyncBluetoothListener, response_async};
|
||||||
use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties;
|
use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties;
|
||||||
use dom::bluetoothdevice::BluetoothDevice;
|
use dom::bluetoothdevice::BluetoothDevice;
|
||||||
use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic;
|
use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic;
|
||||||
use dom::bluetoothuuid::{BluetoothCharacteristicUUID, BluetoothServiceUUID, BluetoothUUID};
|
use dom::bluetoothuuid::{BluetoothCharacteristicUUID, BluetoothServiceUUID, BluetoothUUID};
|
||||||
use dom::globalscope::GlobalScope;
|
use dom::globalscope::GlobalScope;
|
||||||
use dom::promise::Promise;
|
use dom::promise::Promise;
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::IpcSender;
|
||||||
|
use js::jsapi::JSContext;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattservice
|
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattservice
|
||||||
|
@ -66,87 +66,192 @@ impl BluetoothRemoteGATTService {
|
||||||
self.device.get()
|
self.device.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothMethodMsg> {
|
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
|
||||||
self.global().as_window().bluetooth_thread()
|
self.global().as_window().bluetooth_thread()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_instance_id(&self) -> String {
|
fn get_instance_id(&self) -> String {
|
||||||
self.instance_id.clone()
|
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
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic
|
||||||
fn get_characteristic(&self,
|
fn GetCharacteristic(&self,
|
||||||
characteristic: BluetoothCharacteristicUUID)
|
characteristic: BluetoothCharacteristicUUID)
|
||||||
-> Fallible<Root<BluetoothRemoteGATTCharacteristic>> {
|
-> Rc<Promise> {
|
||||||
let uuid = try!(BluetoothUUID::characteristic(characteristic)).to_string();
|
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) {
|
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() {
|
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(
|
self.get_bluetooth_thread().send(
|
||||||
BluetoothMethodMsg::GetCharacteristic(self.get_instance_id(), uuid, sender)).unwrap();
|
BluetoothRequest::GetCharacteristic(self.get_instance_id(), uuid, sender)).unwrap();
|
||||||
let characteristic = receiver.recv().unwrap();
|
return p;
|
||||||
match characteristic {
|
}
|
||||||
Ok(characteristic) => {
|
|
||||||
|
#[allow(unrooted_must_root)]
|
||||||
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics
|
||||||
|
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 = 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) {
|
||||||
|
p.reject_error(p_cx, Security);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if !self.Device().Gatt().Connected() {
|
||||||
|
p.reject_error(p_cx, Network);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
let sender = response_async(&p, self);
|
||||||
|
self.get_bluetooth_thread().send(
|
||||||
|
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 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) {
|
||||||
|
p.reject_error(p_cx, Security);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
if !self.Device().Gatt().Connected() {
|
||||||
|
p.reject_error(p_cx, Network);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
let sender = response_async(&p, self);
|
||||||
|
self.get_bluetooth_thread().send(
|
||||||
|
BluetoothRequest::GetIncludedService(self.get_instance_id(),
|
||||||
|
uuid,
|
||||||
|
sender)).unwrap();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[allow(unrooted_must_root)]
|
||||||
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices
|
||||||
|
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 = 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) {
|
||||||
|
p.reject_error(p_cx, Security);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if !self.Device().Gatt().Connected() {
|
||||||
|
p.reject_error(p_cx, Network);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
let sender = response_async(&p, self);
|
||||||
|
self.get_bluetooth_thread().send(
|
||||||
|
BluetoothRequest::GetIncludedServices(self.get_instance_id(),
|
||||||
|
uuid,
|
||||||
|
sender)).unwrap();
|
||||||
|
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 context = self.device.get().get_context();
|
||||||
let mut characteristic_map = context.get_characteristic_map().borrow_mut();
|
let mut characteristic_map = context.get_characteristic_map().borrow_mut();
|
||||||
if let Some(existing_characteristic) = characteristic_map.get(&characteristic.instance_id) {
|
if let Some(existing_characteristic) = characteristic_map.get(&characteristic.instance_id) {
|
||||||
return Ok(existing_characteristic.get());
|
return promise.resolve_native(promise_cx, &existing_characteristic.get());
|
||||||
}
|
}
|
||||||
let global = self.global();
|
let properties =
|
||||||
let properties = BluetoothCharacteristicProperties::new(&global,
|
BluetoothCharacteristicProperties::new(&self.global(),
|
||||||
characteristic.broadcast,
|
characteristic.broadcast,
|
||||||
characteristic.read,
|
characteristic.read,
|
||||||
characteristic.write_without_response,
|
characteristic.write_without_response,
|
||||||
characteristic.write,
|
characteristic.write,
|
||||||
characteristic.notify,
|
characteristic.notify,
|
||||||
characteristic.indicate,
|
characteristic.indicate,
|
||||||
characteristic.authenticated_signed_writes,
|
characteristic.authenticated_signed_writes,
|
||||||
characteristic.reliable_write,
|
characteristic.reliable_write,
|
||||||
characteristic.writable_auxiliaries);
|
characteristic.writable_auxiliaries);
|
||||||
let bt_characteristic = BluetoothRemoteGATTCharacteristic::new(&global,
|
let bt_characteristic = BluetoothRemoteGATTCharacteristic::new(&self.global(),
|
||||||
self,
|
self,
|
||||||
DOMString::from(characteristic.uuid),
|
DOMString::from(characteristic.uuid),
|
||||||
&properties,
|
&properties,
|
||||||
characteristic.instance_id.clone());
|
characteristic.instance_id.clone());
|
||||||
characteristic_map.insert(characteristic.instance_id, MutHeap::new(&bt_characteristic));
|
characteristic_map.insert(characteristic.instance_id, MutHeap::new(&bt_characteristic));
|
||||||
Ok(bt_characteristic)
|
promise.resolve_native(promise_cx, &bt_characteristic);
|
||||||
},
|
},
|
||||||
Err(error) => {
|
BluetoothResponse::GetCharacteristics(characteristics_vec) => {
|
||||||
Err(Error::from(error))
|
let mut characteristics = vec!();
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics
|
|
||||||
fn get_characteristics(&self,
|
|
||||||
characteristic: Option<BluetoothCharacteristicUUID>)
|
|
||||||
-> Fallible<Vec<Root<BluetoothRemoteGATTCharacteristic>>> {
|
|
||||||
let mut uuid: Option<String> = None;
|
|
||||||
if let Some(c) = characteristic {
|
|
||||||
uuid = Some(try!(BluetoothUUID::characteristic(c)).to_string());
|
|
||||||
if let Some(ref uuid) = uuid {
|
|
||||||
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
|
|
||||||
return Err(Security)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if !self.Device().Gatt().Connected() {
|
|
||||||
return Err(Network)
|
|
||||||
}
|
|
||||||
let mut characteristics = vec!();
|
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
|
||||||
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 context = self.device.get().get_context();
|
||||||
let mut characteristic_map = context.get_characteristic_map().borrow_mut();
|
let mut characteristic_map = context.get_characteristic_map().borrow_mut();
|
||||||
for characteristic in characteristic_vec {
|
for characteristic in characteristics_vec {
|
||||||
let bt_characteristic = match characteristic_map.get(&characteristic.instance_id) {
|
let bt_characteristic = match characteristic_map.get(&characteristic.instance_id) {
|
||||||
Some(existing_characteristic) => existing_characteristic.get(),
|
Some(existing_characteristic) => existing_characteristic.get(),
|
||||||
None => {
|
None => {
|
||||||
|
@ -174,149 +279,29 @@ impl BluetoothRemoteGATTService {
|
||||||
}
|
}
|
||||||
characteristics.push(bt_characteristic);
|
characteristics.push(bt_characteristic);
|
||||||
}
|
}
|
||||||
Ok(characteristics)
|
promise.resolve_native(promise_cx, &characteristics);
|
||||||
},
|
},
|
||||||
Err(error) => {
|
BluetoothResponse::GetIncludedService(service) => {
|
||||||
Err(Error::from(error))
|
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);
|
||||||
},
|
},
|
||||||
}
|
BluetoothResponse::GetIncludedServices(services_vec) => {
|
||||||
}
|
let s: Vec<Root<BluetoothRemoteGATTService>> =
|
||||||
|
services_vec.into_iter()
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservice
|
.map(|service| BluetoothRemoteGATTService::new(&self.global(),
|
||||||
fn get_included_service(&self,
|
&self.device.get(),
|
||||||
service: BluetoothServiceUUID)
|
DOMString::from(service.uuid),
|
||||||
-> Fallible<Root<BluetoothRemoteGATTService>> {
|
service.is_primary,
|
||||||
let uuid = try!(BluetoothUUID::service(service)).to_string();
|
service.instance_id))
|
||||||
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
|
.collect();
|
||||||
return Err(Security)
|
promise.resolve_native(promise_cx, &s);
|
||||||
}
|
|
||||||
if !self.Device().Gatt().Connected() {
|
|
||||||
return Err(Network)
|
|
||||||
}
|
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
|
||||||
self.get_bluetooth_thread().send(
|
|
||||||
BluetoothMethodMsg::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))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices
|
|
||||||
fn get_included_services(&self,
|
|
||||||
service: Option<BluetoothServiceUUID>)
|
|
||||||
-> Fallible<Vec<Root<BluetoothRemoteGATTService>>> {
|
|
||||||
let mut uuid: Option<String> = None;
|
|
||||||
if let Some(s) = service {
|
|
||||||
uuid = Some(try!(BluetoothUUID::service(s)).to_string());
|
|
||||||
if let Some(ref uuid) = uuid {
|
|
||||||
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
|
|
||||||
return Err(Security)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if !self.Device().Gatt().Connected() {
|
|
||||||
return Err(Network)
|
|
||||||
}
|
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
|
||||||
self.get_bluetooth_thread().send(
|
|
||||||
BluetoothMethodMsg::GetIncludedServices(self.get_instance_id(),
|
|
||||||
uuid,
|
|
||||||
sender)).unwrap();
|
|
||||||
let services_vec = receiver.recv().unwrap();
|
|
||||||
let mut services = vec!();
|
|
||||||
match services_vec {
|
|
||||||
Ok(service_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(),
|
|
||||||
None => {
|
|
||||||
BluetoothRemoteGATTService::new(&self.global(),
|
|
||||||
&self.device.get(),
|
|
||||||
DOMString::from(service.uuid),
|
|
||||||
service.is_primary,
|
|
||||||
service.instance_id.clone())
|
|
||||||
},
|
|
||||||
};
|
|
||||||
if !service_map.contains_key(&service.instance_id) {
|
|
||||||
service_map.insert(service.instance_id, MutHeap::new(&bt_service));
|
|
||||||
}
|
|
||||||
services.push(bt_service);
|
|
||||||
}
|
|
||||||
Ok(services)
|
|
||||||
},
|
|
||||||
Err(error) => {
|
|
||||||
Err(Error::from(error))
|
|
||||||
},
|
},
|
||||||
|
_ => 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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at 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;
|
||||||
use dom::bindings::codegen::Bindings::TestRunnerBinding::TestRunnerMethods;
|
use dom::bindings::codegen::Bindings::TestRunnerBinding::TestRunnerMethods;
|
||||||
use dom::bindings::error::{Error, ErrorResult};
|
use dom::bindings::error::{Error, ErrorResult};
|
||||||
|
@ -31,7 +31,7 @@ impl TestRunner {
|
||||||
TestRunnerBinding::Wrap)
|
TestRunnerBinding::Wrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothMethodMsg> {
|
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
|
||||||
self.global().as_window().bluetooth_thread()
|
self.global().as_window().bluetooth_thread()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ impl TestRunnerMethods for TestRunner {
|
||||||
// https://webbluetoothcg.github.io/web-bluetooth/tests#setBluetoothMockDataSet
|
// https://webbluetoothcg.github.io/web-bluetooth/tests#setBluetoothMockDataSet
|
||||||
fn SetBluetoothMockDataSet(&self, dataSetName: DOMString) -> ErrorResult {
|
fn SetBluetoothMockDataSet(&self, dataSetName: DOMString) -> ErrorResult {
|
||||||
let (sender, receiver) = ipc::channel().unwrap();
|
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() {
|
match receiver.recv().unwrap().into() {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use bluetooth_traits::BluetoothMethodMsg;
|
use bluetooth_traits::BluetoothRequest;
|
||||||
use cssparser::Parser;
|
use cssparser::Parser;
|
||||||
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
|
use devtools_traits::{ScriptToDevtoolsControlMsg, TimelineMarker, TimelineMarkerType};
|
||||||
use dom::bindings::callback::ExceptionHandling;
|
use dom::bindings::callback::ExceptionHandling;
|
||||||
|
@ -203,7 +203,7 @@ pub struct Window {
|
||||||
|
|
||||||
/// A handle for communicating messages to the bluetooth thread.
|
/// A handle for communicating messages to the bluetooth thread.
|
||||||
#[ignore_heap_size_of = "channels are hard"]
|
#[ignore_heap_size_of = "channels are hard"]
|
||||||
bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
bluetooth_thread: IpcSender<BluetoothRequest>,
|
||||||
|
|
||||||
/// Pending scroll to fragment event, if any
|
/// Pending scroll to fragment event, if any
|
||||||
fragment_name: DOMRefCell<Option<String>>,
|
fragment_name: DOMRefCell<Option<String>>,
|
||||||
|
@ -304,7 +304,7 @@ impl Window {
|
||||||
self.browsing_context.get().unwrap()
|
self.browsing_context.get().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bluetooth_thread(&self) -> IpcSender<BluetoothMethodMsg> {
|
pub fn bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
|
||||||
self.bluetooth_thread.clone()
|
self.bluetooth_thread.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1521,7 +1521,7 @@ impl Window {
|
||||||
image_cache_chan: ImageCacheChan,
|
image_cache_chan: ImageCacheChan,
|
||||||
image_cache_thread: ImageCacheThread,
|
image_cache_thread: ImageCacheThread,
|
||||||
resource_threads: ResourceThreads,
|
resource_threads: ResourceThreads,
|
||||||
bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
bluetooth_thread: IpcSender<BluetoothRequest>,
|
||||||
mem_profiler_chan: mem::ProfilerChan,
|
mem_profiler_chan: mem::ProfilerChan,
|
||||||
time_profiler_chan: ProfilerChan,
|
time_profiler_chan: ProfilerChan,
|
||||||
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
use bluetooth_traits::{BluetoothResponseListener, BluetoothResponseResult};
|
||||||
use net_traits::{Action, FetchResponseListener, FetchResponseMsg};
|
use net_traits::{Action, FetchResponseListener, FetchResponseMsg};
|
||||||
use script_runtime::{CommonScriptMsg, ScriptChan};
|
use script_runtime::{CommonScriptMsg, ScriptChan};
|
||||||
use script_runtime::ScriptThreadEventCategory::NetworkEvent;
|
use script_runtime::ScriptThreadEventCategory::NetworkEvent;
|
||||||
|
@ -40,6 +41,13 @@ impl<Listener: FetchResponseListener + PreInvoke + Send + 'static> NetworkListen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// helps type inference
|
||||||
|
impl<Listener: BluetoothResponseListener + PreInvoke + Send + 'static> NetworkListener<Listener> {
|
||||||
|
pub fn notify_response(&self, action: BluetoothResponseResult) {
|
||||||
|
self.notify(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A gating mechanism that runs before invoking the runnable on the target thread.
|
/// A gating mechanism that runs before invoking the runnable on the target thread.
|
||||||
/// If the `should_invoke` method returns false, the runnable is discarded without
|
/// If the `should_invoke` method returns false, the runnable is discarded without
|
||||||
/// being invoked.
|
/// being invoked.
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
//! a page runs its course and the script thread returns to processing events in the main event
|
//! a page runs its course and the script thread returns to processing events in the main event
|
||||||
//! loop.
|
//! loop.
|
||||||
|
|
||||||
use bluetooth_traits::BluetoothMethodMsg;
|
use bluetooth_traits::BluetoothRequest;
|
||||||
use devtools;
|
use devtools;
|
||||||
use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo};
|
use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo};
|
||||||
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
use devtools_traits::{ScriptToDevtoolsControlMsg, WorkerId};
|
||||||
|
@ -343,7 +343,7 @@ pub struct ScriptThread {
|
||||||
/// there are many iframes.
|
/// there are many iframes.
|
||||||
resource_threads: ResourceThreads,
|
resource_threads: ResourceThreads,
|
||||||
/// A handle to the bluetooth thread.
|
/// A handle to the bluetooth thread.
|
||||||
bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
bluetooth_thread: IpcSender<BluetoothRequest>,
|
||||||
|
|
||||||
/// The port on which the script thread receives messages (load URL, exit, etc.)
|
/// The port on which the script thread receives messages (load URL, exit, etc.)
|
||||||
port: Receiver<MainThreadScriptMsg>,
|
port: Receiver<MainThreadScriptMsg>,
|
||||||
|
|
|
@ -38,7 +38,7 @@ extern crate url;
|
||||||
mod script_msg;
|
mod script_msg;
|
||||||
pub mod webdriver_msg;
|
pub mod webdriver_msg;
|
||||||
|
|
||||||
use bluetooth_traits::BluetoothMethodMsg;
|
use bluetooth_traits::BluetoothRequest;
|
||||||
use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
|
use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg, WorkerId};
|
||||||
use euclid::Size2D;
|
use euclid::Size2D;
|
||||||
use euclid::length::Length;
|
use euclid::length::Length;
|
||||||
|
@ -445,7 +445,7 @@ pub struct InitialScriptState {
|
||||||
/// A channel to the resource manager thread.
|
/// A channel to the resource manager thread.
|
||||||
pub resource_threads: ResourceThreads,
|
pub resource_threads: ResourceThreads,
|
||||||
/// A channel to the bluetooth thread.
|
/// A channel to the bluetooth thread.
|
||||||
pub bluetooth_thread: IpcSender<BluetoothMethodMsg>,
|
pub bluetooth_thread: IpcSender<BluetoothRequest>,
|
||||||
/// A channel to the image cache thread.
|
/// A channel to the image cache thread.
|
||||||
pub image_cache_thread: ImageCacheThread,
|
pub image_cache_thread: ImageCacheThread,
|
||||||
/// A channel to the time profiler thread.
|
/// A channel to the time profiler thread.
|
||||||
|
|
1
components/servo/Cargo.lock
generated
1
components/servo/Cargo.lock
generated
|
@ -1571,6 +1571,7 @@ dependencies = [
|
||||||
name = "net_traits"
|
name = "net_traits"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bluetooth_traits 0.0.1",
|
||||||
"cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"heapsize_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -64,7 +64,7 @@ fn webdriver(port: u16, constellation: Sender<ConstellationMsg>) {
|
||||||
fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) { }
|
fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) { }
|
||||||
|
|
||||||
use bluetooth::BluetoothThreadFactory;
|
use bluetooth::BluetoothThreadFactory;
|
||||||
use bluetooth_traits::BluetoothMethodMsg;
|
use bluetooth_traits::BluetoothRequest;
|
||||||
use compositing::{CompositorProxy, IOCompositor};
|
use compositing::{CompositorProxy, IOCompositor};
|
||||||
use compositing::compositor_thread::InitialCompositorState;
|
use compositing::compositor_thread::InitialCompositorState;
|
||||||
use compositing::windowing::WindowEvent;
|
use compositing::windowing::WindowEvent;
|
||||||
|
@ -246,7 +246,7 @@ fn create_constellation(opts: opts::Opts,
|
||||||
supports_clipboard: bool,
|
supports_clipboard: bool,
|
||||||
webrender_api_sender: webrender_traits::RenderApiSender)
|
webrender_api_sender: webrender_traits::RenderApiSender)
|
||||||
-> (Sender<ConstellationMsg>, SWManagerSenders) {
|
-> (Sender<ConstellationMsg>, SWManagerSenders) {
|
||||||
let bluetooth_thread: IpcSender<BluetoothMethodMsg> = BluetoothThreadFactory::new();
|
let bluetooth_thread: IpcSender<BluetoothRequest> = BluetoothThreadFactory::new();
|
||||||
|
|
||||||
let (public_resource_threads, private_resource_threads) =
|
let (public_resource_threads, private_resource_threads) =
|
||||||
new_resource_threads(opts.user_agent,
|
new_resource_threads(opts.user_agent,
|
||||||
|
|
1
ports/cef/Cargo.lock
generated
1
ports/cef/Cargo.lock
generated
|
@ -1447,6 +1447,7 @@ dependencies = [
|
||||||
name = "net_traits"
|
name = "net_traits"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bluetooth_traits 0.0.1",
|
||||||
"cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cookie 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"heapsize_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue