script/dom/bluetooth/
bluetoothremotegattserver.rs1use std::cell::Cell;
6use std::rc::Rc;
7
8use base::generic_channel::GenericSender;
9use bluetooth_traits::{BluetoothRequest, BluetoothResponse, GATTType};
10use dom_struct::dom_struct;
11use js::realm::CurrentRealm;
12
13use crate::dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
14use crate::dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
15use crate::dom::bindings::error::{Error, ErrorResult};
16use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object_with_cx};
17use crate::dom::bindings::root::{Dom, DomRoot};
18use crate::dom::bluetooth::{AsyncBluetoothListener, get_gatt_children, response_async};
19use crate::dom::bluetoothdevice::BluetoothDevice;
20use crate::dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID};
21use crate::dom::globalscope::GlobalScope;
22use crate::dom::promise::Promise;
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 cx: &mut js::context::JSContext,
44 global: &GlobalScope,
45 device: &BluetoothDevice,
46 ) -> DomRoot<BluetoothRemoteGATTServer> {
47 reflect_dom_object_with_cx(
48 Box::new(BluetoothRemoteGATTServer::new_inherited(device)),
49 global,
50 cx,
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) -> Rc<Promise> {
76 let p = Promise::new_in_realm(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 js::context::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 ) -> Rc<Promise> {
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 ) -> Rc<Promise> {
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 js::context::JSContext,
158 response: BluetoothResponse,
159 promise: &Rc<Promise>,
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(e, CanGc::from_cx(cx));
168 }
169 return promise.reject_error(Error::Network(None), CanGc::from_cx(cx));
170 }
171
172 self.connected.set(connected);
174
175 promise.resolve_native(self, CanGc::from_cx(cx));
177 },
178 BluetoothResponse::GetPrimaryServices(services_vec, single) => {
181 let device = self.Device();
182 if single {
183 promise.resolve_native(
184 &device.get_or_create_service(cx, &services_vec[0], self),
185 CanGc::from_cx(cx),
186 );
187 return;
188 }
189 let mut services = vec![];
190 for service in services_vec {
191 let bt_service = device.get_or_create_service(cx, &service, self);
192 services.push(bt_service);
193 }
194 promise.resolve_native(&services, CanGc::from_cx(cx));
195 },
196 _ => promise.reject_error(
197 Error::Type(c"Something went wrong...".to_owned()),
198 CanGc::from_cx(cx),
199 ),
200 }
201 }
202}