mirror of
https://github.com/servo/servo.git
synced 2025-06-17 04:44:28 +00:00
Move the AttributeInstanceMaps from bluetooth to bluetoothDevice. <!-- Please describe your changes on the following line: --> The previous implementation differed from the spec, because there was three maps instead of one. With this, they will be merged into one. Also this map has been moved from bluetooth to bluetoothDevice, because its make more sense to store it there. There is an issue about it [here](https://github.com/WebBluetoothCG/web-bluetooth/issues/330). --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors <!-- Either: --> - [X] There are tests for these changes <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/14441) <!-- Reviewable:end -->
232 lines
9.4 KiB
Rust
232 lines
9.4 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
use bluetooth_traits::{BluetoothRequest, BluetoothResponse};
|
|
use bluetooth_traits::blocklist::{Blocklist, uuid_is_blocklisted};
|
|
use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
|
|
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding;
|
|
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
|
|
use dom::bindings::error::Error::{self, Network, Security};
|
|
use dom::bindings::error::ErrorResult;
|
|
use dom::bindings::js::{JS, MutHeap, Root};
|
|
use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
|
|
use dom::bluetooth::{AsyncBluetoothListener, response_async};
|
|
use dom::bluetoothdevice::BluetoothDevice;
|
|
use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID};
|
|
use dom::globalscope::GlobalScope;
|
|
use dom::promise::Promise;
|
|
use ipc_channel::ipc::{self, IpcSender};
|
|
use js::jsapi::JSContext;
|
|
use std::cell::Cell;
|
|
use std::rc::Rc;
|
|
|
|
// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattserver
|
|
#[dom_struct]
|
|
pub struct BluetoothRemoteGATTServer {
|
|
reflector_: Reflector,
|
|
device: MutHeap<JS<BluetoothDevice>>,
|
|
connected: Cell<bool>,
|
|
}
|
|
|
|
impl BluetoothRemoteGATTServer {
|
|
pub fn new_inherited(device: &BluetoothDevice) -> BluetoothRemoteGATTServer {
|
|
BluetoothRemoteGATTServer {
|
|
reflector_: Reflector::new(),
|
|
device: MutHeap::new(device),
|
|
connected: Cell::new(false),
|
|
}
|
|
}
|
|
|
|
pub fn new(global: &GlobalScope, device: &BluetoothDevice) -> Root<BluetoothRemoteGATTServer> {
|
|
reflect_dom_object(box BluetoothRemoteGATTServer::new_inherited(device),
|
|
global,
|
|
BluetoothRemoteGATTServerBinding::Wrap)
|
|
}
|
|
|
|
fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
|
|
self.global().as_window().bluetooth_thread()
|
|
}
|
|
}
|
|
|
|
impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
|
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-device
|
|
fn Device(&self) -> Root<BluetoothDevice> {
|
|
self.device.get()
|
|
}
|
|
|
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connected
|
|
fn Connected(&self) -> bool {
|
|
self.connected.get()
|
|
}
|
|
|
|
#[allow(unrooted_must_root)]
|
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect
|
|
fn Connect(&self) -> Rc<Promise> {
|
|
// Step 1.
|
|
let p = Promise::new(&self.global());
|
|
let sender = response_async(&p, self);
|
|
|
|
// TODO: Step 2: Implement representedDevice internal slot for BluetoothDevice.
|
|
|
|
// TODO: Step 3: Check if the UA is currently using the Bluetooth system.
|
|
|
|
// TODO: Step 4: Implement activeAlgorithms internal slot for BluetoothRemoteGATTServer.
|
|
|
|
// TODO: Step 5.1 - 5.2: Implement activeAlgorithms, representedDevice internal slots
|
|
// and the` garbage-collect the connection` algorithm.
|
|
|
|
// Note: Steps 5.1.1 and 5.1.3 are in components/bluetooth/lib.rs in the gatt_server_connect function.
|
|
// Steps 5.2.4 - 5.2.5 are in response function.
|
|
self.get_bluetooth_thread().send(
|
|
BluetoothRequest::GATTServerConnect(String::from(self.Device().Id()), sender)).unwrap();
|
|
// Step 5: return promise.
|
|
return p;
|
|
}
|
|
|
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-disconnect
|
|
fn Disconnect(&self) -> ErrorResult {
|
|
// TODO: Step 1: Implement activeAlgorithms internal slot for BluetoothRemoteGATTServer.
|
|
|
|
// Step 2.
|
|
if !self.Connected() {
|
|
return Ok(());
|
|
}
|
|
let (sender, receiver) = ipc::channel().unwrap();
|
|
self.get_bluetooth_thread().send(
|
|
BluetoothRequest::GATTServerDisconnect(String::from(self.Device().Id()), sender)).unwrap();
|
|
let server = receiver.recv().unwrap();
|
|
|
|
// TODO: Step 3: Implement the `clean up the disconnected device` algorithm.
|
|
|
|
// TODO: Step 4: Implement representedDevice internal slot for BluetoothDevice.
|
|
|
|
// TODO: Step 5: Implement the `garbage-collect the connection` algorithm.
|
|
match server {
|
|
Ok(connected) => {
|
|
self.connected.set(connected);
|
|
Ok(())
|
|
},
|
|
Err(error) => {
|
|
Err(Error::from(error))
|
|
},
|
|
}
|
|
}
|
|
|
|
#[allow(unrooted_must_root)]
|
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice
|
|
fn GetPrimaryService(&self, service: BluetoothServiceUUID) -> Rc<Promise> {
|
|
// TODO: Step 1: Implement the Permission API and the allowedServices BluetoothDevice internal slot.
|
|
// Subsequent steps are relative to https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
|
|
let p = Promise::new(&self.global());
|
|
let p_cx = p.global().get_cx();
|
|
|
|
// Step 1.
|
|
let uuid = match BluetoothUUID::service(service) {
|
|
Ok(uuid) => uuid.to_string(),
|
|
Err(e) => {
|
|
p.reject_error(p_cx, e);
|
|
return p;
|
|
}
|
|
};
|
|
|
|
// Step 2.
|
|
if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) {
|
|
p.reject_error(p_cx, Security);
|
|
return p;
|
|
}
|
|
|
|
// Step 3 - 4.
|
|
if !self.Device().Gatt().Connected() {
|
|
p.reject_error(p_cx, Network);
|
|
return p;
|
|
}
|
|
|
|
// TODO: Step 5: Implement representedDevice internal slot for BluetoothDevice.
|
|
|
|
// Note: Steps 6 - 7 are implemented in components/bluetooth/lib.rs in get_primary_service function
|
|
// and in handle_response function.
|
|
let sender = response_async(&p, self);
|
|
self.get_bluetooth_thread().send(
|
|
BluetoothRequest::GetPrimaryService(String::from(self.Device().Id()), uuid, sender)).unwrap();
|
|
return p;
|
|
}
|
|
|
|
#[allow(unrooted_must_root)]
|
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices
|
|
fn GetPrimaryServices(&self, service: Option<BluetoothServiceUUID>) -> Rc<Promise> {
|
|
// TODO: Step 1: Implement the Permission API and the allowedServices BluetoothDevice internal slot.
|
|
// Subsequent steps are relative to https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
|
|
let p = Promise::new(&self.global());
|
|
let p_cx = p.global().get_cx();
|
|
|
|
let mut uuid: Option<String> = None;
|
|
if let Some(s) = service {
|
|
// Step 1.
|
|
uuid = match BluetoothUUID::service(s) {
|
|
Ok(uuid) => Some(uuid.to_string()),
|
|
Err(e) => {
|
|
p.reject_error(p_cx, e);
|
|
return p;
|
|
}
|
|
};
|
|
if let Some(ref uuid) = uuid {
|
|
// Step 2.
|
|
if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) {
|
|
p.reject_error(p_cx, Security);
|
|
return p;
|
|
}
|
|
}
|
|
};
|
|
|
|
// Step 3 - 4.
|
|
if !self.Device().Gatt().Connected() {
|
|
p.reject_error(p_cx, Network);
|
|
return p;
|
|
}
|
|
|
|
// TODO: Step 5: Implement representedDevice internal slot for BluetoothDevice.
|
|
|
|
// Note: Steps 6 - 7 are implemented in components/bluetooth/lib.rs in get_primary_services function
|
|
// and in handle_response function.
|
|
let sender = response_async(&p, self);
|
|
self.get_bluetooth_thread().send(
|
|
BluetoothRequest::GetPrimaryServices(String::from(self.Device().Id()), uuid, sender)).unwrap();
|
|
return p;
|
|
}
|
|
}
|
|
|
|
impl AsyncBluetoothListener for BluetoothRemoteGATTServer {
|
|
fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc<Promise>) {
|
|
let device = self.Device();
|
|
match response {
|
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect
|
|
BluetoothResponse::GATTServerConnect(connected) => {
|
|
// Step 5.2.4.
|
|
self.connected.set(connected);
|
|
|
|
// Step 5.2.5.
|
|
promise.resolve_native(promise_cx, self);
|
|
},
|
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice
|
|
// https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
|
|
// Step 7.
|
|
BluetoothResponse::GetPrimaryService(service) => {
|
|
let bt_service = device.get_or_create_service(&service, &self);
|
|
promise.resolve_native(promise_cx, &bt_service);
|
|
},
|
|
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices
|
|
// https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
|
|
// Step 7.
|
|
BluetoothResponse::GetPrimaryServices(services_vec) => {
|
|
let mut services = vec!();
|
|
for service in services_vec {
|
|
let bt_service = device.get_or_create_service(&service, &self);
|
|
services.push(bt_service);
|
|
}
|
|
promise.resolve_native(promise_cx, &services);
|
|
},
|
|
_ => promise.reject_error(promise_cx, Error::Type("Something went wrong...".to_owned())),
|
|
}
|
|
}
|
|
}
|