script/dom/bluetooth/
bluetoothremotegattservice.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::rc::Rc;
6
7use bluetooth_traits::{BluetoothResponse, GATTType};
8use dom_struct::dom_struct;
9
10use crate::dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
11use crate::dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
12use crate::dom::bindings::error::Error;
13use crate::dom::bindings::reflector::reflect_dom_object;
14use crate::dom::bindings::root::{Dom, DomRoot};
15use crate::dom::bindings::str::DOMString;
16use crate::dom::bluetooth::{AsyncBluetoothListener, get_gatt_children};
17use crate::dom::bluetoothdevice::BluetoothDevice;
18use crate::dom::bluetoothuuid::{BluetoothCharacteristicUUID, BluetoothServiceUUID, BluetoothUUID};
19use crate::dom::eventtarget::EventTarget;
20use crate::dom::globalscope::GlobalScope;
21use crate::dom::promise::Promise;
22use crate::script_runtime::CanGc;
23
24// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattservice
25#[dom_struct]
26pub(crate) struct BluetoothRemoteGATTService {
27    eventtarget: EventTarget,
28    device: Dom<BluetoothDevice>,
29    uuid: DOMString,
30    is_primary: bool,
31    instance_id: String,
32}
33
34impl BluetoothRemoteGATTService {
35    pub(crate) fn new_inherited(
36        device: &BluetoothDevice,
37        uuid: DOMString,
38        is_primary: bool,
39        instance_id: String,
40    ) -> BluetoothRemoteGATTService {
41        BluetoothRemoteGATTService {
42            eventtarget: EventTarget::new_inherited(),
43            device: Dom::from_ref(device),
44            uuid,
45            is_primary,
46            instance_id,
47        }
48    }
49
50    #[allow(non_snake_case)]
51    pub(crate) fn new(
52        global: &GlobalScope,
53        device: &BluetoothDevice,
54        uuid: DOMString,
55        isPrimary: bool,
56        instanceID: String,
57        can_gc: CanGc,
58    ) -> DomRoot<BluetoothRemoteGATTService> {
59        reflect_dom_object(
60            Box::new(BluetoothRemoteGATTService::new_inherited(
61                device, uuid, isPrimary, instanceID,
62            )),
63            global,
64            can_gc,
65        )
66    }
67
68    fn get_instance_id(&self) -> String {
69        self.instance_id.clone()
70    }
71}
72
73impl BluetoothRemoteGATTServiceMethods<crate::DomTypeHolder> for BluetoothRemoteGATTService {
74    // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-device
75    fn Device(&self) -> DomRoot<BluetoothDevice> {
76        DomRoot::from_ref(&self.device)
77    }
78
79    // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-isprimary
80    fn IsPrimary(&self) -> bool {
81        self.is_primary
82    }
83
84    // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-uuid
85    fn Uuid(&self) -> DOMString {
86        self.uuid.clone()
87    }
88
89    // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic
90    fn GetCharacteristic(
91        &self,
92        characteristic: BluetoothCharacteristicUUID,
93        can_gc: CanGc,
94    ) -> Rc<Promise> {
95        get_gatt_children(
96            self,
97            true,
98            BluetoothUUID::characteristic,
99            Some(characteristic),
100            self.get_instance_id(),
101            self.Device().get_gatt().Connected(),
102            GATTType::Characteristic,
103            can_gc,
104        )
105    }
106
107    // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics
108    fn GetCharacteristics(
109        &self,
110        characteristic: Option<BluetoothCharacteristicUUID>,
111        can_gc: CanGc,
112    ) -> Rc<Promise> {
113        get_gatt_children(
114            self,
115            false,
116            BluetoothUUID::characteristic,
117            characteristic,
118            self.get_instance_id(),
119            self.Device().get_gatt().Connected(),
120            GATTType::Characteristic,
121            can_gc,
122        )
123    }
124
125    // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservice
126    fn GetIncludedService(&self, service: BluetoothServiceUUID, can_gc: CanGc) -> Rc<Promise> {
127        get_gatt_children(
128            self,
129            false,
130            BluetoothUUID::service,
131            Some(service),
132            self.get_instance_id(),
133            self.Device().get_gatt().Connected(),
134            GATTType::IncludedService,
135            can_gc,
136        )
137    }
138
139    // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices
140    fn GetIncludedServices(
141        &self,
142        service: Option<BluetoothServiceUUID>,
143        can_gc: CanGc,
144    ) -> Rc<Promise> {
145        get_gatt_children(
146            self,
147            false,
148            BluetoothUUID::service,
149            service,
150            self.get_instance_id(),
151            self.Device().get_gatt().Connected(),
152            GATTType::IncludedService,
153            can_gc,
154        )
155    }
156
157    // https://webbluetoothcg.github.io/web-bluetooth/#dom-serviceeventhandlers-onserviceadded
158    event_handler!(serviceadded, GetOnserviceadded, SetOnserviceadded);
159
160    // https://webbluetoothcg.github.io/web-bluetooth/#dom-serviceeventhandlers-onservicechanged
161    event_handler!(servicechanged, GetOnservicechanged, SetOnservicechanged);
162
163    // https://webbluetoothcg.github.io/web-bluetooth/#dom-serviceeventhandlers-onserviceremoved
164    event_handler!(serviceremoved, GetOnserviceremoved, SetOnserviceremoved);
165}
166
167impl AsyncBluetoothListener for BluetoothRemoteGATTService {
168    fn handle_response(&self, response: BluetoothResponse, promise: &Rc<Promise>, can_gc: CanGc) {
169        let device = self.Device();
170        match response {
171            // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
172            // Step 7.
173            BluetoothResponse::GetCharacteristics(characteristics_vec, single) => {
174                if single {
175                    promise.resolve_native(
176                        &device.get_or_create_characteristic(&characteristics_vec[0], self, can_gc),
177                        can_gc,
178                    );
179                    return;
180                }
181                let mut characteristics = vec![];
182                for characteristic in characteristics_vec {
183                    let bt_characteristic =
184                        device.get_or_create_characteristic(&characteristic, self, can_gc);
185                    characteristics.push(bt_characteristic);
186                }
187                promise.resolve_native(&characteristics, can_gc);
188            },
189            // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren
190            // Step 7.
191            BluetoothResponse::GetIncludedServices(services_vec, single) => {
192                if single {
193                    return promise.resolve_native(
194                        &device.get_or_create_service(&services_vec[0], &device.get_gatt(), can_gc),
195                        can_gc,
196                    );
197                }
198                let mut services = vec![];
199                for service in services_vec {
200                    let bt_service =
201                        device.get_or_create_service(&service, &device.get_gatt(), can_gc);
202                    services.push(bt_service);
203                }
204                promise.resolve_native(&services, can_gc);
205            },
206            _ => promise.reject_error(Error::Type("Something went wrong...".to_owned()), can_gc),
207        }
208    }
209}