script/dom/bluetooth/
bluetoothremotegattserver.rs1use std::cell::Cell;
6
7use dom_struct::dom_struct;
8use js::context::JSContext;
9use js::realm::CurrentRealm;
10use script_bindings::reflector::{Reflector, reflect_dom_object};
11use servo_base::generic_channel::GenericSender;
12use servo_bluetooth_traits::{BluetoothRequest, BluetoothResponse, GATTType};
13
14use crate::dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
15use crate::dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
16use crate::dom::bindings::error::{Error, ErrorResult};
17use crate::dom::bindings::reflector::DomGlobal;
18use crate::dom::bindings::root::{Dom, DomRoot};
19use crate::dom::bluetooth::{AsyncBluetoothListener, get_gatt_children, response_async};
20use crate::dom::bluetoothdevice::BluetoothDevice;
21use crate::dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID};
22use crate::dom::globalscope::GlobalScope;
23use crate::dom::promise::{Promise, RootedPromise};
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 cx: &mut JSContext,
44 global: &GlobalScope,
45 device: &BluetoothDevice,
46 ) -> DomRoot<BluetoothRemoteGATTServer> {
47 reflect_dom_object(
48 cx,
49 Box::new(BluetoothRemoteGATTServer::new_inherited(device)),
50 global,
51 )
52 }
53
54 fn get_bluetooth_thread(&self) -> GenericSender<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, cx: &mut CurrentRealm) -> RootedPromise {
76 let p = Promise::new_in_realm_rooted(cx);
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, cx: &mut JSContext) -> ErrorResult {
100 if !self.Connected() {
104 return Ok(());
105 }
106
107 self.Device().clean_up_disconnected_device(cx);
109
110 self.Device().garbage_collect_the_connection(cx)
112 }
113
114 fn GetPrimaryService(
116 &self,
117 cx: &mut CurrentRealm,
118 service: BluetoothServiceUUID,
119 ) -> RootedPromise {
120 let is_connected = self.Device().get_gatt(cx).Connected();
121 get_gatt_children(
123 cx,
124 self,
125 true,
126 BluetoothUUID::service,
127 Some(service),
128 String::from(self.Device().Id()),
129 is_connected,
130 GATTType::PrimaryService,
131 )
132 }
133
134 fn GetPrimaryServices(
136 &self,
137 cx: &mut CurrentRealm,
138 service: Option<BluetoothServiceUUID>,
139 ) -> RootedPromise {
140 get_gatt_children(
142 cx,
143 self,
144 false,
145 BluetoothUUID::service,
146 service,
147 String::from(self.Device().Id()),
148 self.Connected(),
149 GATTType::PrimaryService,
150 )
151 }
152}
153
154impl AsyncBluetoothListener for BluetoothRemoteGATTServer {
155 fn handle_response(
156 &self,
157 cx: &mut JSContext,
158 response: BluetoothResponse,
159 promise: &RootedPromise,
160 ) {
161 match response {
162 BluetoothResponse::GATTServerConnect(connected) => {
164 if self.Device().is_represented_device_null() {
166 if let Err(e) = self.Device().garbage_collect_the_connection(cx) {
167 return promise.reject_error(cx, e);
168 }
169 return promise.reject_error(cx, Error::Network(None));
170 }
171
172 self.connected.set(connected);
174
175 promise.resolve_native(cx, self);
177 },
178 BluetoothResponse::GetPrimaryServices(services_vec, single) => {
181 let device = self.Device();
182 if single {
183 let descriptor = device.get_or_create_service(cx, &services_vec[0], self);
184 promise.resolve_native(cx, &descriptor);
185 return;
186 }
187 let mut services = vec![];
188 for service in services_vec {
189 let bt_service = device.get_or_create_service(cx, &service, self);
190 services.push(bt_service);
191 }
192 promise.resolve_native(cx, &services);
193 },
194 _ => promise.reject_error(cx, Error::Type(c"Something went wrong...".to_owned())),
195 }
196 }
197}