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 #[allow(unsafe_code)]
76 fn Connect(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
77 let p = Promise::new_in_current_realm(comp, can_gc);
79 let sender = response_async(&p, self);
80
81 self.get_bluetooth_thread()
90 .send(BluetoothRequest::GATTServerConnect(
91 String::from(self.Device().Id()),
92 sender,
93 ))
94 .unwrap();
95 p
97 }
98
99 fn Disconnect(&self, can_gc: CanGc) -> ErrorResult {
101 if !self.Connected() {
105 return Ok(());
106 }
107
108 self.Device().clean_up_disconnected_device(can_gc);
110
111 self.Device().garbage_collect_the_connection()
113 }
114
115 fn GetPrimaryService(&self, service: BluetoothServiceUUID, can_gc: CanGc) -> Rc<Promise> {
117 get_gatt_children(
119 self,
120 true,
121 BluetoothUUID::service,
122 Some(service),
123 String::from(self.Device().Id()),
124 self.Device().get_gatt().Connected(),
125 GATTType::PrimaryService,
126 can_gc,
127 )
128 }
129
130 fn GetPrimaryServices(
132 &self,
133 service: Option<BluetoothServiceUUID>,
134 can_gc: CanGc,
135 ) -> Rc<Promise> {
136 get_gatt_children(
138 self,
139 false,
140 BluetoothUUID::service,
141 service,
142 String::from(self.Device().Id()),
143 self.Connected(),
144 GATTType::PrimaryService,
145 can_gc,
146 )
147 }
148}
149
150impl AsyncBluetoothListener for BluetoothRemoteGATTServer {
151 fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise>, can_gc: CanGc) {
152 match response {
153 BluetoothResponse::GATTServerConnect(connected) => {
155 if self.Device().is_represented_device_null() {
157 if let Err(e) = self.Device().garbage_collect_the_connection() {
158 return promise.reject_error(e, can_gc);
159 }
160 return promise.reject_error(Error::Network, can_gc);
161 }
162
163 self.connected.set(connected);
165
166 promise.resolve_native(self, can_gc);
168 },
169 BluetoothResponse::GetPrimaryServices(services_vec, single) => {
172 let device = self.Device();
173 if single {
174 promise.resolve_native(
175 &device.get_or_create_service(&services_vec[0], self, can_gc),
176 can_gc,
177 );
178 return;
179 }
180 let mut services = vec![];
181 for service in services_vec {
182 let bt_service = device.get_or_create_service(&service, self, can_gc);
183 services.push(bt_service);
184 }
185 promise.resolve_native(&services, can_gc);
186 },
187 _ => promise.reject_error(Error::Type("Something went wrong...".to_owned()), can_gc),
188 }
189 }
190}