servo: Merge #11367 - Extend WebBluetooth with included services (from szeged:included_services); r=jdm
authorAttila Dusnoki <dati91@users.noreply.github.com>
Thu, 26 May 2016 14:04:33 -0500
changeset 338929 ccd7c8364211494cd4524a0aeabebcfcfac3adbf
parent 338928 6c25ffa7f48152ba3b55e757a8bfed22c2515bcb
child 338930 3da155267e0143dfd0959a111d995294ae233815
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdm
servo: Merge #11367 - Extend WebBluetooth with included services (from szeged:included_services); r=jdm - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy --faster` does not report any errors - [X] These changes do not require tests because there are no webbluetooth tests yet Source-Repo: https://github.com/servo/servo Source-Revision: 3bf96a7a318d495c48538ccba15f6a4108e9b4c2
servo/components/net/bluetooth_thread.rs
servo/components/net_traits/bluetooth_thread.rs
servo/components/script/dom/bluetoothremotegattservice.rs
servo/components/script/dom/webidls/BluetoothRemoteGATTService.webidl
servo/components/servo/Cargo.lock
servo/ports/cef/Cargo.lock
servo/ports/gonk/Cargo.lock
servo/tests/html/bluetooth_included_service_info.html
--- a/servo/components/net/bluetooth_thread.rs
+++ b/servo/components/net/bluetooth_thread.rs
@@ -22,16 +22,17 @@ use std::time::Duration;
 #[cfg(target_os = "linux")]
 use tinyfiledialogs;
 use util::thread::spawn_named;
 
 const ADAPTER_ERROR: &'static str = "No adapter found";
 const DEVICE_ERROR: &'static str = "No device found";
 const DEVICE_MATCH_ERROR: &'static str = "No device found, that matches the given options";
 const PRIMARY_SERVICE_ERROR: &'static str = "No primary service found";
+const INCLUDED_SERVICE_ERROR: &'static str = "No included service found";
 const CHARACTERISTIC_ERROR: &'static str = "No characteristic found";
 const DESCRIPTOR_ERROR: &'static str = "No descriptor found";
 const VALUE_ERROR: &'static str = "No characteristic or descriptor found with that id";
 // The discovery session needs some time to find any nearby devices
 const DISCOVERY_TIMEOUT_MS: u64 = 1500;
 #[cfg(target_os = "linux")]
 const DIALOG_TITLE: &'static str = "Choose a device";
 #[cfg(target_os = "linux")]
@@ -157,16 +158,22 @@ impl BluetoothManager {
                     self.gatt_server_disconnect(device_id, sender)
                 },
                 BluetoothMethodMsg::GetPrimaryService(device_id, uuid, sender) => {
                     self.get_primary_service(device_id, uuid, sender)
                 },
                 BluetoothMethodMsg::GetPrimaryServices(device_id, uuid, sender) => {
                     self.get_primary_services(device_id, uuid, sender)
                 },
+                BluetoothMethodMsg::GetIncludedService(service_id, uuid, sender) => {
+                    self.get_included_service(service_id, uuid, sender)
+                },
+                BluetoothMethodMsg::GetIncludedServices(service_id, uuid, sender) => {
+                    self.get_included_services(service_id, uuid, sender)
+                },
                 BluetoothMethodMsg::GetCharacteristic(service_id, uuid, sender) => {
                     self.get_characteristic(service_id, uuid, sender)
                 },
                 BluetoothMethodMsg::GetCharacteristics(service_id, uuid, sender) => {
                     self.get_characteristics(service_id, uuid, sender)
                 },
                 BluetoothMethodMsg::GetDescriptor(characteristic_id, uuid, sender) => {
                     self.get_descriptor(characteristic_id, uuid, sender)
@@ -519,16 +526,76 @@ impl BluetoothManager {
         }
         if services_vec.is_empty() {
             return drop(sender.send(Err(String::from(PRIMARY_SERVICE_ERROR))));
         }
 
         let _ = sender.send(Ok(services_vec));
     }
 
+    fn get_included_service(&mut self,
+                            service_id: String,
+                            uuid: String,
+                            sender: IpcSender<BluetoothResult<BluetoothServiceMsg>>) {
+        let mut adapter = match self.get_or_create_adapter() {
+            Some(a) => a,
+            None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
+        };
+        let primary_service = match self.get_gatt_service(&mut adapter, &service_id) {
+            Some(s) => s,
+            None => return drop(sender.send(Err(String::from(PRIMARY_SERVICE_ERROR)))),
+        };
+        let services = primary_service.get_includes().unwrap_or(vec!());
+        for service in services {
+            if let Ok(service_uuid) = service.get_uuid() {
+                if uuid == service_uuid {
+                    return drop(sender.send(Ok(BluetoothServiceMsg {
+                                                   uuid: uuid,
+                                                   is_primary: service.is_primary().unwrap_or(false),
+                                                   instance_id: service.get_object_path(),
+                                               })));
+                }
+            }
+        }
+        return drop(sender.send(Err(String::from(INCLUDED_SERVICE_ERROR))));
+    }
+
+    fn get_included_services(&mut self,
+                             service_id: String,
+                             uuid: Option<String>,
+                             sender: IpcSender<BluetoothResult<BluetoothServicesMsg>>) {
+        let mut adapter = match self.get_or_create_adapter() {
+            Some(a) => a,
+            None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
+        };
+        let primary_service = match self.get_gatt_service(&mut adapter, &service_id) {
+            Some(s) => s,
+            None => return drop(sender.send(Err(String::from(PRIMARY_SERVICE_ERROR)))),
+        };
+        let services = primary_service.get_includes().unwrap_or(vec!());
+        let mut services_vec = vec!();
+        for service in services {
+            if let Ok(service_uuid) = service.get_uuid() {
+                services_vec.push(BluetoothServiceMsg {
+                                      uuid: service_uuid,
+                                      is_primary: service.is_primary().unwrap_or(false),
+                                      instance_id: service.get_object_path(),
+                                  });
+            }
+        }
+        if let Some(uuid) = uuid {
+            services_vec.retain(|ref s| s.uuid == uuid);
+        }
+        if services_vec.is_empty() {
+            return drop(sender.send(Err(String::from(INCLUDED_SERVICE_ERROR))));
+        }
+
+        let _ = sender.send(Ok(services_vec));
+    }
+
     fn get_characteristic(&mut self,
                           service_id: String,
                           uuid: String,
                           sender: IpcSender<BluetoothResult<BluetoothCharacteristicMsg>>) {
         let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
             None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
         };
--- a/servo/components/net_traits/bluetooth_thread.rs
+++ b/servo/components/net_traits/bluetooth_thread.rs
@@ -55,16 +55,18 @@ pub type BluetoothResult<T> = Result<T, 
 
 #[derive(Deserialize, Serialize)]
 pub enum BluetoothMethodMsg {
     RequestDevice(RequestDeviceoptions, IpcSender<BluetoothResult<BluetoothDeviceMsg>>),
     GATTServerConnect(String, IpcSender<BluetoothResult<bool>>),
     GATTServerDisconnect(String, IpcSender<BluetoothResult<bool>>),
     GetPrimaryService(String, String, IpcSender<BluetoothResult<BluetoothServiceMsg>>),
     GetPrimaryServices(String, Option<String>, IpcSender<BluetoothResult<BluetoothServicesMsg>>),
+    GetIncludedService(String, String, IpcSender<BluetoothResult<BluetoothServiceMsg>>),
+    GetIncludedServices(String, Option<String>, IpcSender<BluetoothResult<BluetoothServicesMsg>>),
     GetCharacteristic(String, String, IpcSender<BluetoothResult<BluetoothCharacteristicMsg>>),
     GetCharacteristics(String, Option<String>, IpcSender<BluetoothResult<BluetoothCharacteristicsMsg>>),
     GetDescriptor(String, String, IpcSender<BluetoothResult<BluetoothDescriptorMsg>>),
     GetDescriptors(String, Option<String>, IpcSender<BluetoothResult<BluetoothDescriptorsMsg>>),
     ReadValue(String, IpcSender<BluetoothResult<Vec<u8>>>),
     WriteValue(String, Vec<u8>, IpcSender<BluetoothResult<bool>>),
     Exit,
 }
--- a/servo/components/script/dom/bluetoothremotegattservice.rs
+++ b/servo/components/script/dom/bluetoothremotegattservice.rs
@@ -1,24 +1,25 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
 use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding;
 use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
 use dom::bindings::error::Error::Type;
 use dom::bindings::error::Fallible;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::{JS, MutHeap, Root};
 use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
 use dom::bindings::str::DOMString;
 use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties;
 use dom::bluetoothdevice::BluetoothDevice;
 use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic;
-use dom::bluetoothuuid::{BluetoothCharacteristicUUID, BluetoothUUID};
+use dom::bluetoothuuid::{BluetoothCharacteristicUUID, BluetoothServiceUUID, BluetoothUUID};
 use ipc_channel::ipc::{self, IpcSender};
 use net_traits::bluetooth_thread::BluetoothMethodMsg;
 
 // https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattservice
 #[dom_struct]
 pub struct BluetoothRemoteGATTService {
     reflector_: Reflector,
     device: MutHeap<JS<BluetoothDevice>>,
@@ -150,9 +151,64 @@ impl BluetoothRemoteGATTServiceMethods f
                 }
                 Ok(characteristics)
             },
             Err(error) => {
                 Err(Type(error))
             },
         }
     }
+
+    // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservice
+    fn GetIncludedService(&self,
+                          service: BluetoothServiceUUID)
+                          -> Fallible<Root<BluetoothRemoteGATTService>> {
+        let uuid = try!(BluetoothUUID::GetService(self.global().r(), service)).to_string();
+        let (sender, receiver) = ipc::channel().unwrap();
+        self.get_bluetooth_thread().send(
+            BluetoothMethodMsg::GetIncludedService(self.get_instance_id(),
+                                                   uuid,
+                                                   sender)).unwrap();
+        let service = receiver.recv().unwrap();
+        match service {
+            Ok(service) => {
+                Ok(BluetoothRemoteGATTService::new(self.global().r(),
+                                                   &self.device.get(),
+                                                   DOMString::from(service.uuid),
+                                                   service.is_primary,
+                                                   service.instance_id))
+            },
+            Err(error) => {
+                Err(Type(error))
+            },
+        }
+    }
+
+    // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices
+    fn GetIncludedServices(&self,
+                          service: Option<BluetoothServiceUUID>)
+                          -> Fallible<Vec<Root<BluetoothRemoteGATTService>>> {
+        let mut uuid: Option<String> = None;
+        if let Some(s) = service {
+            uuid = Some(try!(BluetoothUUID::GetService(self.global().r(), s)).to_string())
+        };
+        let (sender, receiver) = ipc::channel().unwrap();
+        self.get_bluetooth_thread().send(
+            BluetoothMethodMsg::GetIncludedServices(self.get_instance_id(),
+                                                    uuid,
+                                                    sender)).unwrap();
+        let services_vec = receiver.recv().unwrap();
+        match services_vec {
+            Ok(service_vec) => {
+                Ok(service_vec.into_iter()
+                              .map(|service| BluetoothRemoteGATTService::new(self.global().r(),
+                                                                             &self.device.get(),
+                                                                             DOMString::from(service.uuid),
+                                                                             service.is_primary,
+                                                                             service.instance_id))
+                              .collect())
+            },
+            Err(error) => {
+                Err(Type(error))
+            },
+        }
+    }
 }
--- a/servo/components/script/dom/webidls/BluetoothRemoteGATTService.webidl
+++ b/servo/components/script/dom/webidls/BluetoothRemoteGATTService.webidl
@@ -12,11 +12,15 @@ interface BluetoothRemoteGATTService {
     [Throws]
     BluetoothRemoteGATTCharacteristic getCharacteristic(BluetoothCharacteristicUUID characteristic);
     [Throws]
     sequence<BluetoothRemoteGATTCharacteristic> getCharacteristics
         (optional BluetoothCharacteristicUUID characteristic);
     //Promise<BluetoothRemoteGATTCharacteristic>getCharacteristic(BluetoothCharacteristicUUID characteristic);
     //Promise<sequence<BluetoothRemoteGATTCharacteristic>>
     //getCharacteristics(optional BluetoothCharacteristicUUID characteristic);
+    [Throws]
+    BluetoothRemoteGATTService getIncludedService(BluetoothServiceUUID service);
+    [Throws]
+    sequence<BluetoothRemoteGATTService> getIncludedServices(optional BluetoothServiceUUID service);
     //Promise<BluetoothRemoteGATTService>getIncludedService(BluetoothServiceUUID service);
     //Promise<sequence<BluetoothRemoteGATTService>>getIncludedServices(optional BluetoothServiceUUID service);
 };
--- a/servo/components/servo/Cargo.lock
+++ b/servo/components/servo/Cargo.lock
@@ -155,17 +155,17 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "block"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "blurz"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "dbus 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "brotli"
@@ -462,19 +462,19 @@ version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "device"
 version = "0.0.1"
-source = "git+https://github.com/servo/devices#cac0952154f65b416acef273a6d1099421ce113e"
+source = "git+https://github.com/servo/devices#3c39846a019eeed939eb7090096631254e6b5efc"
 dependencies = [
- "blurz 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "blurz 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "devtools"
 version = "0.0.1"
 dependencies = [
  "devtools_traits 0.0.1",
  "hyper 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
--- a/servo/ports/cef/Cargo.lock
+++ b/servo/ports/cef/Cargo.lock
@@ -132,17 +132,17 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "block"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "blurz"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "dbus 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "brotli"
@@ -424,19 +424,19 @@ version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "device"
 version = "0.0.1"
-source = "git+https://github.com/servo/devices#cac0952154f65b416acef273a6d1099421ce113e"
+source = "git+https://github.com/servo/devices#3c39846a019eeed939eb7090096631254e6b5efc"
 dependencies = [
- "blurz 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "blurz 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "devtools"
 version = "0.0.1"
 dependencies = [
  "devtools_traits 0.0.1",
  "hyper 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
--- a/servo/ports/gonk/Cargo.lock
+++ b/servo/ports/gonk/Cargo.lock
@@ -134,17 +134,17 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "block"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "blurz"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "dbus 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "brotli"
@@ -426,19 +426,19 @@ version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "device"
 version = "0.0.1"
-source = "git+https://github.com/servo/devices#cac0952154f65b416acef273a6d1099421ce113e"
+source = "git+https://github.com/servo/devices#3c39846a019eeed939eb7090096631254e6b5efc"
 dependencies = [
- "blurz 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "blurz 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "devtools"
 version = "0.0.1"
 dependencies = [
  "devtools_traits 0.0.1",
  "hyper 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
copy from servo/tests/html/bluetooth_primary_service_info.html
copy to servo/tests/html/bluetooth_included_service_info.html
--- a/servo/tests/html/bluetooth_primary_service_info.html
+++ b/servo/tests/html/bluetooth_included_service_info.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <html>
-<title>Primary Service info</title>
+<title>Included Service info</title>
 <body>
     <input id="service" type="text" autofocus placeholder="Bluetooth Service">
     <input id="name" type="text" placeholder="Device Name">
     <input id="namePrefix" type="text" placeholder="Device Name Prefix">
     <button type="button" onclick="onButtonClick()">Get Primary Service Info</button>
     <pre id="log"></pre>
     <script>
     function onButtonClick() {
@@ -34,17 +34,22 @@
             log('Connecting to GATTserver on device...');
             var server = device.gatt.connect();
 
             log('Getting Primary Service...');
             var primaryService = server.getPrimaryService(filterService);
 
             log('Primary Service found on device: ' + primaryService.device.name);
             log('> UUID:                          ' + primaryService.uuid);
-            log('> Is primary:                    ' + primaryService.isPrimary);
+
+            log('Getting Included Services...');
+            var includedServices = primaryService.getIncludedServices();
+
+            log('> Included Services: ' +
+                includedServices.map(s => s.uuid).join('\n' + ' '.repeat(21)));
         } catch(err) {
             log(err);
         }
     }
 
     function clear() {
         document.getElementById("log").textContent = "";
     }