script/dom/bluetooth/
bluetoothremotegattserver.rs1use std::cell::Cell;
6use std::rc::Rc;
7
8use bluetooth_traits::{BluetoothRequest, BluetoothResponse, GATTType};
9use dom_struct::dom_struct;
10use ipc_channel::ipc::IpcSender;
11
12use crate::dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
13use crate::dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
14use crate::dom::bindings::error::{Error, ErrorResult};
15use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
16use crate::dom::bindings::root::{Dom, DomRoot};
17use crate::dom::bluetooth::{AsyncBluetoothListener, get_gatt_children, response_async};
18use crate::dom::bluetoothdevice::BluetoothDevice;
19use crate::dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID};
20use crate::dom::globalscope::GlobalScope;
21use crate::dom::promise::Promise;
22use crate::realms::InRealm;
23use crate::script_runtime::CanGc;
24
25#[dom_struct]
27pub(crate) struct BluetoothRemoteGATTServer {
28 reflector_: Reflector,
29 device: Dom<BluetoothDevice>,
30 connected: Cell<bool>,
31}
32
33impl BluetoothRemoteGATTServer {
34 pub(crate) fn new_inherited(device: &BluetoothDevice) -> BluetoothRemoteGATTServer {
35 BluetoothRemoteGATTServer {
36 reflector_: Reflector::new(),
37 device: Dom::from_ref(device),
38 connected: Cell::new(false),
39 }
40 }
41
42 pub(crate) fn new(
43 global: &GlobalScope,
44 device: &BluetoothDevice,
45 can_gc: CanGc,
46 ) -> DomRoot<BluetoothRemoteGATTServer> {
47 reflect_dom_object(
48 Box::new(BluetoothRemoteGATTServer::new_inherited(device)),
49 global,
50 can_gc,
51 )
52 }
53
54 fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> {
55 self.global().as_window().bluetooth_thread()
56 }
57
58 pub(crate) fn set_connected(&self, connected: bool) {
59 self.connected.set(connected);
60 }
61}
62
63impl BluetoothRemoteGATTServerMethods<crate::DomTypeHolder> for BluetoothRemoteGATTServer {
64 fn Device(&self) -> DomRoot<BluetoothDevice> {
66 DomRoot::from_ref(&self.device)
67 }
68
69 fn Connected(&self) -> bool {
71 self.connected.get()
72 }
73
74 fn Connect(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
76 let p = Promise::new_in_current_realm(comp, can_gc);
78 let sender = response_async(&p, self);
79
80 self.get_bluetooth_thread()
89 .send(BluetoothRequest::GATTServerConnect(
90 String::from(self.Device().Id()),
91 sender,
92 ))
93 .unwrap();
94 p
96 }
97
98 fn Disconnect(&self, can_gc: CanGc) -> ErrorResult {
100 if !self.Connected() {
104 return Ok(());
105 }
106
107 self.Device().clean_up_disconnected_device(can_gc);
109
110 self.Device().garbage_collect_the_connection(can_gc)
112 }
113
114 fn GetPrimaryService(&self, service: BluetoothServiceUUID, can_gc: CanGc) -> Rc<Promise> {
116 get_gatt_children(
118 self,
119 true,
120 BluetoothUUID::service,
121 Some(service),
122 String::from(self.Device().Id()),
123 self.Device().get_gatt(can_gc).Connected(),
124 GATTType::PrimaryService,
125 can_gc,
126 )
127 }
128
129 fn GetPrimaryServices(
131 &self,
132 service: Option<BluetoothServiceUUID>,
133 can_gc: CanGc,
134 ) -> Rc<Promise> {
135 get_gatt_children(
137 self,
138 false,
139 BluetoothUUID::service,
140 service,
141 String::from(self.Device().Id()),
142 self.Connected(),
143 GATTType::PrimaryService,
144 can_gc,
145 )
146 }
147}
148
149impl AsyncBluetoothListener for BluetoothRemoteGATTServer {
150 fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise>, can_gc: CanGc) {
151 match response {
152 BluetoothResponse::GATTServerConnect(connected) => {
154 if self.Device().is_represented_device_null() {
156 if let Err(e) = self.Device().garbage_collect_the_connection(can_gc) {
157 return promise.reject_error(e, can_gc);
158 }
159 return promise.reject_error(Error::Network, can_gc);
160 }
161
162 self.connected.set(connected);
164
165 promise.resolve_native(self, can_gc);
167 },
168 BluetoothResponse::GetPrimaryServices(services_vec, single) => {
171 let device = self.Device();
172 if single {
173 promise.resolve_native(
174 &device.get_or_create_service(&services_vec[0], self, can_gc),
175 can_gc,
176 );
177 return;
178 }
179 let mut services = vec![];
180 for service in services_vec {
181 let bt_service = device.get_or_create_service(&service, self, can_gc);
182 services.push(bt_service);
183 }
184 promise.resolve_native(&services, can_gc);
185 },
186 _ => promise.reject_error(Error::Type("Something went wrong...".to_owned()), can_gc),
187 }
188 }
189}