From 9e57364795a5e44382463e830e8927a9d259b667 Mon Sep 17 00:00:00 2001 From: Attila Dusnoki Date: Tue, 22 Mar 2016 14:24:45 +0100 Subject: [PATCH 01/15] Fix value types --- .../script/dom/bluetoothadvertisingdata.rs | 23 ++++--- components/script/dom/bluetoothdevice.rs | 69 +++++++++---------- 2 files changed, 48 insertions(+), 44 deletions(-) diff --git a/components/script/dom/bluetoothadvertisingdata.rs b/components/script/dom/bluetoothadvertisingdata.rs index 71c1346fa3d..f6a7805acbf 100644 --- a/components/script/dom/bluetoothadvertisingdata.rs +++ b/components/script/dom/bluetoothadvertisingdata.rs @@ -12,13 +12,16 @@ use dom::bindings::reflector::{Reflector, reflect_dom_object}; #[dom_struct] pub struct BluetoothAdvertisingData { reflector_: Reflector, - appearance: u16, - txPower: i8, - rssi: i8, + appearance: Option, + txPower: Option, + rssi: Option, } impl BluetoothAdvertisingData { - pub fn new_inherited(appearance: u16, txPower: i8, rssi: i8) -> BluetoothAdvertisingData { + pub fn new_inherited(appearance: Option, + txPower: Option, + rssi: Option) + -> BluetoothAdvertisingData { BluetoothAdvertisingData { reflector_: Reflector::new(), appearance: appearance, @@ -27,7 +30,11 @@ impl BluetoothAdvertisingData { } } - pub fn new(global: GlobalRef, appearance: u16, txPower: i8, rssi: i8) -> Root { + pub fn new(global: GlobalRef, + appearance: Option, + txPower: Option, + rssi: Option) + -> Root { reflect_dom_object(box BluetoothAdvertisingData::new_inherited(appearance, txPower, rssi), @@ -39,16 +46,16 @@ impl BluetoothAdvertisingData { impl BluetoothAdvertisingDataMethods for BluetoothAdvertisingData { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothadvertisingdata-appearance fn GetAppearance(&self) -> Option { - Some(self.appearance) + self.appearance } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothadvertisingdata-txpower fn GetTxPower(&self) -> Option { - Some(self.txPower) + self.txPower } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothadvertisingdata-rssi fn GetRssi(&self) -> Option { - Some(self.rssi) + self.rssi } } diff --git a/components/script/dom/bluetoothdevice.rs b/components/script/dom/bluetoothdevice.rs index a941f89fa7e..8330ca4604a 100644 --- a/components/script/dom/bluetoothdevice.rs +++ b/components/script/dom/bluetoothdevice.rs @@ -5,8 +5,8 @@ use dom::bindings::codegen::Bindings::BluetoothDeviceBinding; use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::{BluetoothDeviceMethods, VendorIDSource}; use dom::bindings::global::GlobalRef; -use dom::bindings::js::{JS, Root, MutHeap}; -use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::bindings::js::{JS, Root, MutHeap, MutNullableHeap}; +use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; use dom::bluetoothadvertisingdata::BluetoothAdvertisingData; use dom::bluetoothremotegattserver::BluetoothRemoteGATTServer; use util::str::DOMString; @@ -16,26 +16,25 @@ use util::str::DOMString; pub struct BluetoothDevice { reflector_: Reflector, id: DOMString, - name: DOMString, + name: Option, adData: MutHeap>, - deviceClass: u32, - vendorIDSource: VendorIDSource, - vendorID: u32, - productID: u32, - productVersion: u32, - gatt: MutHeap>, + deviceClass: Option, + vendorIDSource: Option, + vendorID: Option, + productID: Option, + productVersion: Option, + gatt: MutNullableHeap>, } impl BluetoothDevice { pub fn new_inherited(id: DOMString, - name: DOMString, + name: Option, adData: &BluetoothAdvertisingData, - deviceClass: u32, - vendorIDSource: VendorIDSource, - vendorID: u32, - productID: u32, - productVersion: u32, - gatt: &BluetoothRemoteGATTServer) + deviceClass: Option, + vendorIDSource: Option, + vendorID: Option, + productID: Option, + productVersion: Option) -> BluetoothDevice { BluetoothDevice { reflector_: Reflector::new(), @@ -47,21 +46,20 @@ impl BluetoothDevice { vendorID: vendorID, productID: productID, productVersion: productVersion, - gatt: MutHeap::new(gatt), + gatt: Default::default(), } } pub fn new(global: GlobalRef, - id: DOMString, - name: DOMString, - adData: &BluetoothAdvertisingData, - deviceClass: u32, - vendorIDSource: VendorIDSource, - vendorID: u32, - productID: u32, - productVersion: u32, - gatt: &BluetoothRemoteGATTServer) - -> Root { + id: DOMString, + name: Option, + adData: &BluetoothAdvertisingData, + deviceClass: Option, + vendorIDSource: Option, + vendorID: Option, + productID: Option, + productVersion: Option) + -> Root { reflect_dom_object(box BluetoothDevice::new_inherited(id, name, adData, @@ -69,8 +67,7 @@ impl BluetoothDevice { vendorIDSource, vendorID, productID, - productVersion, - gatt), + productVersion), global, BluetoothDeviceBinding::Wrap) } @@ -85,7 +82,7 @@ impl BluetoothDeviceMethods for BluetoothDevice { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-name fn GetName(&self) -> Option { - Some(self.name.clone()) + self.name.clone() } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-addata @@ -95,31 +92,31 @@ impl BluetoothDeviceMethods for BluetoothDevice { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-deviceclass fn GetDeviceClass(&self) -> Option { - Some(self.deviceClass) + self.deviceClass } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-vendoridsource fn GetVendorIDSource(&self) -> Option { - Some(self.vendorIDSource) + self.vendorIDSource } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-vendorid fn GetVendorID(&self) -> Option { - Some(self.vendorID) + self.vendorID } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-productid fn GetProductID(&self) -> Option { - Some(self.productID) + self.productID } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-productversion fn GetProductVersion(&self) -> Option { - Some(self.productVersion) + self.productVersion } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-gatt fn Gatt(&self) -> Root { - self.gatt.get() + self.gatt.or_init(|| BluetoothRemoteGATTServer::new(self.global().r(), self)) } } From 9d55748de24fc140302ef4dffefe43acb998c269 Mon Sep 17 00:00:00 2001 From: zakorgyula Date: Thu, 17 Mar 2016 11:28:15 +0100 Subject: [PATCH 02/15] Update assigned services, characteristics and descriptors --- components/script/dom/bluetoothuuid.rs | 237 ++++++++++++++++++++++++- 1 file changed, 228 insertions(+), 9 deletions(-) diff --git a/components/script/dom/bluetoothuuid.rs b/components/script/dom/bluetoothuuid.rs index 33aa6d944d5..1817601dc97 100644 --- a/components/script/dom/bluetoothuuid.rs +++ b/components/script/dom/bluetoothuuid.rs @@ -18,27 +18,246 @@ pub struct BluetoothUUID { reflector_: Reflector, } -const BLUETOOTH_ASSIGNED_SERVICES: &'static [(&'static str, u32)] = &[ -//TODO(zakorgy) create all the services //https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx +const BLUETOOTH_ASSIGNED_SERVICES: &'static [(&'static str, u32)] = &[ ("org.bluetooth.service.alert_notification", 0x1811_u32), ("org.bluetooth.service.automation_io", 0x1815_u32), - ("org.bluetooth.service.battery_service", 0x180f_u32) + ("org.bluetooth.service.battery_service", 0x180f_u32), + ("org.bluetooth.service.blood_pressure", 0x1810_u32), + ("org.bluetooth.service.body_composition", 0x181b_u32), + ("org.bluetooth.service.bond_management", 0x181e_u32), + ("org.bluetooth.service.continuous_glucose_monitoring", 0x181f_u32), + ("org.bluetooth.service.current_time", 0x1805_u32), + ("org.bluetooth.service.cycling_power", 0x1818_u32), + ("org.bluetooth.service.cycling_speed_and_cadence", 0x1816_u32), + ("org.bluetooth.service.device_information", 0x180a_u32), + ("org.bluetooth.service.environmental_sensing", 0x181a_u32), + ("org.bluetooth.service.generic_access", 0x1800_u32), + ("org.bluetooth.service.generic_attribute", 0x1801_u32), + ("org.bluetooth.service.glucose", 0x1808_u32), + ("org.bluetooth.service.health_thermometer", 0x1809_u32), + ("org.bluetooth.service.heart_rate", 0x180d_u32), + ("org.bluetooth.service.http_proxy", 0x1823_u32), + ("org.bluetooth.service.human_interface_device", 0x1812_u32), + ("org.bluetooth.service.immediate_alert", 0x1802_u32), + ("org.bluetooth.service.indoor_positioning", 0x1821_u32), + ("org.bluetooth.service.internet_protocol_support", 0x1820_u32), + ("org.bluetooth.service.link_loss", 0x1803_u32), + ("org.bluetooth.service.location_and_navigation", 0x1819_u32), + ("org.bluetooth.service.next_dst_change", 0x1807_u32), + ("org.bluetooth.service.object_transfer", 0x1825_u32), + ("org.bluetooth.service.phone_alert_status", 0x180e_u32), + ("org.bluetooth.service.pulse_oximeter", 0x1822_u32), + ("org.bluetooth.service.reference_time_update", 0x1806_u32), + ("org.bluetooth.service.running_speed_and_cadence", 0x1814_u32), + ("org.bluetooth.service.scan_parameters", 0x1813_u32), + ("org.bluetooth.service.transport_discovery", 0x1824), + ("org.bluetooth.service.tx_power", 0x1804_u32), + ("org.bluetooth.service.user_data", 0x181c_u32), + ("org.bluetooth.service.weight_scale", 0x181d_u32), ]; -const BLUETOOTH_ASSIGNED_CHARCTERISTICS: &'static [(&'static str, u32)] = &[ -//TODO(zakorgy) create all the characteristics //https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx +const BLUETOOTH_ASSIGNED_CHARCTERISTICS: &'static [(&'static str, u32)] = &[ ("org.bluetooth.characteristic.aerobic_heart_rate_lower_limit", 0x2a7e_u32), ("org.bluetooth.characteristic.aerobic_heart_rate_upper_limit", 0x2a84_u32), - ("org.bluetooth.characteristic.battery_level", 0x2a19_u32) + ("org.bluetooth.characteristic.aerobic_threshold", 0x2a7f_u32), + ("org.bluetooth.characteristic.age", 0x2a80_u32), + ("org.bluetooth.characteristic.aggregate", 0x2a5a_u32), + ("org.bluetooth.characteristic.alert_category_id", 0x2a43_u32), + ("org.bluetooth.characteristic.alert_category_id_bit_mask", 0x2a42_u32), + ("org.bluetooth.characteristic.alert_level", 0x2a06_u32), + ("org.bluetooth.characteristic.alert_notification_control_point", 0x2a44_u32), + ("org.bluetooth.characteristic.alert_status", 0x2a3f_u32), + ("org.bluetooth.characteristic.altitude", 0x2ab3_u32), + ("org.bluetooth.characteristic.anaerobic_heart_rate_lower_limit", 0x2a81_u32), + ("org.bluetooth.characteristic.anaerobic_heart_rate_upper_limit", 0x2a82_u32), + ("org.bluetooth.characteristic.anaerobic_threshold", 0x2a83_u32), + ("org.bluetooth.characteristic.analog", 0x2a58_u32), + ("org.bluetooth.characteristic.apparent_wind_direction", 0x2a73_u32), + ("org.bluetooth.characteristic.apparent_wind_speed", 0x2a72_u32), + ("org.bluetooth.characteristic.gap.appearance", 0x2a01_u32), + ("org.bluetooth.characteristic.barometric_pressure_trend", 0x2aa3_u32), + ("org.bluetooth.characteristic.battery_level", 0x2a19_u32), + ("org.bluetooth.characteristic.blood_pressure_feature", 0x2a49_u32), + ("org.bluetooth.characteristic.blood_pressure_measurement", 0x2a35_u32), + ("org.bluetooth.characteristic.body_composition_feature", 0x2a9b_u32), + ("org.bluetooth.characteristic.body_composition_measurement", 0x2a9c_u32), + ("org.bluetooth.characteristic.body_sensor_location", 0x2a38_u32), + ("org.bluetooth.characteristic.bond_management_control_point", 0x2aa4_u32), + ("org.bluetooth.characteristic.bond_management_feature", 0x2aa5_u32), + ("org.bluetooth.characteristic.boot_keyboard_input_report", 0x2a22_u32), + ("org.bluetooth.characteristic.boot_keyboard_output_report", 0x2a32_u32), + ("org.bluetooth.characteristic.boot_mouse_input_report", 0x2a33_u32), + ("org.bluetooth.characteristic.gap.central_address_resolution_support", 0x2aa6_u32), + ("org.bluetooth.characteristic.cgm_feature", 0x2aa8_u32), + ("org.bluetooth.characteristic.cgm_measurement", 0x2aa7_u32), + ("org.bluetooth.characteristic.cgm_session_run_time", 0x2aab_u32), + ("org.bluetooth.characteristic.cgm_session_start_time", 0x2aaa_u32), + ("org.bluetooth.characteristic.cgm_specific_ops_control_point", 0x2aac_u32), + ("org.bluetooth.characteristic.cgm_status", 0x2aa9_u32), + ("org.bluetooth.characteristic.csc_feature", 0x2a5c_u32), + ("org.bluetooth.characteristic.csc_measurement", 0x2a5b_u32), + ("org.bluetooth.characteristic.current_time", 0x2a2b_u32), + ("org.bluetooth.characteristic.cycling_power_control_point", 0x2a66_u32), + ("org.bluetooth.characteristic.cycling_power_feature", 0x2a65_u32), + ("org.bluetooth.characteristic.cycling_power_measurement", 0x2a63_u32), + ("org.bluetooth.characteristic.cycling_power_vector", 0x2a64_u32), + ("org.bluetooth.characteristic.database_change_increment", 0x2a99_u32), + ("org.bluetooth.characteristic.date_of_birth", 0x2a85_u32), + ("org.bluetooth.characteristic.date_of_threshold_assessment", 0x2a86_u32), + ("org.bluetooth.characteristic.date_time", 0x2a08_u32), + ("org.bluetooth.characteristic.day_date_time", 0x2a0a_u32), + ("org.bluetooth.characteristic.day_of_week", 0x2a09_u32), + ("org.bluetooth.characteristic.descriptor_value_changed", 0x2a7d_u32), + ("org.bluetooth.characteristic.gap.device_name", 0x2a00_u32), + ("org.bluetooth.characteristic.dew_point", 0x2a7b_u32), + ("org.bluetooth.characteristic.digital", 0x2a56_u32), + ("org.bluetooth.characteristic.dst_offset", 0x2a0d_u32), + ("org.bluetooth.characteristic.elevation", 0x2a6c_u32), + ("org.bluetooth.characteristic.email_address", 0x2a87_u32), + ("org.bluetooth.characteristic.exact_time_256", 0x2a0c_u32), + ("org.bluetooth.characteristic.fat_burn_heart_rate_lower_limit", 0x2a88_u32), + ("org.bluetooth.characteristic.fat_burn_heart_rate_upper_limit", 0x2a89_u32), + ("org.bluetooth.characteristic.firmware_revision_string", 0x2a26_u32), + ("org.bluetooth.characteristic.first_name", 0x2a8a_u32), + ("org.bluetooth.characteristic.five_zone_heart_rate_limits", 0x2a8b_u32), + ("org.bluetooth.characteristic.floor_number", 0x2ab2_u32), + ("org.bluetooth.characteristic.gender", 0x2a8c_u32), + ("org.bluetooth.characteristic.glucose_feature", 0x2a51_u32), + ("org.bluetooth.characteristic.glucose_measurement", 0x2a18_u32), + ("org.bluetooth.characteristic.glucose_measurement_context", 0x2a34_u32), + ("org.bluetooth.characteristic.gust_factor", 0x2a74_u32), + ("org.bluetooth.characteristic.hardware_revision_string", 0x2a27_u32), + ("org.bluetooth.characteristic.heart_rate_control_point", 0x2a39_u32), + ("org.bluetooth.characteristic.heart_rate_max", 0x2a8d_u32), + ("org.bluetooth.characteristic.heart_rate_measurement", 0x2a37_u32), + ("org.bluetooth.characteristic.heat_index", 0x2a7a_u32), + ("org.bluetooth.characteristic.height", 0x2a8e_u32), + ("org.bluetooth.characteristic.hid_control_point", 0x2a4c_u32), + ("org.bluetooth.characteristic.hid_information", 0x2a4a_u32), + ("org.bluetooth.characteristic.hip_circumference", 0x2a8f_u32), + ("org.bluetooth.characteristic.http_control_point", 0x2aba_u32), + ("org.bluetooth.characteristic.http_entity_body", 0x2ab9_u32), + ("org.bluetooth.characteristic.http_headers", 0x2ab7_u32), + ("org.bluetooth.characteristic.http_status_code", 0x2ab8_u32), + ("org.bluetooth.characteristic.https_security", 0x2abb_u32), + ("org.bluetooth.characteristic.humidity", 0x2a6f_u32), + ("org.bluetooth.characteristic.ieee_11073-20601_regulatory_certification_data_list", 0x2a2a_u32), + ("org.bluetooth.characteristic.indoor_positioning_configuration", 0x2aad_u32), + ("org.bluetooth.characteristic.intermediate_cuff_pressure", 0x2a36_u32), + ("org.bluetooth.characteristic.intermediate_temperature", 0x2a1e_u32), + ("org.bluetooth.characteristic.irradiance", 0x2a77_u32), + ("org.bluetooth.characteristic.language", 0x2aa2_u32), + ("org.bluetooth.characteristic.last_name", 0x2a90_u32), + ("org.bluetooth.characteristic.latitude", 0x2aae_u32), + ("org.bluetooth.characteristic.ln_control_point", 0x2a6b_u32), + ("org.bluetooth.characteristic.ln_feature", 0x2a6a_u32), + ("org.bluetooth.characteristic.local_east_coordinate.xml", 0x2ab1_u32), + ("org.bluetooth.characteristic.local_north_coordinate", 0x2ab0_u32), + ("org.bluetooth.characteristic.local_time_information", 0x2a0f_u32), + ("org.bluetooth.characteristic.location_and_speed", 0x2a67_u32), + ("org.bluetooth.characteristic.location_name", 0x2ab5_u32), + ("org.bluetooth.characteristic.longitude", 0x2aaf_u32), + ("org.bluetooth.characteristic.magnetic_declination", 0x2a2c_u32), + ("org.bluetooth.characteristic.magnetic_flux_density_2d", 0x2aa0_u32), + ("org.bluetooth.characteristic.magnetic_flux_density_3d", 0x2aa1_u32), + ("org.bluetooth.characteristic.manufacturer_name_string", 0x2a29_u32), + ("org.bluetooth.characteristic.maximum_recommended_heart_rate", 0x2a91_u32), + ("org.bluetooth.characteristic.measurement_interval", 0x2a21_u32), + ("org.bluetooth.characteristic.model_number_string", 0x2a24_u32), + ("org.bluetooth.characteristic.navigation", 0x2a68_u32), + ("org.bluetooth.characteristic.new_alert", 0x2a46_u32), + ("org.bluetooth.characteristic.object_action_control_point", 0x2ac5_u32), + ("org.bluetooth.characteristic.object_changed", 0x2ac8_u32), + ("org.bluetooth.characteristic.object_first_created", 0x2ac1_u32), + ("org.bluetooth.characteristic.object_id", 0x2ac3_u32), + ("org.bluetooth.characteristic.object_last_modified", 0x2ac2_u32), + ("org.bluetooth.characteristic.object_list_control_point", 0x2ac6_u32), + ("org.bluetooth.characteristic.object_list_filter", 0x2ac7_u32), + ("org.bluetooth.characteristic.object_name", 0x2abe_u32), + ("org.bluetooth.characteristic.object_properties", 0x2ac4_u32), + ("org.bluetooth.characteristic.object_size", 0x2ac0_u32), + ("org.bluetooth.characteristic.object_type", 0x2abf_u32), + ("org.bluetooth.characteristic.ots_feature", 0x2abd_u32), + ("org.bluetooth.characteristic.gap.peripheral_preferred_connection_parameters", 0x2a04_u32), + ("org.bluetooth.characteristic.gap.peripheral_privacy_flag", 0x2a02_u32), + ("org.bluetooth.characteristic.plx_continuous_measurement", 0x2a5f_u32), + ("org.bluetooth.characteristic.plx_features", 0x2a60_u32), + ("org.bluetooth.characteristic.plx_spot_check_measurement", 0x2a5e_u32), + ("org.bluetooth.characteristic.pnp_id", 0x2a50_u32), + ("org.bluetooth.characteristic.pollen_concentration", 0x2a75_u32), + ("org.bluetooth.characteristic.position_quality", 0x2a69_u32), + ("org.bluetooth.characteristic.pressure", 0x2a6d_u32), + ("org.bluetooth.characteristic.protocol_mode", 0x2a4e_u32), + ("org.bluetooth.characteristic.rainfall", 0x2a78_u32), + ("org.bluetooth.characteristic.gap.reconnection_address", 0x2a03_u32), + ("org.bluetooth.characteristic.record_access_control_point", 0x2a52_u32), + ("org.bluetooth.characteristic.reference_time_information", 0x2a14_u32), + ("org.bluetooth.characteristic.report", 0x2a4d_u32), + ("org.bluetooth.characteristic.report_map", 0x2a4b_u32), + ("org.bluetooth.characteristic.resting_heart_rate", 0x2a92_u32), + ("org.bluetooth.characteristic.ringer_control_point", 0x2a40_u32), + ("org.bluetooth.characteristic.ringer_setting", 0x2a41_u32), + ("org.bluetooth.characteristic.rsc_feature", 0x2a54_u32), + ("org.bluetooth.characteristic.rsc_measurement", 0x2a53_u32), + ("org.bluetooth.characteristic.sc_control_point", 0x2a55_u32), + ("org.bluetooth.characteristic.scan_interval_window", 0x2a4f_u32), + ("org.bluetooth.characteristic.scan_refresh", 0x2a31_u32), + ("org.bluetooth.characteristic.sensor_location", 0x2a5d_u32), + ("org.bluetooth.characteristic.serial_number_string", 0x2a25_u32), + ("org.bluetooth.characteristic.gatt.service_changed", 0x2a05_u32), + ("org.bluetooth.characteristic.software_revision_string", 0x2a28_u32), + ("org.bluetooth.characteristic.sport_type_for_aerobic_and_anaerobic_thresholds", 0x2a93_u32), + ("org.bluetooth.characteristic.supported_new_alert_category", 0x2a47_u32), + ("org.bluetooth.characteristic.supported_unread_alert_category", 0x2a48_u32), + ("org.bluetooth.characteristic.system_id", 0x2a23_u32), + ("org.bluetooth.characteristic.tds_control_point", 0x2abc_u32), + ("org.bluetooth.characteristic.temperature", 0x2a6e_u32), + ("org.bluetooth.characteristic.temperature_measurement", 0x2a1c_u32), + ("org.bluetooth.characteristic.temperature_type", 0x2a1d_u32), + ("org.bluetooth.characteristic.three_zone_heart_rate_limits", 0x2a94_u32), + ("org.bluetooth.characteristic.time_accuracy", 0x2a12_u32), + ("org.bluetooth.characteristic.time_source", 0x2a13_u32), + ("org.bluetooth.characteristic.time_update_control_point", 0x2a16_u32), + ("org.bluetooth.characteristic.time_update_state", 0x2a17_u32), + ("org.bluetooth.characteristic.time_with_dst", 0x2a11_u32), + ("org.bluetooth.characteristic.time_zone", 0x2a0e_u32), + ("org.bluetooth.characteristic.true_wind_direction", 0x2a71_u32), + ("org.bluetooth.characteristic.true_wind_speed", 0x2a70_u32), + ("org.bluetooth.characteristic.two_zone_heart_rate_limit", 0x2a95_u32), + ("org.bluetooth.characteristic.tx_power_level", 0x2a07_u32), + ("org.bluetooth.characteristic.uncertainty", 0x2ab4_u32), + ("org.bluetooth.characteristic.unread_alert_status", 0x2a45_u32), + ("org.bluetooth.characteristic.uri", 0x2ab6_u32), + ("org.bluetooth.characteristic.user_control_point", 0x2a9f_u32), + ("org.bluetooth.characteristic.user_index", 0x2a9a_u32), + ("org.bluetooth.characteristic.uv_index", 0x2a76_u32), + ("org.bluetooth.characteristic.vo2_max", 0x2a96_u32), + ("org.bluetooth.characteristic.waist_circumference", 0x2a97_u32), + ("org.bluetooth.characteristic.weight", 0x2a98_u32), + ("org.bluetooth.characteristic.weight_measurement", 0x2a9d_u32), + ("org.bluetooth.characteristic.weight_scale_feature", 0x2a9e_u32), + ("org.bluetooth.characteristic.wind_chill", 0x2a79_u32), ]; -const BLUETOOTH_ASSIGNED_DESCRIPTORS: &'static [(&'static str, u32)] = &[ -//TODO(zakorgy) create all the descriptors //https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx +const BLUETOOTH_ASSIGNED_DESCRIPTORS: &'static [(&'static str, u32)] = &[ ("org.bluetooth.descriptor.gatt.characteristic_extended_properties", 0x2900_u32), - ("org.bluetooth.descriptor.gatt.characteristic_user_description", 0x2901_u32) + ("org.bluetooth.descriptor.gatt.characteristic_user_description", 0x2901_u32), + ("org.bluetooth.descriptor.gatt.client_characteristic_configuration", 0x2902_u32), + ("org.bluetooth.descriptor.gatt.server_characteristic_configuration", 0x2903_u32), + ("org.bluetooth.descriptor.gatt.characteristic_presentation_format", 0x2904_u32), + ("org.bluetooth.descriptor.gatt.characteristic_aggregate_format", 0x2905_u32), + ("org.bluetooth.descriptor.valid_range", 0x2906_u32), + ("org.bluetooth.descriptor.external_report_reference", 0x2907_u32), + ("org.bluetooth.descriptor.report_reference", 0x2908_u32), + ("org.bluetooth.descriptor.number_of_digitals", 0x2909_u32), + ("org.bluetooth.descriptor.value_trigger_setting", 0x290a_u32), + ("org.bluetooth.descriptor.es_configuration", 0x290b_u32), + ("org.bluetooth.descriptor.es_measurement", 0x290c_u32), + ("org.bluetooth.descriptor.es_trigger_setting", 0x290d_u32), + ("org.bluetooth.descriptor.time_trigger_setting", 0x290e_u32), ]; const BASE_UUID: &'static str = "-0000-1000-8000-00805f9b34fb"; From 9825ea41b49e4cff5ccccaef0dbeef9a982d7010 Mon Sep 17 00:00:00 2001 From: fokinv Date: Thu, 17 Mar 2016 11:57:20 +0100 Subject: [PATCH 03/15] Add Bluetooth IPC support --- components/compositing/constellation.rs | 11 + components/compositing/pipeline.rs | 6 + components/net/Cargo.toml | 1 + components/net/bluetooth_thread.rs | 522 ++++++++++++++++++ components/net/lib.rs | 2 + components/net_traits/bluetooth_thread.rs | 69 +++ components/net_traits/lib.rs | 1 + components/script/dom/bluetooth.rs | 65 ++- .../dom/bluetoothremotegattcharacteristic.rs | 107 +++- .../dom/bluetoothremotegattdescriptor.rs | 85 ++- .../script/dom/bluetoothremotegattserver.rs | 84 ++- .../script/dom/bluetoothremotegattservice.rs | 70 ++- .../script/dom/webidls/BluetoothDevice.webidl | 3 +- .../BluetoothRemoteGATTCharacteristic.webidl | 4 +- .../BluetoothRemoteGATTDescriptor.webidl | 3 +- components/script/dom/window.rs | 11 + components/script/script_thread.rs | 5 + components/script_traits/lib.rs | 3 + components/servo/Cargo.lock | 27 + components/servo/lib.rs | 4 + 20 files changed, 1037 insertions(+), 46 deletions(-) create mode 100644 components/net/bluetooth_thread.rs create mode 100644 components/net_traits/bluetooth_thread.rs diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 34c7dfcf3a9..8a61ca418d7 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -36,6 +36,7 @@ use msg::constellation_msg::{PipelineNamespace, PipelineNamespaceId, NavigationD use msg::constellation_msg::{SubpageId, WindowSizeData, WindowSizeType}; use msg::constellation_msg::{self, ConstellationChan, PanicMsg}; use msg::webdriver_msg; +use net_traits::bluetooth_thread::BluetoothMethodMsg; use net_traits::image_cache_thread::ImageCacheThread; use net_traits::storage_thread::{StorageThread, StorageThreadMsg}; use net_traits::{self, ResourceThread}; @@ -123,6 +124,9 @@ pub struct Constellation { /// A channel through which messages can be sent to the developer tools. devtools_chan: Option>, + /// A channel through which messages can be sent to the bluetooth thread. + bluetooth_thread: IpcSender, + /// A channel through which messages can be sent to the storage thread. storage_thread: StorageThread, @@ -197,6 +201,8 @@ pub struct InitialConstellationState { pub compositor_proxy: Box, /// A channel to the developer tools, if applicable. pub devtools_chan: Option>, + /// A channel to the bluetooth thread. + pub bluetooth_thread: IpcSender, /// A channel to the image cache thread. pub image_cache_thread: ImageCacheThread, /// A channel to the font cache thread. @@ -338,6 +344,7 @@ impl Constellation panic_receiver: panic_receiver, compositor_proxy: state.compositor_proxy, devtools_chan: state.devtools_chan, + bluetooth_thread: state.bluetooth_thread, resource_thread: state.resource_thread, image_cache_thread: state.image_cache_thread, font_cache_thread: state.font_cache_thread, @@ -424,6 +431,7 @@ impl Constellation scheduler_chan: self.scheduler_chan.clone(), compositor_proxy: self.compositor_proxy.clone_compositor_proxy(), devtools_chan: self.devtools_chan.clone(), + bluetooth_thread: self.bluetooth_thread.clone(), image_cache_thread: self.image_cache_thread.clone(), font_cache_thread: self.font_cache_thread.clone(), resource_thread: self.resource_thread.clone(), @@ -840,6 +848,9 @@ impl Constellation if let Err(e) = self.storage_thread.send(StorageThreadMsg::Exit) { warn!("Exit storage thread failed ({})", e); } + if let Err(e) = self.bluetooth_thread.send(BluetoothMethodMsg::Exit) { + warn!("Exit bluetooth thread failed ({})", e); + } self.font_cache_thread.exit(); self.compositor_proxy.send(ToCompositorMsg::ShutdownComplete); } diff --git a/components/compositing/pipeline.rs b/components/compositing/pipeline.rs index 9facc11829c..ca44fa49faf 100644 --- a/components/compositing/pipeline.rs +++ b/components/compositing/pipeline.rs @@ -18,6 +18,7 @@ use msg::constellation_msg::{ConstellationChan, PanicMsg, FrameId, PipelineId, S use msg::constellation_msg::{LoadData, WindowSizeData}; use msg::constellation_msg::{PipelineNamespaceId}; use net_traits::ResourceThread; +use net_traits::bluetooth_thread::BluetoothMethodMsg; use net_traits::image_cache_thread::ImageCacheThread; use net_traits::storage_thread::StorageThread; use profile_traits::mem as profile_mem; @@ -92,6 +93,8 @@ pub struct InitialPipelineState { pub compositor_proxy: Box, /// A channel to the developer tools, if applicable. pub devtools_chan: Option>, + /// A channel to the bluetooth thread. + pub bluetooth_thread: IpcSender, /// A channel to the image cache thread. pub image_cache_thread: ImageCacheThread, /// A channel to the font cache thread. @@ -214,6 +217,7 @@ impl Pipeline { constellation_chan: state.constellation_chan, scheduler_chan: state.scheduler_chan, devtools_chan: script_to_devtools_chan, + bluetooth_thread: state.bluetooth_thread, image_cache_thread: state.image_cache_thread, font_cache_thread: state.font_cache_thread.clone(), resource_thread: state.resource_thread, @@ -390,6 +394,7 @@ pub struct UnprivilegedPipelineContent { scheduler_chan: IpcSender, devtools_chan: Option>, script_to_compositor_chan: IpcSender, + bluetooth_thread: IpcSender, image_cache_thread: ImageCacheThread, font_cache_thread: FontCacheThread, resource_thread: ResourceThread, @@ -430,6 +435,7 @@ impl UnprivilegedPipelineContent { layout_to_constellation_chan: self.layout_to_constellation_chan.clone(), scheduler_chan: self.scheduler_chan.clone(), panic_chan: self.panic_chan.clone(), + bluetooth_thread: self.bluetooth_thread.clone(), resource_thread: self.resource_thread, storage_thread: self.storage_thread.clone(), image_cache_thread: self.image_cache_thread.clone(), diff --git a/components/net/Cargo.toml b/components/net/Cargo.toml index 80437830a24..5d139ea5191 100644 --- a/components/net/Cargo.toml +++ b/components/net/Cargo.toml @@ -17,6 +17,7 @@ plugins = {path = "../plugins"} msg = {path = "../msg"} ipc-channel = {git = "https://github.com/servo/ipc-channel"} webrender_traits = {git = "https://github.com/servo/webrender_traits"} +device = {git = "https://github.com/servo/devices"} cookie = { version = "0.2.4", features = [ "serialize-rustc" ] } flate2 = "0.2.0" hyper = { version = "0.9", features = [ "serde-serialization" ] } diff --git a/components/net/bluetooth_thread.rs b/components/net/bluetooth_thread.rs new file mode 100644 index 00000000000..e2bb015673e --- /dev/null +++ b/components/net/bluetooth_thread.rs @@ -0,0 +1,522 @@ +/* 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 device::bluetooth::BluetoothAdapter; +use device::bluetooth::BluetoothDevice; +use device::bluetooth::BluetoothGATTCharacteristic; +use device::bluetooth::BluetoothGATTDescriptor; +use device::bluetooth::BluetoothGATTService; +use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; +use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg}; +use std::borrow::ToOwned; +use std::collections::HashMap; +use std::string::String; +use util::thread::spawn_named; + +macro_rules! send_error( + ($sender:expr, $error:expr) => ( + return $sender.send(BluetoothObjectMsg::Error { error: String::from($error) }).unwrap(); + ); +); + +macro_rules! check_cache( + ($cache:expr, $key:expr) => ( + if $cache.contains_key($key) { + return $cache.get($key); + } + ); +); + +pub trait BluetoothThreadFactory { + fn new() -> Self; +} + +impl BluetoothThreadFactory for IpcSender { + fn new() -> IpcSender { + let (sender, receiver) = ipc::channel().unwrap(); + let adapter = match BluetoothAdapter::init() { + Ok(a) => Some(a), + Err(_) => None, + }; + spawn_named("BluetoothThread".to_owned(), move || { + BluetoothManager::new(receiver, adapter).start(); + }); + sender + } +} + +pub struct BluetoothManager { + receiver: IpcReceiver, + adapter: Option, + service_to_device: HashMap, + characteristic_to_service: HashMap, + descriptor_to_characteristic: HashMap, + cached_devices: HashMap, + cached_services: HashMap, + cached_characteristics: HashMap, + cached_descriptors: HashMap, +} + +impl BluetoothManager { + pub fn new (receiver: IpcReceiver, adapter: Option) -> BluetoothManager { + BluetoothManager { + receiver: receiver, + adapter: adapter, + service_to_device: HashMap::new(), + characteristic_to_service: HashMap::new(), + descriptor_to_characteristic: HashMap::new(), + cached_devices: HashMap::new(), + cached_services: HashMap::new(), + cached_characteristics: HashMap::new(), + cached_descriptors: HashMap::new(), + } + } + + fn start(&mut self) { + loop { + match self.receiver.recv().unwrap() { + BluetoothMethodMsg::RequestDevice(sender) => { + self.request_device(sender) + } + BluetoothMethodMsg::GATTServerConnect(device_id, sender) => { + self.gatt_server_connect(device_id, sender) + } + BluetoothMethodMsg::GATTServerDisconnect(device_id, sender) => { + self.gatt_server_disconnect(device_id, sender) + } + BluetoothMethodMsg::GetPrimaryService(device_id, sender) => { + self.get_primary_service(device_id, sender) + } + BluetoothMethodMsg::GetCharacteristic(service_id, sender) => { + self.get_characteristic(service_id, sender) + } + BluetoothMethodMsg::GetDescriptor(characteristic_id, sender) => { + self.get_descriptor(characteristic_id, sender) + } + BluetoothMethodMsg::ReadValue(id, sender) => { + self.read_value(id, sender) + } + BluetoothMethodMsg::WriteValue(id, value, sender) => { + self.write_value(id, value, sender) + } + BluetoothMethodMsg::Exit => { + break + } + } + } + } + + // Adapter + + fn get_adapter(&mut self) -> Option { + if self.adapter.is_none() + || self.adapter.clone().unwrap().get_address().is_err() { + self.adapter = BluetoothAdapter::init().ok(); + } + self.adapter.clone() + } + + // Device + + fn get_devices(&mut self, adapter: &mut BluetoothAdapter) -> Vec { + let devices = adapter.get_devices().unwrap_or(vec!()); + for device in &devices { + self.cached_devices.insert(device.get_address().unwrap_or("".to_owned()), device.clone()); + } + devices + } + + fn get_device(&mut self, adapter: &mut BluetoothAdapter, device_id: &str) -> Option<&BluetoothDevice> { + check_cache!(self.cached_devices, device_id); + // Update cache + self.get_devices(adapter); + check_cache!(self.cached_devices, device_id); + None + } + + // Service + + fn get_gatt_services(&mut self, adapter: &mut BluetoothAdapter, device_id: &str) -> Vec { + let services = match self.get_device(adapter, device_id) { + Some(d) => d.get_gatt_services().unwrap_or(vec!()), + None => vec!(), + }; + for service in &services { + self.cached_services.insert(service.get_object_path(), service.clone()); + self.service_to_device.insert(service.get_object_path(), device_id.to_owned()); + } + services + } + + fn get_gatt_service(&mut self, + adapter: &mut BluetoothAdapter, + service_id: &str) + -> Option<&BluetoothGATTService> { + check_cache!(self.cached_services, service_id); + let device_id = match self.service_to_device.get_mut(service_id) { + Some(d) => d.clone(), + None => return None, + }; + // Update cache + self.get_gatt_services(adapter, &device_id); + check_cache!(self.cached_services, service_id); + None + } + + #[allow(dead_code)] + fn get_gatt_service_by_uuid(&mut self, + adapter: &mut BluetoothAdapter, + device_id: &str, + service_uuid: &str) + -> Option { + for service in self.cached_services.values() { + if service.get_uuid().unwrap_or("".to_owned()) == service_uuid { + return Some(service.clone()); + } + } + // Update cache + let services = self.get_gatt_services(adapter, device_id); + for service in services { + if service.get_uuid().unwrap_or("".to_owned()) == service_uuid { + return Some(service.clone()); + } + } + None + } + + // Characteristic + + fn get_gatt_characteristics(&mut self, + adapter: &mut BluetoothAdapter, + service_id: &str) + -> Vec { + let characteristics = match self.get_gatt_service(adapter, service_id) { + Some(s) => s.get_gatt_characteristics().unwrap_or(vec!()), + None => vec!(), + }; + + for characteristic in &characteristics { + self.cached_characteristics.insert(characteristic.get_object_path(), characteristic.clone()); + self.characteristic_to_service.insert(characteristic.get_object_path(), service_id.to_owned()); + } + characteristics + } + + fn get_gatt_characteristic(&mut self, + adapter: &mut BluetoothAdapter, + characteristic_id: &str) + -> Option<&BluetoothGATTCharacteristic> { + check_cache!(self.cached_characteristics, characteristic_id); + let service_id = match self.characteristic_to_service.get_mut(characteristic_id) { + Some(s) => s.clone(), + None => return None, + }; + // Update cache + self.get_gatt_characteristics(adapter, &service_id); + check_cache!(self.cached_characteristics, characteristic_id); + None + } + + #[allow(dead_code)] + fn get_gatt_characteristic_by_uuid(&mut self, + adapter: &mut BluetoothAdapter, + service_id: &str, + characteristic_uuid: &str) + -> Option { + for characteristic in self.cached_characteristics.values() { + if characteristic.get_uuid().unwrap_or("".to_owned()) == characteristic_uuid { + return Some(characteristic.clone()); + } + } + // Update cache + let characteristics = self.get_gatt_characteristics(adapter, service_id); + for characteristic in characteristics { + if characteristic.get_uuid().unwrap_or("".to_owned()) == characteristic_uuid { + return Some(characteristic.clone()); + } + } + None + } + + fn get_characteristic_properties(&self, characteristic: &BluetoothGATTCharacteristic) -> [bool; 9] { + let mut props = [false; 9]; + let flags = characteristic.get_flags().unwrap_or(vec!()); + for flag in flags { + match flag.as_ref() { + "broadcast" => props[0] = true, + "read" => props[1] = true, + "write_without_response" => props[2] = true, + "write" => props[3] = true, + "notify" => props[4] = true, + "indicate" => props[5] = true, + "authenticated_signed_writes" => props[6] = true, + "reliable_write" => props[7] = true, + "writable_auxiliaries" => props[8] = true, + _ => (), + } + } + props + } + + // Descriptor + + fn get_gatt_descriptors(&mut self, + adapter: &mut BluetoothAdapter, + characteristic_id: &str) + -> Vec { + let descriptors = match self.get_gatt_characteristic(adapter, characteristic_id) { + Some(c) => c.get_gatt_descriptors().unwrap_or(vec!()), + None => vec!(), + }; + + for descriptor in &descriptors { + self.cached_descriptors.insert(descriptor.get_object_path(), descriptor.clone()); + self.descriptor_to_characteristic.insert(descriptor.get_object_path(), characteristic_id.to_owned()); + } + descriptors + } + + fn get_gatt_descriptor(&mut self, + adapter: &mut BluetoothAdapter, + descriptor_id: &str) + -> Option<&BluetoothGATTDescriptor> { + check_cache!(self.cached_descriptors, descriptor_id); + let characteristic_id = match self.descriptor_to_characteristic.get_mut(descriptor_id) { + Some(c) => c.clone(), + None => return None, + }; + // Update cache + self.get_gatt_descriptors(adapter, &characteristic_id); + check_cache!(self.cached_descriptors, descriptor_id); + None + } + + #[allow(dead_code)] + fn get_gatt_descriptor_by_uuid(&mut self, + adapter: &mut BluetoothAdapter, + characteristic_id: &str, + descriptor_uuid: &str) + -> Option { + for descriptor in self.cached_descriptors.values() { + if descriptor.get_uuid().unwrap_or("".to_owned()) == descriptor_uuid { + return Some(descriptor.clone()); + } + } + // Update cache + let descriptors = self.get_gatt_descriptors(adapter, characteristic_id); + for descriptor in descriptors { + if descriptor.get_uuid().unwrap_or("".to_owned()) == descriptor_uuid { + return Some(descriptor.clone()); + } + } + None + } + + // Methods + + fn request_device(&mut self, sender: IpcSender) { + let mut adapter = match self.get_adapter() { + Some(a) => a, + None => send_error!(sender, "No adapter found"), + }; + let devices = self.get_devices(&mut adapter); + if devices.is_empty() { + send_error!(sender, "No device found"); + } + + //TODO select the proper device + let device = &devices[0]; + + let message = BluetoothObjectMsg::BluetoothDevice { + id: device.get_address().unwrap_or("".to_owned()), + name: device.get_name().ok(), + device_class: device.get_class().ok(), + vendor_id_source: device.get_vendor_id_source().ok(), + vendor_id: device.get_vendor_id().ok(), + product_id: device.get_product_id().ok(), + product_version: device.get_device_id().ok(), + appearance: device.get_appearance().ok(), + tx_power: match device.get_tx_power() { + Ok(p) => Some(p as i8), + Err(_) => None, + }, + rssi: match device.get_rssi() { + Ok(p) => Some(p as i8), + Err(_) => None, + } + }; + sender.send(message).unwrap(); + } + + pub fn gatt_server_connect(&mut self, device_id: String, sender: IpcSender) { + let mut adapter = match self.get_adapter() { + Some(a) => a, + None => send_error!(sender, "No adapter found"), + }; + + let connected = match self.get_device(&mut adapter, &device_id) { + Some(d) => { + if d.is_connected().unwrap_or(false) { + true + } else { + !d.connect().is_err() + } + } + None => send_error!(sender, "No device found"), + }; + + let message = BluetoothObjectMsg::BluetoothServer { + connected: connected + }; + sender.send(message).unwrap(); + } + + pub fn gatt_server_disconnect(&mut self, device_id: String, sender: IpcSender) { + let mut adapter = match self.get_adapter() { + Some(a) => a, + None => send_error!(sender, "No adapter found"), + }; + + let connected = match self.get_device(&mut adapter, &device_id) { + Some(d) => { + if d.is_connected().unwrap_or(false) { + d.disconnect().is_err() + } else { + false + } + } + None => send_error!(sender, "No device found"), + }; + + let message = BluetoothObjectMsg::BluetoothServer { + connected: connected + }; + sender.send(message).unwrap(); + } + + pub fn get_primary_service(&mut self, device_id: String, sender: IpcSender) { + let mut adapter = match self.get_adapter() { + Some(a) => a, + None => send_error!(sender, "No adapter found"), + }; + + let services = self.get_gatt_services(&mut adapter, &device_id); + if services.is_empty() { + send_error!(sender, "No service found"); + } + + for service in services { + if service.is_primary().unwrap_or(false) { + let message = BluetoothObjectMsg::BluetoothService { + uuid: service.get_uuid().unwrap_or("".to_owned()), + is_primary: true, + instance_id: service.get_object_path() + }; + sender.send(message).unwrap(); + return; + } + } + + send_error!(sender, "No primary service found"); + } + + pub fn get_characteristic(&mut self, service_id: String, sender: IpcSender) { + let mut adapter = match self.get_adapter() { + Some(a) => a, + None => send_error!(sender, "No adapter found"), + }; + + let characteristics = self.get_gatt_characteristics(&mut adapter, &service_id); + if characteristics.is_empty() { + send_error!(sender, "No characteristic found"); + } + + let characteristic = &characteristics[0]; + let properties = self.get_characteristic_properties(&characteristic); + let message = BluetoothObjectMsg::BluetoothCharacteristic { + uuid: characteristic.get_uuid().unwrap_or("".to_owned()), + instance_id: characteristic.get_object_path(), + broadcast: properties[0], + read: properties[1], + write_without_response: properties[2], + write: properties[3], + notify: properties[4], + indicate: properties[5], + authenticated_signed_writes: properties[6], + reliable_write: properties[7], + writable_auxiliaries: properties[8] + }; + sender.send(message).unwrap(); + } + + pub fn get_descriptor(&mut self, characteristic_id: String, sender: IpcSender) { + let mut adapter = match self.get_adapter() { + Some(a) => a, + None => send_error!(sender, "No adapter found"), + }; + + let descriptors = self.get_gatt_descriptors(&mut adapter, &characteristic_id); + if descriptors.is_empty() { + send_error!(sender, "No descriptor found"); + } + + let descriptor = &descriptors[0]; + let message = BluetoothObjectMsg::BluetoothDescriptor { + uuid: descriptor.get_uuid().unwrap_or("".to_owned()), + instance_id: descriptor.get_object_path(), + }; + sender.send(message).unwrap(); + } + + pub fn read_value(&mut self, id: String, sender: IpcSender) { + let mut adapter = match self.get_adapter() { + Some(a) => a, + None => send_error!(sender, "No adapter found"), + }; + let mut value = match self.get_gatt_characteristic(&mut adapter, &id) { + Some(c) => Some(c.read_value().unwrap_or(vec!())), + None => None, + }; + if value.is_none() { + value = match self.get_gatt_descriptor(&mut adapter, &id) { + Some(d) => Some(d.read_value().unwrap_or(vec!())), + None => None, + }; + } + + let message = match value { + Some(v) => BluetoothObjectMsg::BluetoothReadValue { value: v }, + None => send_error!(sender, "No characteristic or descriptor found with that id"), + }; + + sender.send(message).unwrap(); + } + + pub fn write_value(&mut self, id: String, value: Vec, sender: IpcSender) { + let mut adapter = match self.get_adapter() { + Some(a) => a, + None => send_error!(sender, "No adapter found"), + }; + let mut result = match self.get_gatt_characteristic(&mut adapter, &id) { + Some(c) => Some(c.write_value(value.clone())), + None => None, + }; + if result.is_none() { + result = match self.get_gatt_descriptor(&mut adapter, &id) { + Some(d) => Some(d.write_value(value.clone())), + None => None, + }; + } + + let message = match result { + Some(v) => match v { + Ok(_) => BluetoothObjectMsg::BluetoothWriteValue, + Err(e) => send_error!(sender, e.to_string()), + }, + None => send_error!(sender, "No characteristic or descriptor found with that id"), + }; + + sender.send(message).unwrap(); + } +} diff --git a/components/net/lib.rs b/components/net/lib.rs index 97b978f1725..0f6c508fc0a 100644 --- a/components/net/lib.rs +++ b/components/net/lib.rs @@ -13,6 +13,7 @@ extern crate brotli; extern crate cookie as cookie_rs; +extern crate device; extern crate devtools_traits; extern crate flate2; extern crate hyper; @@ -39,6 +40,7 @@ extern crate webrender_traits; extern crate websocket; pub mod about_loader; +pub mod bluetooth_thread; pub mod chrome_loader; pub mod cookie; pub mod cookie_storage; diff --git a/components/net_traits/bluetooth_thread.rs b/components/net_traits/bluetooth_thread.rs new file mode 100644 index 00000000000..86bdffc1fff --- /dev/null +++ b/components/net_traits/bluetooth_thread.rs @@ -0,0 +1,69 @@ +/* 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 ipc_channel::ipc::IpcSender; + +#[derive(Deserialize, Serialize)] +pub enum BluetoothMethodMsg { + RequestDevice(IpcSender), + GATTServerConnect(String, IpcSender), + GATTServerDisconnect(String, IpcSender), + GetPrimaryService(String, IpcSender), + GetCharacteristic(String, IpcSender), + GetDescriptor(String, IpcSender), + ReadValue(String, IpcSender), + WriteValue(String, Vec, IpcSender), + Exit, +} + +#[derive(Deserialize, Serialize)] +pub enum BluetoothObjectMsg { + BluetoothDevice { + // Bluetooth Device properties + id: String, + name: Option, + device_class: Option, + vendor_id_source: Option, + vendor_id: Option, + product_id: Option, + product_version: Option, + // Advertisiong Data properties + appearance: Option, + tx_power: Option, + rssi: Option + }, + BluetoothServer { + connected: bool + }, + BluetoothService { + uuid: String, + is_primary: bool, + instance_id: String + }, + BluetoothCharacteristic { + // Characteristic + uuid: String, + instance_id: String, + // Characteristic properties + broadcast: bool, + read: bool, + write_without_response: bool, + write: bool, + notify: bool, + indicate: bool, + authenticated_signed_writes: bool, + reliable_write: bool, + writable_auxiliaries: bool + }, + BluetoothDescriptor { + uuid: String, + instance_id: String + }, + BluetoothReadValue { + value: Vec + }, + BluetoothWriteValue, + Error { + error: String + }, +} diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index f4b7a85e7c5..45895f63711 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -40,6 +40,7 @@ use std::thread; use url::Url; use websocket::header; +pub mod bluetooth_thread; pub mod hosts; pub mod image_cache_thread; pub mod net_error_list; diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs index 58d506dec45..36ac2a1f7e4 100644 --- a/components/script/dom/bluetooth.rs +++ b/components/script/dom/bluetooth.rs @@ -4,10 +4,15 @@ use dom::bindings::codegen::Bindings::BluetoothBinding; use dom::bindings::codegen::Bindings::BluetoothBinding::BluetoothMethods; +use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::VendorIDSource; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; +use dom::bluetoothadvertisingdata::BluetoothAdvertisingData; use dom::bluetoothdevice::BluetoothDevice; +use ipc_channel::ipc::{self, IpcSender}; +use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg}; +use util::str::DOMString; // https://webbluetoothcg.github.io/web-bluetooth/#bluetooth #[dom_struct] @@ -27,13 +32,67 @@ impl Bluetooth { global, BluetoothBinding::Wrap) } + + fn get_bluetooth_thread(&self) -> IpcSender { + let global_root = self.global(); + let global_ref = global_root.r(); + global_ref.as_window().bluetooth_thread() + } } impl BluetoothMethods for Bluetooth { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice fn RequestDevice(&self) -> Option> { - //UNIMPLEMENTED - None + let (sender, receiver) = ipc::channel().unwrap(); + self.get_bluetooth_thread().send(BluetoothMethodMsg::RequestDevice(sender)).unwrap(); + let device = receiver.recv().unwrap(); + match device { + BluetoothObjectMsg::BluetoothDevice { + id, + name, + device_class, + vendor_id_source, + vendor_id, + product_id, + product_version, + appearance, + tx_power, + rssi, + } => { + let ad_data = &BluetoothAdvertisingData::new(self.global().r(), + appearance, + tx_power, + rssi); + let vendor_id_source = match vendor_id_source { + Some(vid) => match vid.as_ref() { + "bluetooth" => Some(VendorIDSource::Bluetooth), + "usb" => Some(VendorIDSource::Usb), + _ => Some(VendorIDSource::Unknown), + }, + None => None, + }; + let name = match name { + Some(n) => Some(DOMString::from(n)), + None => None, + }; + Some(BluetoothDevice::new(self.global().r(), + DOMString::from(id), + name, + ad_data, + device_class, + vendor_id_source, + vendor_id, + product_id, + product_version)) + }, + BluetoothObjectMsg::Error { + error + } => { + println!("{}", error); + None + }, + _ => unreachable!() + } } } diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs index 4b05b347242..3ce8749979a 100644 --- a/components/script/dom/bluetoothremotegattcharacteristic.rs +++ b/components/script/dom/bluetoothremotegattcharacteristic.rs @@ -2,16 +2,24 @@ * 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::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding:: BluetoothRemoteGATTCharacteristicMethods; +use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; +use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods; +use dom::bindings::error::Error::Network; +use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; -use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::str::ByteString; use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties; use dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor; use dom::bluetoothremotegattservice::BluetoothRemoteGATTService; +use ipc_channel::ipc::{self, IpcSender}; +use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg}; use util::str::DOMString; // https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattcharacteristic @@ -21,34 +29,49 @@ pub struct BluetoothRemoteGATTCharacteristic { service: MutHeap>, uuid: DOMString, properties: MutHeap>, - value: Option, + value: DOMRefCell>, + instanceID: String, } impl BluetoothRemoteGATTCharacteristic { pub fn new_inherited(service: &BluetoothRemoteGATTService, uuid: DOMString, - properties: &BluetoothCharacteristicProperties) + properties: &BluetoothCharacteristicProperties, + instanceID: String) -> BluetoothRemoteGATTCharacteristic { BluetoothRemoteGATTCharacteristic { reflector_: Reflector::new(), service: MutHeap::new(service), uuid: uuid, properties: MutHeap::new(properties), - value: None, + value: DOMRefCell::new(None), + instanceID: instanceID, } } pub fn new(global: GlobalRef, service: &BluetoothRemoteGATTService, uuid: DOMString, - properties: &BluetoothCharacteristicProperties) + properties: &BluetoothCharacteristicProperties, + instanceID: String) -> Root { reflect_dom_object(box BluetoothRemoteGATTCharacteristic::new_inherited(service, uuid, - properties), + properties, + instanceID), global, BluetoothRemoteGATTCharacteristicBinding::Wrap) } + + fn get_bluetooth_thread(&self) -> IpcSender { + let global_root = self.global(); + let global_ref = global_root.r(); + global_ref.as_window().bluetooth_thread() + } + + pub fn get_instance_id(&self) -> String { + self.instanceID.clone() + } } impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteristic { @@ -70,18 +93,78 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor fn GetDescriptor(&self) -> Option> { - //UNIMPLEMENTED - None + let (sender, receiver) = ipc::channel().unwrap(); + self.get_bluetooth_thread().send( + BluetoothMethodMsg::GetDescriptor(self.get_instance_id(), sender)).unwrap(); + let descriptor = receiver.recv().unwrap(); + match descriptor { + BluetoothObjectMsg::BluetoothDescriptor { + uuid, + instance_id + } => { + Some(BluetoothRemoteGATTDescriptor::new(self.global().r(), + &self, + DOMString::from(uuid), + instance_id)) + }, + BluetoothObjectMsg::Error { + error + } => { + println!("{}", error); + None + }, + _ => unreachable!() + } } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-value fn GetValue(&self) -> Option { - self.value.clone() + self.value.borrow().clone() } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue - fn ReadValue(&self) -> ByteString { - //UNIMPLEMENTED - ByteString::new(vec!()) + fn ReadValue(&self) -> Fallible { + let (sender, receiver) = ipc::channel().unwrap(); + if !self.Service().Device().Gatt().Connected() { + Err(Network) + } + else { + self.get_bluetooth_thread().send( + BluetoothMethodMsg::ReadValue(self.get_instance_id(), sender)).unwrap(); + let result = receiver.recv().unwrap(); + let value = match result { + BluetoothObjectMsg::BluetoothReadValue { + value + } => { + Some(ByteString::new(value)) + }, + BluetoothObjectMsg::Error { + error + } => { + println!("{}", error); + None + }, + _ => unreachable!() + }; + *self.value.borrow_mut() = value; + Ok(self.GetValue().unwrap()) + } + } + + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue + fn WriteValue(&self, value: Vec) { + let (sender, receiver) = ipc::channel().unwrap(); + self.get_bluetooth_thread().send( + BluetoothMethodMsg::WriteValue(self.get_instance_id(), value, sender)).unwrap(); + let result = receiver.recv().unwrap(); + match result { + BluetoothObjectMsg::BluetoothWriteValue => (), + BluetoothObjectMsg::Error { + error + } => { + println!("{}", error); + }, + _ => unreachable!() + }; } } diff --git a/components/script/dom/bluetoothremotegattdescriptor.rs b/components/script/dom/bluetoothremotegattdescriptor.rs index 5812a2ea832..7b55e1d962e 100644 --- a/components/script/dom/bluetoothremotegattdescriptor.rs +++ b/components/script/dom/bluetoothremotegattdescriptor.rs @@ -2,13 +2,23 @@ * 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::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods; +use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding:: + BluetoothRemoteGATTCharacteristicMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTDescriptorBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTDescriptorBinding::BluetoothRemoteGATTDescriptorMethods; +use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; +use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods; +use dom::bindings::error::Error::Network; +use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; -use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::str::ByteString; use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic; +use ipc_channel::ipc::{self, IpcSender}; +use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg}; use util::str::DOMString; // http://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattdescriptor @@ -17,30 +27,45 @@ pub struct BluetoothRemoteGATTDescriptor { reflector_: Reflector, characteristic: MutHeap>, uuid: DOMString, - value: Option, + value: DOMRefCell>, + instanceID: String, } impl BluetoothRemoteGATTDescriptor { pub fn new_inherited(characteristic: &BluetoothRemoteGATTCharacteristic, - uuid: DOMString) + uuid: DOMString, + instanceID: String) -> BluetoothRemoteGATTDescriptor { BluetoothRemoteGATTDescriptor { reflector_: Reflector::new(), characteristic: MutHeap::new(characteristic), uuid: uuid, - value: None, + value: DOMRefCell::new(None), + instanceID: instanceID, } } pub fn new(global: GlobalRef, characteristic: &BluetoothRemoteGATTCharacteristic, - uuid: DOMString) + uuid: DOMString, + instanceID: String) -> Root{ reflect_dom_object(box BluetoothRemoteGATTDescriptor::new_inherited(characteristic, - uuid), + uuid, + instanceID), global, BluetoothRemoteGATTDescriptorBinding::Wrap) } + + fn get_bluetooth_thread(&self) -> IpcSender { + let global_root = self.global(); + let global_ref = global_root.r(); + global_ref.as_window().bluetooth_thread() + } + + pub fn get_instance_id(&self) -> String { + self.instanceID.clone() + } } impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor { @@ -57,12 +82,52 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-value fn GetValue(&self) -> Option { - self.value.clone() + self.value.borrow().clone() } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue - fn ReadValue(&self) -> ByteString { - //UNIMPLEMENTED - ByteString::new(vec!()) + fn ReadValue(&self) -> Fallible { + let (sender, receiver) = ipc::channel().unwrap(); + if !self.Characteristic().Service().Device().Gatt().Connected() { + Err(Network) + } + else { + self.get_bluetooth_thread().send( + BluetoothMethodMsg::ReadValue(self.get_instance_id(), sender)).unwrap(); + let result = receiver.recv().unwrap(); + let value = match result { + BluetoothObjectMsg::BluetoothReadValue { + value + } => { + Some(ByteString::new(value)) + }, + BluetoothObjectMsg::Error { + error + } => { + println!("{}", error); + None + }, + _ => unreachable!() + }; + *self.value.borrow_mut() = value; + Ok(self.GetValue().unwrap()) + } + } + + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue + fn WriteValue(&self, value: Vec) { + let (sender, receiver) = ipc::channel().unwrap(); + self.get_bluetooth_thread().send( + BluetoothMethodMsg::WriteValue(self.get_instance_id(), value, sender)).unwrap(); + let result = receiver.recv().unwrap(); + match result { + BluetoothObjectMsg::BluetoothWriteValue => (), + BluetoothObjectMsg::Error { + error + } => { + println!("{}", error); + }, + _ => unreachable!() + }; } } diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs index 7441344fe2f..2eec908d4c5 100644 --- a/components/script/dom/bluetoothremotegattserver.rs +++ b/components/script/dom/bluetoothremotegattserver.rs @@ -2,14 +2,18 @@ * 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::BluetoothRemoteGATTServerBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; -use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; use dom::bluetoothdevice::BluetoothDevice; use dom::bluetoothremotegattservice::BluetoothRemoteGATTService; +use ipc_channel::ipc::{self, IpcSender}; +use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg}; use std::cell::Cell; +use util::str::DOMString; // https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattserver #[dom_struct] @@ -20,21 +24,25 @@ pub struct BluetoothRemoteGATTServer { } impl BluetoothRemoteGATTServer { - pub fn new_inherited(device: &BluetoothDevice, is_connected: bool) -> BluetoothRemoteGATTServer { + pub fn new_inherited(device: &BluetoothDevice) -> BluetoothRemoteGATTServer { BluetoothRemoteGATTServer { reflector_: Reflector::new(), device: MutHeap::new(device), - connected: Cell::new(is_connected), + connected: Cell::new(false), } } - pub fn new(global: GlobalRef, device: &BluetoothDevice, connected: bool) -> Root { - reflect_dom_object(box BluetoothRemoteGATTServer::new_inherited( - device, - connected), + pub fn new(global: GlobalRef, device: &BluetoothDevice) -> Root { + reflect_dom_object(box BluetoothRemoteGATTServer::new_inherited(device), global, BluetoothRemoteGATTServerBinding::Wrap) } + + fn get_bluetooth_thread(&self) -> IpcSender { + let global_root = self.global(); + let global_ref = global_root.r(); + global_ref.as_window().bluetooth_thread() + } } impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { @@ -51,20 +59,72 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect fn Connect(&self) -> Root { - if !self.connected.get() { - self.connected.set(true); + let (sender, receiver) = ipc::channel().unwrap(); + self.get_bluetooth_thread().send( + BluetoothMethodMsg::GATTServerConnect(String::from(self.Device().Id()), sender)).unwrap(); + let server = receiver.recv().unwrap(); + match server { + BluetoothObjectMsg::BluetoothServer { + connected + } => { + self.connected.set(connected); + }, + BluetoothObjectMsg::Error { + error + } => { + println!("{}", error); + }, + _ => unreachable!() } Root::from_ref(self) } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-disconnect fn Disconnect(&self) { - self.connected.set(false); + let (sender, receiver) = ipc::channel().unwrap(); + self.get_bluetooth_thread().send( + BluetoothMethodMsg::GATTServerDisconnect(String::from(self.Device().Id()), sender)).unwrap(); + let server = receiver.recv().unwrap(); + match server { + BluetoothObjectMsg::BluetoothServer { + connected + } => { + self.connected.set(connected); + }, + BluetoothObjectMsg::Error { + error + } => { + println!("{}", error); + }, + _ => unreachable!() + } } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice fn GetPrimaryService(&self) -> Option> { - //UNIMPLEMENTED - None + let (sender, receiver) = ipc::channel().unwrap(); + self.get_bluetooth_thread().send( + BluetoothMethodMsg::GetPrimaryService(String::from(self.Device().Id()), sender)).unwrap(); + let service = receiver.recv().unwrap(); + match service { + BluetoothObjectMsg::BluetoothService { + uuid, + is_primary, + instance_id + } => { + Some(BluetoothRemoteGATTService::new(self.global().r(), + &self.device.get(), + DOMString::from(uuid), + is_primary, + instance_id)) + }, + BluetoothObjectMsg::Error { + error + } => { + println!("{}", error); + None + }, + _ => unreachable!() + } } } diff --git a/components/script/dom/bluetoothremotegattservice.rs b/components/script/dom/bluetoothremotegattservice.rs index af2cd70ce7c..433bf8ef9d8 100644 --- a/components/script/dom/bluetoothremotegattservice.rs +++ b/components/script/dom/bluetoothremotegattservice.rs @@ -6,9 +6,12 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; -use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; +use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties; use dom::bluetoothdevice::BluetoothDevice; use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic; +use ipc_channel::ipc::{self, IpcSender}; +use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg}; use util::str::DOMString; // https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattservice @@ -18,32 +21,47 @@ pub struct BluetoothRemoteGATTService { device: MutHeap>, uuid: DOMString, isPrimary: bool, + instanceID: String, } impl BluetoothRemoteGATTService { pub fn new_inherited(device: &BluetoothDevice, uuid: DOMString, - isPrimary: bool) + isPrimary: bool, + instanceID: String) -> BluetoothRemoteGATTService { BluetoothRemoteGATTService { reflector_: Reflector::new(), device: MutHeap::new(device), uuid: uuid, isPrimary: isPrimary, + instanceID: instanceID, } } pub fn new(global: GlobalRef, device: &BluetoothDevice, uuid: DOMString, - isPrimary: bool) + isPrimary: bool, + instanceID: String) -> Root { reflect_dom_object(box BluetoothRemoteGATTService::new_inherited(device, uuid, - isPrimary), + isPrimary, + instanceID), global, BluetoothRemoteGATTServiceBinding::Wrap) } + + fn get_bluetooth_thread(&self) -> IpcSender { + let global_root = self.global(); + let global_ref = global_root.r(); + global_ref.as_window().bluetooth_thread() + } + + pub fn get_instance_id(&self) -> String { + self.instanceID.clone() + } } impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { @@ -64,7 +82,47 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic fn GetCharacteristic(&self) -> Option> { - // UNIMPLEMENTED - None + let (sender, receiver) = ipc::channel().unwrap(); + self.get_bluetooth_thread().send( + BluetoothMethodMsg::GetCharacteristic(self.get_instance_id(), sender)).unwrap(); + let characteristic = receiver.recv().unwrap(); + match characteristic { + BluetoothObjectMsg::BluetoothCharacteristic { + uuid, + instance_id, + broadcast, + read, + write_without_response, + write, + notify, + indicate, + authenticated_signed_writes, + reliable_write, + writable_auxiliaries, + } => { + let properties = &BluetoothCharacteristicProperties::new(self.global().r(), + broadcast, + read, + write_without_response, + write, + notify, + indicate, + authenticated_signed_writes, + reliable_write, + writable_auxiliaries); + Some(BluetoothRemoteGATTCharacteristic::new(self.global().r(), + &self, + DOMString::from(uuid), + properties, + instance_id)) + }, + BluetoothObjectMsg::Error { + error + } => { + println!("{}", error); + None + }, + _ => unreachable!() + } } } diff --git a/components/script/dom/webidls/BluetoothDevice.webidl b/components/script/dom/webidls/BluetoothDevice.webidl index 3a32dc38179..e8851e6240c 100644 --- a/components/script/dom/webidls/BluetoothDevice.webidl +++ b/components/script/dom/webidls/BluetoothDevice.webidl @@ -7,7 +7,8 @@ // Allocation authorities for Vendor IDs: enum VendorIDSource { "bluetooth", - "usb" + "usb", + "unknown" }; [Pref="dom.bluetooth.enabled"] diff --git a/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl b/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl index e6ba9c89d2a..b3a1e691351 100644 --- a/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl +++ b/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl @@ -14,8 +14,10 @@ interface BluetoothRemoteGATTCharacteristic { //Promise getDescriptor(BluetoothDescriptorUUID descriptor); //Promise> //getDescriptors(optional BluetoothDescriptorUUID descriptor); - //Promise readValue(); + [Throws] ByteString readValue(); + //Promise readValue(); + void writeValue(sequence value); //Promise writeValue(BufferSource value); //Promise startNotifications(); //Promise stopNotifications(); diff --git a/components/script/dom/webidls/BluetoothRemoteGATTDescriptor.webidl b/components/script/dom/webidls/BluetoothRemoteGATTDescriptor.webidl index c7abe9e4859..77becb830bf 100644 --- a/components/script/dom/webidls/BluetoothRemoteGATTDescriptor.webidl +++ b/components/script/dom/webidls/BluetoothRemoteGATTDescriptor.webidl @@ -9,8 +9,9 @@ interface BluetoothRemoteGATTDescriptor { readonly attribute BluetoothRemoteGATTCharacteristic characteristic; readonly attribute DOMString uuid; readonly attribute ByteString? value; - + [Throws] ByteString readValue(); //Promise readValue(); + void writeValue(sequence value); //Promise writeValue(BufferSource value); }; diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 94b6d2c7fb3..9c75b92184e 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -47,6 +47,7 @@ use msg::constellation_msg::{ConstellationChan, LoadData, PipelineId, SubpageId} use msg::constellation_msg::{WindowSizeData, WindowSizeType}; use msg::webdriver_msg::{WebDriverJSError, WebDriverJSResult}; use net_traits::ResourceThread; +use net_traits::bluetooth_thread::BluetoothMethodMsg; use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread}; use net_traits::storage_thread::{StorageThread, StorageType}; use num_traits::ToPrimitive; @@ -212,6 +213,10 @@ pub struct Window { #[ignore_heap_size_of = "channels are hard"] resource_thread: Arc, + /// A handle for communicating messages to the bluetooth thread. + #[ignore_heap_size_of = "channels are hard"] + bluetooth_thread: IpcSender, + /// A handle for communicating messages to the storage thread. #[ignore_heap_size_of = "channels are hard"] storage_thread: StorageThread, @@ -334,6 +339,10 @@ impl Window { &*self.page } + pub fn bluetooth_thread(&self) -> IpcSender { + self.bluetooth_thread.clone() + } + pub fn storage_thread(&self) -> StorageThread { self.storage_thread.clone() } @@ -1401,6 +1410,7 @@ impl Window { compositor: IpcSender, image_cache_thread: ImageCacheThread, resource_thread: Arc, + bluetooth_thread: IpcSender, storage_thread: StorageThread, mem_profiler_chan: mem::ProfilerChan, devtools_chan: Option>, @@ -1456,6 +1466,7 @@ impl Window { dom_static: GlobalStaticData::new(), js_runtime: DOMRefCell::new(Some(runtime.clone())), resource_thread: resource_thread, + bluetooth_thread: bluetooth_thread, storage_thread: storage_thread, constellation_chan: constellation_chan, page_clip_rect: Cell::new(MAX_RECT), diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 4768273c16e..7070a29c2c4 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -64,6 +64,7 @@ use msg::constellation_msg::{PipelineId, PipelineNamespace}; use msg::constellation_msg::{SubpageId, WindowSizeData, WindowSizeType}; use msg::webdriver_msg::WebDriverScriptCommand; use net_traits::LoadData as NetLoadData; +use net_traits::bluetooth_thread::BluetoothMethodMsg; use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread}; use net_traits::storage_thread::StorageThread; use net_traits::{AsyncResponseTarget, ControlMsg, LoadConsumer, LoadContext, Metadata, ResourceThread}; @@ -310,6 +311,8 @@ pub struct ScriptThread { /// A handle to the resource thread. This is an `Arc` to avoid running out of file descriptors if /// there are many iframes. resource_thread: Arc, + /// A handle to the bluetooth thread. + bluetooth_thread: IpcSender, /// A handle to the storage thread. storage_thread: StorageThread, @@ -540,6 +543,7 @@ impl ScriptThread { image_cache_port: image_cache_port, resource_thread: Arc::new(state.resource_thread), + bluetooth_thread: state.bluetooth_thread, storage_thread: state.storage_thread, port: port, @@ -1482,6 +1486,7 @@ impl ScriptThread { self.compositor.borrow_mut().clone(), self.image_cache_thread.clone(), self.resource_thread.clone(), + self.bluetooth_thread.clone(), self.storage_thread.clone(), self.mem_profiler_chan.clone(), self.devtools_chan.clone(), diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index 2d4469ef80d..a001159acfb 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -46,6 +46,7 @@ use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData}; use msg::constellation_msg::{PipelineNamespaceId, SubpageId}; use msg::webdriver_msg::WebDriverScriptCommand; use net_traits::ResourceThread; +use net_traits::bluetooth_thread::BluetoothMethodMsg; use net_traits::image_cache_thread::ImageCacheThread; use net_traits::response::HttpsState; use net_traits::storage_thread::StorageThread; @@ -320,6 +321,8 @@ pub struct InitialScriptState { pub scheduler_chan: IpcSender, /// A channel to the resource manager thread. pub resource_thread: ResourceThread, + /// A channel to the bluetooth thread. + pub bluetooth_thread: IpcSender, /// A channel to the storage thread. pub storage_thread: StorageThread, /// A channel to the image cache thread. diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index adba235f7f4..a3a64440eb3 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -167,6 +167,15 @@ name = "block" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "blurz" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dbus 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "brotli" version = "0.3.20" @@ -414,6 +423,15 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "dbus" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "debug_unreachable" version = "0.1.1" @@ -430,6 +448,14 @@ 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/dati91/devices?branch=device-api#dccc5111e46124cef596cef10ce9056362892e59" +dependencies = [ + "blurz 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "devtools" version = "0.0.1" @@ -1307,6 +1333,7 @@ version = "0.0.1" dependencies = [ "brotli 0.3.20 (git+https://github.com/ende76/brotli-rs)", "cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "device 0.0.1 (git+https://github.com/dati91/devices?branch=device-api)", "devtools_traits 0.0.1", "flate2 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 42e6706500c..c8355affa58 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -71,9 +71,11 @@ use compositing::{CompositorProxy, CompositorThread, Constellation}; use gaol::sandbox::{ChildSandbox, ChildSandboxMethods}; use gfx::font_cache_thread::FontCacheThread; use ipc_channel::ipc::{self, IpcSender}; +use net::bluetooth_thread::BluetoothThreadFactory; use net::image_cache_thread::new_image_cache_thread; use net::resource_thread::new_resource_thread; use net::storage_thread::StorageThreadFactory; +use net_traits::bluetooth_thread::BluetoothMethodMsg; use net_traits::storage_thread::StorageThread; use profile::mem as profile_mem; use profile::time as profile_time; @@ -208,6 +210,7 @@ fn create_constellation(opts: opts::Opts, devtools_chan: Option>, supports_clipboard: bool, webrender_api_sender: Option) -> Sender { + let bluetooth_thread: IpcSender = BluetoothThreadFactory::new(); let resource_thread = new_resource_thread(opts.user_agent.clone(), devtools_chan.clone()); let image_cache_thread = new_image_cache_thread(resource_thread.clone(), webrender_api_sender.as_ref().map(|wr| wr.create_api())); @@ -218,6 +221,7 @@ fn create_constellation(opts: opts::Opts, let initial_state = InitialConstellationState { compositor_proxy: compositor_proxy, devtools_chan: devtools_chan, + bluetooth_thread: bluetooth_thread, image_cache_thread: image_cache_thread, font_cache_thread: font_cache_thread, resource_thread: resource_thread, From b01c52c18fc0a5280861b1d6339ca83c8a9a1b06 Mon Sep 17 00:00:00 2001 From: fokinv Date: Thu, 31 Mar 2016 10:35:24 +0200 Subject: [PATCH 04/15] Implementation of the getPrimaryService(s), the getCharacteristic(s) and the getDescriptor(s) functions. --- components/net/bluetooth_thread.rs | 213 +++++++++++++++--- components/net_traits/bluetooth_thread.rs | 18 +- .../dom/bluetoothremotegattcharacteristic.rs | 70 +++++- .../script/dom/bluetoothremotegattserver.rs | 64 +++++- .../script/dom/bluetoothremotegattservice.rs | 84 ++++++- components/script/dom/bluetoothuuid.rs | 9 + .../BluetoothRemoteGATTCharacteristic.webidl | 5 +- .../webidls/BluetoothRemoteGATTServer.webidl | 3 +- .../webidls/BluetoothRemoteGATTService.webidl | 4 +- 9 files changed, 411 insertions(+), 59 deletions(-) diff --git a/components/net/bluetooth_thread.rs b/components/net/bluetooth_thread.rs index e2bb015673e..ba7ab276ac0 100644 --- a/components/net/bluetooth_thread.rs +++ b/components/net/bluetooth_thread.rs @@ -85,14 +85,23 @@ impl BluetoothManager { BluetoothMethodMsg::GATTServerDisconnect(device_id, sender) => { self.gatt_server_disconnect(device_id, sender) } - BluetoothMethodMsg::GetPrimaryService(device_id, sender) => { - self.get_primary_service(device_id, sender) + BluetoothMethodMsg::GetPrimaryService(device_id, uuid, sender) => { + self.get_primary_service(device_id, uuid, sender) } - BluetoothMethodMsg::GetCharacteristic(service_id, sender) => { - self.get_characteristic(service_id, sender) + BluetoothMethodMsg::GetPrimaryServices(device_id, uuid, sender) => { + self.get_primary_services(device_id, uuid, sender) } - BluetoothMethodMsg::GetDescriptor(characteristic_id, sender) => { - self.get_descriptor(characteristic_id, 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) + } + BluetoothMethodMsg::GetDescriptors(characteristic_id, uuid, sender) => { + self.get_descriptors(characteristic_id, uuid, sender) } BluetoothMethodMsg::ReadValue(id, sender) => { self.read_value(id, sender) @@ -164,7 +173,6 @@ impl BluetoothManager { None } - #[allow(dead_code)] fn get_gatt_service_by_uuid(&mut self, adapter: &mut BluetoothAdapter, device_id: &str, @@ -185,6 +193,21 @@ impl BluetoothManager { None } + fn get_gatt_services_by_uuid(&mut self, + adapter: &mut BluetoothAdapter, + device_id: &str, + service_uuid: &str) + -> Vec { + let mut services_vec: Vec = vec!(); + let services = self.get_gatt_services(adapter, device_id); + for service in services { + if service.get_uuid().unwrap_or("".to_owned()) == service_uuid { + services_vec.push(service.clone()); + } + } + services_vec + } + // Characteristic fn get_gatt_characteristics(&mut self, @@ -218,7 +241,6 @@ impl BluetoothManager { None } - #[allow(dead_code)] fn get_gatt_characteristic_by_uuid(&mut self, adapter: &mut BluetoothAdapter, service_id: &str, @@ -239,6 +261,21 @@ impl BluetoothManager { None } + fn get_gatt_characteristics_by_uuid(&mut self, + adapter: &mut BluetoothAdapter, + service_id: &str, + characteristic_uuid: &str) + -> Vec { + let mut characteristics_vec: Vec = vec!(); + let characteristics = self.get_gatt_characteristics(adapter, service_id); + for characteristic in characteristics { + if characteristic.get_uuid().unwrap_or("".to_owned()) == characteristic_uuid { + characteristics_vec.push(characteristic.clone()); + } + } + characteristics_vec + } + fn get_characteristic_properties(&self, characteristic: &BluetoothGATTCharacteristic) -> [bool; 9] { let mut props = [false; 9]; let flags = characteristic.get_flags().unwrap_or(vec!()); @@ -292,7 +329,6 @@ impl BluetoothManager { None } - #[allow(dead_code)] fn get_gatt_descriptor_by_uuid(&mut self, adapter: &mut BluetoothAdapter, characteristic_id: &str, @@ -313,6 +349,21 @@ impl BluetoothManager { None } + fn get_gatt_descriptors_by_uuid(&mut self, + adapter: &mut BluetoothAdapter, + characteristic_id: &str, + descriptor_uuid: &str) + -> Vec { + let mut descriptors_vec: Vec = vec!(); + let descriptors = self.get_gatt_descriptors(adapter, characteristic_id); + for descriptor in descriptors { + if descriptor.get_uuid().unwrap_or("".to_owned()) == descriptor_uuid { + descriptors_vec.push(descriptor.clone()); + } + } + descriptors_vec + } + // Methods fn request_device(&mut self, sender: IpcSender) { @@ -395,44 +446,67 @@ impl BluetoothManager { sender.send(message).unwrap(); } - pub fn get_primary_service(&mut self, device_id: String, sender: IpcSender) { + pub fn get_primary_service(&mut self, device_id: String, uuid: String, sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, None => send_error!(sender, "No adapter found"), }; + let service = match self.get_gatt_service_by_uuid(&mut adapter, &device_id, &uuid) { + Some(s) => s, + None => send_error!(sender, "No primary service found") + }; + if !service.is_primary().unwrap_or(false) { + send_error!(sender, "No primary service found"); + } + let message = BluetoothObjectMsg::BluetoothService { + uuid: service.get_uuid().unwrap_or("".to_owned()), + is_primary: true, + instance_id: service.get_object_path(), + }; + sender.send(message).unwrap(); + } - let services = self.get_gatt_services(&mut adapter, &device_id); + pub fn get_primary_services(&mut self, + device_id: String, + uuid: Option, + sender: IpcSender) { + let mut adapter = match self.get_adapter() { + Some(a) => a, + None => send_error!(sender, "No adapter found"), + }; + let services: Vec = match uuid { + Some(id) => self.get_gatt_services_by_uuid(&mut adapter, &device_id, &id), + None => self.get_gatt_services(&mut adapter, &device_id), + }; if services.is_empty() { send_error!(sender, "No service found"); } - + let mut services_vec: Vec = vec!(); for service in services { if service.is_primary().unwrap_or(false) { - let message = BluetoothObjectMsg::BluetoothService { + services_vec.push(BluetoothObjectMsg::BluetoothService { uuid: service.get_uuid().unwrap_or("".to_owned()), is_primary: true, - instance_id: service.get_object_path() - }; - sender.send(message).unwrap(); - return; + instance_id: service.get_object_path(), + }); } } - - send_error!(sender, "No primary service found"); + if services_vec.is_empty() { + send_error!(sender, "No service found"); + } + let message = BluetoothObjectMsg::BluetoothServices { services_vec: services_vec }; + sender.send(message).unwrap(); } - pub fn get_characteristic(&mut self, service_id: String, sender: IpcSender) { + pub fn get_characteristic(&mut self, service_id: String, uuid: String, sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, None => send_error!(sender, "No adapter found"), }; - - let characteristics = self.get_gatt_characteristics(&mut adapter, &service_id); - if characteristics.is_empty() { - send_error!(sender, "No characteristic found"); - } - - let characteristic = &characteristics[0]; + let characteristic = match self.get_gatt_characteristic_by_uuid(&mut adapter, &service_id, &uuid) { + Some(c) => c, + None => send_error!(sender, "No characteristic found"), + }; let properties = self.get_characteristic_properties(&characteristic); let message = BluetoothObjectMsg::BluetoothCharacteristic { uuid: characteristic.get_uuid().unwrap_or("".to_owned()), @@ -445,23 +519,63 @@ impl BluetoothManager { indicate: properties[5], authenticated_signed_writes: properties[6], reliable_write: properties[7], - writable_auxiliaries: properties[8] + writable_auxiliaries: properties[8], }; sender.send(message).unwrap(); } - pub fn get_descriptor(&mut self, characteristic_id: String, sender: IpcSender) { + pub fn get_characteristics(&mut self, + service_id: String, + uuid: Option, + sender: IpcSender) { + let mut adapter = match self.get_adapter() { + Some(a) => a, + None => send_error!(sender, "No adapter found"), + }; + let characteristics = match uuid { + Some(id) => self.get_gatt_characteristics_by_uuid(&mut adapter, &service_id, &id), + None => self.get_gatt_characteristics(&mut adapter, &service_id), + }; + if characteristics.is_empty() { + send_error!(sender, "No characteristic found"); + } + let mut characteristics_vec: Vec = vec!(); + for characteristic in characteristics { + let properties = self.get_characteristic_properties(&characteristic); + characteristics_vec.push(BluetoothObjectMsg::BluetoothCharacteristic { + uuid: characteristic.get_uuid().unwrap_or("".to_owned()), + instance_id: characteristic.get_object_path(), + broadcast: properties[0], + read: properties[1], + write_without_response: properties[2], + write: properties[3], + notify: properties[4], + indicate: properties[5], + authenticated_signed_writes: properties[6], + reliable_write: properties[7], + writable_auxiliaries: properties[8], + }); + } + if characteristics_vec.is_empty() { + send_error!(sender, "No characteristic found"); + } + let message = BluetoothObjectMsg::BluetoothCharacteristics { characteristics_vec: characteristics_vec }; + sender.send(message).unwrap(); + } + + pub fn get_descriptor(&mut self, + characteristic_id: String, + uuid: String, + sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, None => send_error!(sender, "No adapter found"), }; - let descriptors = self.get_gatt_descriptors(&mut adapter, &characteristic_id); - if descriptors.is_empty() { - send_error!(sender, "No descriptor found"); - } - - let descriptor = &descriptors[0]; + let descriptor = match self.get_gatt_descriptor_by_uuid(&mut adapter, &characteristic_id, &uuid) { + Some(d) => d, + None => send_error!(sender, "No descriptor found"), + }; let message = BluetoothObjectMsg::BluetoothDescriptor { uuid: descriptor.get_uuid().unwrap_or("".to_owned()), instance_id: descriptor.get_object_path(), @@ -469,6 +583,35 @@ impl BluetoothManager { sender.send(message).unwrap(); } + pub fn get_descriptors(&mut self, + characteristic_id: String, + uuid: Option, + sender: IpcSender) { + let mut adapter = match self.get_adapter() { + Some(a) => a, + None => send_error!(sender, "No adapter found"), + }; + let descriptors = match uuid { + Some(id) => self.get_gatt_descriptors_by_uuid(&mut adapter, &characteristic_id, &id), + None => self.get_gatt_descriptors(&mut adapter, &characteristic_id), + }; + if descriptors.is_empty() { + send_error!(sender, "No descriptor found"); + } + let mut descriptors_vec: Vec = vec!(); + for descriptor in descriptors { + descriptors_vec.push(BluetoothObjectMsg::BluetoothDescriptor { + uuid: descriptor.get_uuid().unwrap_or("".to_owned()), + instance_id: descriptor.get_object_path(), + }); + } + if descriptors_vec.is_empty() { + send_error!(sender, "No descriptor found"); + } + let message = BluetoothObjectMsg::BluetoothDescriptors { descriptors_vec: descriptors_vec }; + sender.send(message).unwrap(); + } + pub fn read_value(&mut self, id: String, sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, diff --git a/components/net_traits/bluetooth_thread.rs b/components/net_traits/bluetooth_thread.rs index 86bdffc1fff..c035a1ea164 100644 --- a/components/net_traits/bluetooth_thread.rs +++ b/components/net_traits/bluetooth_thread.rs @@ -8,9 +8,12 @@ pub enum BluetoothMethodMsg { RequestDevice(IpcSender), GATTServerConnect(String, IpcSender), GATTServerDisconnect(String, IpcSender), - GetPrimaryService(String, IpcSender), - GetCharacteristic(String, IpcSender), - GetDescriptor(String, IpcSender), + GetPrimaryService(String, String, IpcSender), + GetPrimaryServices(String, Option, IpcSender), + GetCharacteristic(String, String, IpcSender), + GetCharacteristics(String, Option, IpcSender), + GetDescriptor(String, String, IpcSender), + GetDescriptors(String, Option, IpcSender), ReadValue(String, IpcSender), WriteValue(String, Vec, IpcSender), Exit, @@ -40,6 +43,9 @@ pub enum BluetoothObjectMsg { is_primary: bool, instance_id: String }, + BluetoothServices { + services_vec: Vec + }, BluetoothCharacteristic { // Characteristic uuid: String, @@ -55,10 +61,16 @@ pub enum BluetoothObjectMsg { reliable_write: bool, writable_auxiliaries: bool }, + BluetoothCharacteristics { + characteristics_vec: Vec + }, BluetoothDescriptor { uuid: String, instance_id: String }, + BluetoothDescriptors { + descriptors_vec: Vec, + }, BluetoothReadValue { value: Vec }, diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs index 3ce8749979a..db487bb70bc 100644 --- a/components/script/dom/bluetoothremotegattcharacteristic.rs +++ b/components/script/dom/bluetoothremotegattcharacteristic.rs @@ -9,7 +9,8 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding:: BluetoothRemoteGATTCharacteristicMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods; -use dom::bindings::error::Error::Network; +use dom::bindings::codegen::UnionTypes::StringOrUnsignedLong; +use dom::bindings::error::Error::{Network, Type}; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; @@ -18,6 +19,7 @@ use dom::bindings::str::ByteString; use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties; use dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor; use dom::bluetoothremotegattservice::BluetoothRemoteGATTService; +use dom::bluetoothuuid::BluetoothUUID; use ipc_channel::ipc::{self, IpcSender}; use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg}; use util::str::DOMString; @@ -92,31 +94,77 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor - fn GetDescriptor(&self) -> Option> { + fn GetDescriptor(&self, + descriptor: StringOrUnsignedLong) + -> Fallible> { + let uuid: String = match BluetoothUUID::GetDescriptor(self.global().r(), descriptor.clone()) { + Ok(domstring) => domstring.to_string(), + Err(error) => return Err(error), + }; let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( - BluetoothMethodMsg::GetDescriptor(self.get_instance_id(), sender)).unwrap(); + BluetoothMethodMsg::GetDescriptor(self.get_instance_id(), uuid, sender)).unwrap(); let descriptor = receiver.recv().unwrap(); match descriptor { BluetoothObjectMsg::BluetoothDescriptor { uuid, instance_id } => { - Some(BluetoothRemoteGATTDescriptor::new(self.global().r(), - &self, - DOMString::from(uuid), - instance_id)) + Ok(BluetoothRemoteGATTDescriptor::new(self.global().r(), + &self, + DOMString::from(uuid), + instance_id)) }, BluetoothObjectMsg::Error { error - } => { - println!("{}", error); - None - }, + } => Err(Type(error)), _ => unreachable!() } } + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors + fn GetDescriptors(&self, + descriptor: Option) + -> Fallible>> { + let uuid: Option = match descriptor { + Some(d) => match BluetoothUUID::GetDescriptor(self.global().r(), d.clone()) { + Ok(domstring) => Some(domstring.to_string()), + Err(error) => return Err(error), + }, + None => None, + }; + let (sender, receiver) = ipc::channel().unwrap(); + let mut descriptors: Vec> = vec!(); + self.get_bluetooth_thread().send( + BluetoothMethodMsg::GetDescriptors(self.get_instance_id(), uuid, sender)).unwrap(); + let descriptors_vec = receiver.recv().unwrap(); + match descriptors_vec { + BluetoothObjectMsg::BluetoothDescriptors { + descriptors_vec + } => { + for d in descriptors_vec { + match d { + BluetoothObjectMsg::BluetoothDescriptor { + uuid, + instance_id, + } => { + descriptors.push(BluetoothRemoteGATTDescriptor::new(self.global().r(), + &self, + DOMString::from(uuid), + instance_id)) + }, + _ => unreachable!(), + } + } + Ok(descriptors) + }, + BluetoothObjectMsg::Error { + error + } => Err(Type(error)), + _ => unreachable!(), + } + } + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-value fn GetValue(&self) -> Option { self.value.borrow().clone() diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs index 2eec908d4c5..e3b0e5bd8c9 100644 --- a/components/script/dom/bluetoothremotegattserver.rs +++ b/components/script/dom/bluetoothremotegattserver.rs @@ -5,11 +5,13 @@ use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; +use dom::bindings::codegen::UnionTypes::StringOrUnsignedLong; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; use dom::bluetoothdevice::BluetoothDevice; use dom::bluetoothremotegattservice::BluetoothRemoteGATTService; +use dom::bluetoothuuid::BluetoothUUID; use ipc_channel::ipc::{self, IpcSender}; use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg}; use std::cell::Cell; @@ -101,16 +103,23 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice - fn GetPrimaryService(&self) -> Option> { + fn GetPrimaryService(&self, service: StringOrUnsignedLong) -> Option> { + let uuid: String = match BluetoothUUID::GetService(self.global().r(), service.clone()) { + Ok(domstring) => domstring.to_string(), + Err(_) => { + println!("No UUID provided!"); + return None; + }, + }; let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( - BluetoothMethodMsg::GetPrimaryService(String::from(self.Device().Id()), sender)).unwrap(); + BluetoothMethodMsg::GetPrimaryService(String::from(self.Device().Id()), uuid, sender)).unwrap(); let service = receiver.recv().unwrap(); match service { BluetoothObjectMsg::BluetoothService { uuid, is_primary, - instance_id + instance_id, } => { Some(BluetoothRemoteGATTService::new(self.global().r(), &self.device.get(), @@ -124,7 +133,54 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { println!("{}", error); None }, - _ => unreachable!() + _ => unreachable!(), + } + } + + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices + fn GetPrimaryServices(&self, service: Option) + -> Option>> { + let uuid: Option = match service { + Some(s) => match BluetoothUUID::GetService(self.global().r(), s.clone()) { + Ok(domstring) => Some(domstring.to_string()), + Err(_) => None, + }, + None => None, + }; + let mut services: Vec> = vec!(); + let (sender, receiver) = ipc::channel().unwrap(); + self.get_bluetooth_thread().send( + BluetoothMethodMsg::GetPrimaryServices(String::from(self.Device().Id()), uuid, sender)).unwrap(); + let services_vec = receiver.recv().unwrap(); + match services_vec { + BluetoothObjectMsg::BluetoothServices { + services_vec + } => { + for s in services_vec { + match s { + BluetoothObjectMsg::BluetoothService { + uuid, + is_primary, + instance_id, + } => { + services.push(BluetoothRemoteGATTService::new(self.global().r(), + &self.device.get(), + DOMString::from(uuid), + is_primary, + instance_id)) + }, + _ => unreachable!(), + } + } + Some(services) + }, + BluetoothObjectMsg::Error { + error + } => { + println!("{}", error); + None + }, + _ => unreachable!(), } } } diff --git a/components/script/dom/bluetoothremotegattservice.rs b/components/script/dom/bluetoothremotegattservice.rs index 433bf8ef9d8..8d4afe48ed3 100644 --- a/components/script/dom/bluetoothremotegattservice.rs +++ b/components/script/dom/bluetoothremotegattservice.rs @@ -4,12 +4,14 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods; +use dom::bindings::codegen::UnionTypes::StringOrUnsignedLong; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties; use dom::bluetoothdevice::BluetoothDevice; use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic; +use dom::bluetoothuuid::BluetoothUUID; use ipc_channel::ipc::{self, IpcSender}; use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg}; use util::str::DOMString; @@ -81,10 +83,19 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic - fn GetCharacteristic(&self) -> Option> { + fn GetCharacteristic(&self, characteristic: StringOrUnsignedLong) + -> Option> { + let uuid: String = match BluetoothUUID::GetCharacteristic(self.global().r(), + characteristic.clone()) { + Ok(domstring) => domstring.to_string(), + Err(_) => { + println!("No UUID provided!"); + return None; + }, + }; let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( - BluetoothMethodMsg::GetCharacteristic(self.get_instance_id(), sender)).unwrap(); + BluetoothMethodMsg::GetCharacteristic(self.get_instance_id(), uuid, sender)).unwrap(); let characteristic = receiver.recv().unwrap(); match characteristic { BluetoothObjectMsg::BluetoothCharacteristic { @@ -122,7 +133,74 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { println!("{}", error); None }, - _ => unreachable!() + _ => unreachable!(), + } + } + + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics + fn GetCharacteristics(&self, characteristic: Option) + -> Option>> { + let uuid: Option = match characteristic { + Some(c) => match BluetoothUUID::GetCharacteristic(self.global().r(), c.clone()) { + Ok(domstring) => Some(domstring.to_string()), + Err(_) => None, + }, + None => None, + }; + let mut characteristics: Vec> = vec!(); + let (sender, receiver) = ipc::channel().unwrap(); + self.get_bluetooth_thread().send( + BluetoothMethodMsg::GetCharacteristics(self.get_instance_id(), uuid, sender)).unwrap(); + let characteristics_vec = receiver.recv().unwrap(); + match characteristics_vec { + BluetoothObjectMsg::BluetoothCharacteristics { + characteristics_vec + } => { + for characteristic in characteristics_vec { + match characteristic { + BluetoothObjectMsg::BluetoothCharacteristic { + uuid, + instance_id, + broadcast, + read, + write_without_response, + write, + notify, + indicate, + authenticated_signed_writes, + reliable_write, + writable_auxiliaries, + } => { + let properties = &BluetoothCharacteristicProperties::new( + self.global().r(), + broadcast, + read, + write_without_response, + write, + notify, + indicate, + authenticated_signed_writes, + reliable_write, + writable_auxiliaries); + characteristics.push(BluetoothRemoteGATTCharacteristic::new( + self.global().r(), + &self, + DOMString::from(uuid), + properties, + instance_id)) + }, + _ => unreachable!(), + } + } + Some(characteristics) + }, + BluetoothObjectMsg::Error { + error + } => { + println!("{}", error); + None + }, + _ => unreachable!(), } } } diff --git a/components/script/dom/bluetoothuuid.rs b/components/script/dom/bluetoothuuid.rs index 1817601dc97..91c581d5d3b 100644 --- a/components/script/dom/bluetoothuuid.rs +++ b/components/script/dom/bluetoothuuid.rs @@ -333,3 +333,12 @@ impl BluetoothUUID { } } } + +impl Clone for StringOrUnsignedLong { + fn clone(&self) -> StringOrUnsignedLong { + match self { + &StringOrUnsignedLong::String(ref s) => StringOrUnsignedLong::String(s.clone()), + &StringOrUnsignedLong::UnsignedLong(ul) => StringOrUnsignedLong::UnsignedLong(ul), + } + } +} diff --git a/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl b/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl index b3a1e691351..3024b3bc7f2 100644 --- a/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl +++ b/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl @@ -10,7 +10,10 @@ interface BluetoothRemoteGATTCharacteristic { readonly attribute DOMString uuid; readonly attribute BluetoothCharacteristicProperties properties; readonly attribute ByteString? value; - BluetoothRemoteGATTDescriptor? getDescriptor(/*BluetoothDescriptorUUID descriptor*/); + [Throws] + BluetoothRemoteGATTDescriptor getDescriptor((DOMString or unsigned long) descriptor); + [Throws] + sequence getDescriptors(optional (DOMString or unsigned long) descriptor); //Promise getDescriptor(BluetoothDescriptorUUID descriptor); //Promise> //getDescriptors(optional BluetoothDescriptorUUID descriptor); diff --git a/components/script/dom/webidls/BluetoothRemoteGATTServer.webidl b/components/script/dom/webidls/BluetoothRemoteGATTServer.webidl index 327542b522f..ac6af9649b1 100644 --- a/components/script/dom/webidls/BluetoothRemoteGATTServer.webidl +++ b/components/script/dom/webidls/BluetoothRemoteGATTServer.webidl @@ -10,7 +10,8 @@ interface BluetoothRemoteGATTServer { readonly attribute boolean connected; BluetoothRemoteGATTServer connect(); void disconnect(); - BluetoothRemoteGATTService? getPrimaryService(); + BluetoothRemoteGATTService? getPrimaryService((DOMString or unsigned long) service); + sequence? getPrimaryServices(optional (DOMString or unsigned long) service); //Promise getPrimaryService(BluetoothServiceUUID service); //Promise>getPrimaryServices(optional BluetoothServiceUUID service); //Promise connect(); diff --git a/components/script/dom/webidls/BluetoothRemoteGATTService.webidl b/components/script/dom/webidls/BluetoothRemoteGATTService.webidl index e8d66f6ac63..1cc34ba41a3 100644 --- a/components/script/dom/webidls/BluetoothRemoteGATTService.webidl +++ b/components/script/dom/webidls/BluetoothRemoteGATTService.webidl @@ -9,7 +9,9 @@ interface BluetoothRemoteGATTService { readonly attribute BluetoothDevice device; readonly attribute DOMString uuid; readonly attribute boolean isPrimary; - BluetoothRemoteGATTCharacteristic? getCharacteristic(/*DOMString characteristic*/); + BluetoothRemoteGATTCharacteristic? getCharacteristic((DOMString or unsigned long) characteristic); + sequence? getCharacteristics + (optional (DOMString or unsigned long) characteristic); //PromisegetCharacteristic(BluetoothCharacteristicUUID characteristic); //Promise> //getCharacteristics(optional BluetoothCharacteristicUUID characteristic); From 66fbc4ac46113aafda01f32fb6252c5bf2fbbab5 Mon Sep 17 00:00:00 2001 From: zakorgy Date: Wed, 6 Apr 2016 16:26:52 +0200 Subject: [PATCH 05/15] requestDevice options (filters and optionalServices) --- components/net/bluetooth_thread.rs | 55 +++-- components/net_traits/Cargo.toml | 1 + components/net_traits/bluetooth_scanfilter.rs | 135 ++++++++++ components/net_traits/bluetooth_thread.rs | 3 +- components/net_traits/lib.rs | 2 + components/script/dom/bluetooth.rs | 231 ++++++++++++++---- .../script/dom/webidls/Bluetooth.webidl | 14 +- components/servo/Cargo.lock | 1 + 8 files changed, 361 insertions(+), 81 deletions(-) create mode 100644 components/net_traits/bluetooth_scanfilter.rs diff --git a/components/net/bluetooth_thread.rs b/components/net/bluetooth_thread.rs index ba7ab276ac0..a5bac3d5db4 100644 --- a/components/net/bluetooth_thread.rs +++ b/components/net/bluetooth_thread.rs @@ -8,6 +8,7 @@ use device::bluetooth::BluetoothGATTCharacteristic; use device::bluetooth::BluetoothGATTDescriptor; use device::bluetooth::BluetoothGATTService; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; +use net_traits::bluetooth_scanfilter::{RequestDeviceoptions, matches_filters}; use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg}; use std::borrow::ToOwned; use std::collections::HashMap; @@ -76,8 +77,8 @@ impl BluetoothManager { fn start(&mut self) { loop { match self.receiver.recv().unwrap() { - BluetoothMethodMsg::RequestDevice(sender) => { - self.request_device(sender) + BluetoothMethodMsg::RequestDevice(options, sender) => { + self.request_device(options, sender) } BluetoothMethodMsg::GATTServerConnect(device_id, sender) => { self.gatt_server_connect(device_id, sender) @@ -366,7 +367,9 @@ impl BluetoothManager { // Methods - fn request_device(&mut self, sender: IpcSender) { + fn request_device(&mut self, + options: RequestDeviceoptions, + sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, None => send_error!(sender, "No adapter found"), @@ -376,28 +379,30 @@ impl BluetoothManager { send_error!(sender, "No device found"); } - //TODO select the proper device - let device = &devices[0]; - - let message = BluetoothObjectMsg::BluetoothDevice { - id: device.get_address().unwrap_or("".to_owned()), - name: device.get_name().ok(), - device_class: device.get_class().ok(), - vendor_id_source: device.get_vendor_id_source().ok(), - vendor_id: device.get_vendor_id().ok(), - product_id: device.get_product_id().ok(), - product_version: device.get_device_id().ok(), - appearance: device.get_appearance().ok(), - tx_power: match device.get_tx_power() { - Ok(p) => Some(p as i8), - Err(_) => None, - }, - rssi: match device.get_rssi() { - Ok(p) => Some(p as i8), - Err(_) => None, - } - }; - sender.send(message).unwrap(); + match devices.into_iter().find(|ref d| matches_filters(d, options.get_filters())) { + Some(device) => { + let message = BluetoothObjectMsg::BluetoothDevice { + id: device.get_address().unwrap_or("".to_owned()), + name: device.get_name().ok(), + device_class: device.get_class().ok(), + vendor_id_source: device.get_vendor_id_source().ok(), + vendor_id: device.get_vendor_id().ok(), + product_id: device.get_product_id().ok(), + product_version: device.get_device_id().ok(), + appearance: device.get_appearance().ok(), + tx_power: match device.get_tx_power() { + Ok(p) => Some(p as i8), + Err(_) => None, + }, + rssi: match device.get_rssi() { + Ok(p) => Some(p as i8), + Err(_) => None, + }, + }; + sender.send(message).unwrap(); + }, + None => send_error!(sender, "No device found, that matches the given options"), + } } pub fn gatt_server_connect(&mut self, device_id: String, sender: IpcSender) { diff --git a/components/net_traits/Cargo.toml b/components/net_traits/Cargo.toml index 2f0158fd020..f53bb989a35 100644 --- a/components/net_traits/Cargo.toml +++ b/components/net_traits/Cargo.toml @@ -12,6 +12,7 @@ path = "lib.rs" util = {path = "../util"} msg = {path = "../msg"} ipc-channel = {git = "https://github.com/servo/ipc-channel"} +device = {git = "https://github.com/servo/devices"} heapsize = "0.3.0" heapsize_plugin = "0.1.2" hyper = { version = "0.9", features = [ "serde-serialization" ] } diff --git a/components/net_traits/bluetooth_scanfilter.rs b/components/net_traits/bluetooth_scanfilter.rs new file mode 100644 index 00000000000..58eb72f518e --- /dev/null +++ b/components/net_traits/bluetooth_scanfilter.rs @@ -0,0 +1,135 @@ +/* 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 device::bluetooth::BluetoothDevice; + +// A device name can never be longer than 29 bytes. An adv packet is at most +// 31 bytes long. The length and identifier of the length field take 2 bytes. +// That least 29 bytes for the name. +const MAX_NAME_LENGTH: usize = 29; + +#[derive(Deserialize, Serialize)] +pub struct ServiceUUIDSequence(Vec); + +impl ServiceUUIDSequence { + pub fn new(vec: Vec) -> ServiceUUIDSequence { + ServiceUUIDSequence(vec) + } + + fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +#[derive(Deserialize, Serialize)] +pub struct BluetoothScanfilter { + name: String, + name_prefix: String, + services: ServiceUUIDSequence, +} + +impl BluetoothScanfilter { + fn is_empty_or_invalid_filter(&self) -> bool { + self.name.is_empty() && + self.name_prefix.is_empty() && + self.services.is_empty() && + self.name.len() > MAX_NAME_LENGTH && + self.name_prefix.len() > MAX_NAME_LENGTH + } + + pub fn new(name: String, name_prefix: String, services: Vec) -> BluetoothScanfilter { + BluetoothScanfilter { + name: name, + name_prefix: name_prefix, + services: ServiceUUIDSequence::new(services), + } + } +} + +#[derive(Deserialize, Serialize)] +pub struct BluetoothScanfilterSequence(Vec); + +impl BluetoothScanfilterSequence { + pub fn new(vec: Vec) -> BluetoothScanfilterSequence { + BluetoothScanfilterSequence(vec) + } +} + +impl BluetoothScanfilterSequence { + fn has_empty_or_invalid_filter(&self) -> bool { + self.0.is_empty() && + self.0.iter().all(|x| !(x.is_empty_or_invalid_filter())) + } +} + +#[derive(Deserialize, Serialize)] +pub struct RequestDeviceoptions { + filters: BluetoothScanfilterSequence, + optional_services: ServiceUUIDSequence, +} + +impl RequestDeviceoptions { + pub fn new(filters: BluetoothScanfilterSequence, + services: ServiceUUIDSequence) + -> RequestDeviceoptions { + RequestDeviceoptions { + filters: filters, + optional_services: services, + } + } + + pub fn get_filters(&self) -> &BluetoothScanfilterSequence { + &self.filters + } +} + +pub fn matches_filter(device: &BluetoothDevice, filter: &BluetoothScanfilter) -> bool { + if filter.is_empty_or_invalid_filter() { + return false; + } + + if !filter.name.is_empty() { + if let Ok(device_name) = device.get_name() { + if !device_name.eq(&filter.name) { + return false; + } + } else { + return false; + } + } + + if !filter.name_prefix.is_empty() { + if let Ok(device_name) = device.get_name() { + if !device_name.starts_with(&*filter.name_prefix) { + return false; + } + } else { + return false; + } + } + + if !filter.services.is_empty() { + if let Ok(stringvec) = device.get_uuids() { + for service in &filter.services.0 { + if !stringvec.iter().any(|x| x == service) { + return false; + } + } + } + } + return true; +} + +pub fn matches_filters(device: &BluetoothDevice, filters: &BluetoothScanfilterSequence) -> bool { + if filters.has_empty_or_invalid_filter() { + return false; + } + + for filter in &filters.0 { + if matches_filter(device, filter) { + return true; + } + } + return false; +} diff --git a/components/net_traits/bluetooth_thread.rs b/components/net_traits/bluetooth_thread.rs index c035a1ea164..6437027e144 100644 --- a/components/net_traits/bluetooth_thread.rs +++ b/components/net_traits/bluetooth_thread.rs @@ -1,11 +1,12 @@ /* 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 bluetooth_scanfilter::RequestDeviceoptions; use ipc_channel::ipc::IpcSender; #[derive(Deserialize, Serialize)] pub enum BluetoothMethodMsg { - RequestDevice(IpcSender), + RequestDevice(RequestDeviceoptions, IpcSender), GATTServerConnect(String, IpcSender), GATTServerDisconnect(String, IpcSender), GetPrimaryService(String, String, IpcSender), diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index 45895f63711..17416d215dd 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -13,6 +13,7 @@ #![deny(unsafe_code)] +extern crate device; extern crate heapsize; extern crate hyper; extern crate image as piston_image; @@ -40,6 +41,7 @@ use std::thread; use url::Url; use websocket::header; +pub mod bluetooth_scanfilter; pub mod bluetooth_thread; pub mod hosts; pub mod image_cache_thread; diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs index 36ac2a1f7e4..b66a427864a 100644 --- a/components/script/dom/bluetooth.rs +++ b/components/script/dom/bluetooth.rs @@ -2,18 +2,38 @@ * 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 core::clone::Clone; use dom::bindings::codegen::Bindings::BluetoothBinding; -use dom::bindings::codegen::Bindings::BluetoothBinding::BluetoothMethods; +use dom::bindings::codegen::Bindings::BluetoothBinding::RequestDeviceOptions; +use dom::bindings::codegen::Bindings::BluetoothBinding::{BluetoothScanFilter, BluetoothMethods}; use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::VendorIDSource; +use dom::bindings::error::Error::Type; +use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; use dom::bluetoothadvertisingdata::BluetoothAdvertisingData; use dom::bluetoothdevice::BluetoothDevice; +use dom::bluetoothuuid::BluetoothUUID; use ipc_channel::ipc::{self, IpcSender}; +use net_traits::bluetooth_scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence}; +use net_traits::bluetooth_scanfilter::{RequestDeviceoptions, ServiceUUIDSequence}; use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg}; use util::str::DOMString; +// A device name can never be longer than 29 bytes. An adv packet is at most +// 31 bytes long. The length and identifier of the length field take 2 bytes. +// That least 29 bytes for the name. +const MAX_FILTER_NAME_LENGTH: usize = 29; +// 248 is the maximum number of UTF-8 code units in a Bluetooth Device Name. +const MAX_DEVICE_NAME_LENGTH: usize = 248; +const FILTER_EMPTY_ERROR: &'static str = "'filters' member must be non - empty to find any devices."; +const FILTER_ERROR: &'static str = "A filter must restrict the devices in some way."; +const FILTER_NAME_TOO_LONG_ERROR: &'static str = "A 'name' or 'namePrefix' can't be longer then 29 bytes."; +const NAME_PREFIX_ERROR: &'static str = "'namePrefix', if present, must be non - empty."; +const NAME_TOO_LONG_ERROR: &'static str = "A device name can't be longer than 248 bytes."; +const SERVICE_ERROR: &'static str = "'services', if present, must contain at least one service."; + // https://webbluetoothcg.github.io/web-bluetooth/#bluetooth #[dom_struct] pub struct Bluetooth { @@ -40,59 +60,162 @@ impl Bluetooth { } } -impl BluetoothMethods for Bluetooth { - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice - fn RequestDevice(&self) -> Option> { - let (sender, receiver) = ipc::channel().unwrap(); - self.get_bluetooth_thread().send(BluetoothMethodMsg::RequestDevice(sender)).unwrap(); - let device = receiver.recv().unwrap(); - match device { - BluetoothObjectMsg::BluetoothDevice { - id, - name, - device_class, - vendor_id_source, - vendor_id, - product_id, - product_version, - appearance, - tx_power, - rssi, - } => { - let ad_data = &BluetoothAdvertisingData::new(self.global().r(), - appearance, - tx_power, - rssi); - let vendor_id_source = match vendor_id_source { - Some(vid) => match vid.as_ref() { - "bluetooth" => Some(VendorIDSource::Bluetooth), - "usb" => Some(VendorIDSource::Usb), - _ => Some(VendorIDSource::Unknown), - }, - None => None, - }; - let name = match name { - Some(n) => Some(DOMString::from(n)), - None => None, - }; - Some(BluetoothDevice::new(self.global().r(), - DOMString::from(id), - name, - ad_data, - device_class, - vendor_id_source, - vendor_id, - product_id, - product_version)) - }, - BluetoothObjectMsg::Error { - error - } => { - println!("{}", error); - None - }, - _ => unreachable!() +impl Clone for BluetoothScanFilter { + fn clone(&self) -> BluetoothScanFilter { + BluetoothScanFilter { + name: self.name.clone(), + namePrefix: self.namePrefix.clone(), + services: self.services.clone(), + } + } +} + +impl Clone for RequestDeviceOptions { + fn clone(&self) -> RequestDeviceOptions { + RequestDeviceOptions { + filters: self.filters.clone(), + optionalServices: self.optionalServices.clone(), + } + } +} + +fn canonicalize_filter(filter: &BluetoothScanFilter, global: GlobalRef) + -> Fallible { + if !(filter.services.is_some() || + filter.name.is_some() || + filter.namePrefix.is_some()) { + return Err(Type(FILTER_ERROR.to_owned())); + } + + let mut services_vec: Vec = vec!(); + if let Some(services) = filter.services.clone() { + if services.is_empty() { + return Err(Type(SERVICE_ERROR.to_owned())); + } + for service in services { + match BluetoothUUID::GetService(global, service) { + Ok(valid) => services_vec.push(valid.to_string()), + Err(err) => return Err(err), + } + } + } + + let mut name = String::new(); + if let Some(filter_name) = filter.name.clone() { + //NOTE: DOMString::len() gives back the size in bytes + if filter_name.len() > MAX_DEVICE_NAME_LENGTH { + return Err(Type(NAME_TOO_LONG_ERROR.to_owned())); + } + if filter_name.len() > MAX_FILTER_NAME_LENGTH { + return Err(Type(FILTER_NAME_TOO_LONG_ERROR.to_owned())); + } + name = filter_name.to_string(); + } + + let mut name_prefix = String::new(); + if let Some(filter_name_prefix) = filter.namePrefix.clone() { + if filter_name_prefix.len() == 0 { + return Err(Type(NAME_PREFIX_ERROR.to_owned())); + } + if filter_name_prefix.len() > MAX_DEVICE_NAME_LENGTH { + return Err(Type(NAME_TOO_LONG_ERROR.to_owned())); + } + if filter_name_prefix.len() > MAX_FILTER_NAME_LENGTH { + return Err(Type(FILTER_NAME_TOO_LONG_ERROR.to_owned())); + } + name_prefix = filter_name_prefix.to_string(); + } + + Ok(BluetoothScanfilter::new(name, name_prefix, services_vec)) +} + +fn convert_request_device_options(options: &RequestDeviceOptions, global: GlobalRef) + -> Fallible { + if options.filters.is_empty() { + return Err(Type(FILTER_EMPTY_ERROR.to_owned())); + } + + let mut filters = vec!(); + for filter in &options.filters { + match canonicalize_filter(&filter, global) { + Ok(canonicalized_filter) => filters.push(canonicalized_filter), + Err(err) => return Err(err), + } + } + + let mut optional_services = vec!(); + if let Some(opt_services) = options.optionalServices.clone() { + for opt_service in opt_services { + match BluetoothUUID::GetService(global, opt_service) { + Ok(valid_service) => optional_services.push(valid_service.to_string()), + Err(err) => return Err(err), + } + } + } + + Ok(RequestDeviceoptions::new(BluetoothScanfilterSequence::new(filters), + ServiceUUIDSequence::new(optional_services))) +} + +impl BluetoothMethods for Bluetooth { + + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice + fn RequestDevice(&self, + option: &RequestDeviceOptions) + -> Fallible> { + let (sender, receiver) = ipc::channel().unwrap(); + match convert_request_device_options(option, self.global().r()) { + Ok(option) => { + self.get_bluetooth_thread() + .send(BluetoothMethodMsg::RequestDevice(option, sender)) + .unwrap(); + let device = receiver.recv().unwrap(); + match device { + BluetoothObjectMsg::BluetoothDevice { + id, + name, + device_class, + vendor_id_source, + vendor_id, + product_id, + product_version, + appearance, + tx_power, + rssi, + } => { + let ad_data = &BluetoothAdvertisingData::new(self.global().r(), + appearance, + tx_power, + rssi); + let vendor_id_source = match vendor_id_source { + Some(vid) => match vid.as_ref() { + "bluetooth" => Some(VendorIDSource::Bluetooth), + "usb" => Some(VendorIDSource::Usb), + _ => Some(VendorIDSource::Unknown), + }, + None => None, + }; + let name = match name { + Some(n) => Some(DOMString::from(n)), + None => None, + }; + Ok(BluetoothDevice::new(self.global().r(), + DOMString::from(id), + name, + ad_data, + device_class, + vendor_id_source, + vendor_id, + product_id, + product_version)) + }, + BluetoothObjectMsg::Error { + error + } => return Err(Type(error)), + _ => unreachable!() + } + }, + Err(err) => Err(err), } } } diff --git a/components/script/dom/webidls/Bluetooth.webidl b/components/script/dom/webidls/Bluetooth.webidl index 4199e0bc486..0d6c381e65f 100644 --- a/components/script/dom/webidls/Bluetooth.webidl +++ b/components/script/dom/webidls/Bluetooth.webidl @@ -4,10 +4,22 @@ // https://webbluetoothcg.github.io/web-bluetooth/#bluetooth +dictionary BluetoothScanFilter { + sequence services; + DOMString name; + DOMString namePrefix; +}; + +dictionary RequestDeviceOptions { + required sequence filters; + sequence optionalServices /*= []*/; +}; + [Pref="dom.bluetooth.enabled"] interface Bluetooth { // Promise requestDevice(RequestDeviceOptions options); - BluetoothDevice? requestDevice(/*RequestDeviceOptions options*/); + [Throws] + BluetoothDevice requestDevice(RequestDeviceOptions options); }; // Bluetooth implements EventTarget; diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index a3a64440eb3..97bb0b56d8a 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -1394,6 +1394,7 @@ dependencies = [ name = "net_traits" version = "0.0.1" dependencies = [ + "device 0.0.1 (git+https://github.com/dati91/devices?branch=device-api)", "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_plugin 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", From b8510454154f9e6efacf48db06f19c69f444d49f Mon Sep 17 00:00:00 2001 From: Attila Dusnoki Date: Fri, 15 Apr 2016 16:46:05 +0200 Subject: [PATCH 06/15] Fix incorrect behaviours --- components/net/bluetooth_thread.rs | 168 +++++++++++------------------ 1 file changed, 62 insertions(+), 106 deletions(-) diff --git a/components/net/bluetooth_thread.rs b/components/net/bluetooth_thread.rs index a5bac3d5db4..b298e78acab 100644 --- a/components/net/bluetooth_thread.rs +++ b/components/net/bluetooth_thread.rs @@ -174,26 +174,6 @@ impl BluetoothManager { None } - fn get_gatt_service_by_uuid(&mut self, - adapter: &mut BluetoothAdapter, - device_id: &str, - service_uuid: &str) - -> Option { - for service in self.cached_services.values() { - if service.get_uuid().unwrap_or("".to_owned()) == service_uuid { - return Some(service.clone()); - } - } - // Update cache - let services = self.get_gatt_services(adapter, device_id); - for service in services { - if service.get_uuid().unwrap_or("".to_owned()) == service_uuid { - return Some(service.clone()); - } - } - None - } - fn get_gatt_services_by_uuid(&mut self, adapter: &mut BluetoothAdapter, device_id: &str, @@ -242,26 +222,6 @@ impl BluetoothManager { None } - fn get_gatt_characteristic_by_uuid(&mut self, - adapter: &mut BluetoothAdapter, - service_id: &str, - characteristic_uuid: &str) - -> Option { - for characteristic in self.cached_characteristics.values() { - if characteristic.get_uuid().unwrap_or("".to_owned()) == characteristic_uuid { - return Some(characteristic.clone()); - } - } - // Update cache - let characteristics = self.get_gatt_characteristics(adapter, service_id); - for characteristic in characteristics { - if characteristic.get_uuid().unwrap_or("".to_owned()) == characteristic_uuid { - return Some(characteristic.clone()); - } - } - None - } - fn get_gatt_characteristics_by_uuid(&mut self, adapter: &mut BluetoothAdapter, service_id: &str, @@ -330,26 +290,6 @@ impl BluetoothManager { None } - fn get_gatt_descriptor_by_uuid(&mut self, - adapter: &mut BluetoothAdapter, - characteristic_id: &str, - descriptor_uuid: &str) - -> Option { - for descriptor in self.cached_descriptors.values() { - if descriptor.get_uuid().unwrap_or("".to_owned()) == descriptor_uuid { - return Some(descriptor.clone()); - } - } - // Update cache - let descriptors = self.get_gatt_descriptors(adapter, characteristic_id); - for descriptor in descriptors { - if descriptor.get_uuid().unwrap_or("".to_owned()) == descriptor_uuid { - return Some(descriptor.clone()); - } - } - None - } - fn get_gatt_descriptors_by_uuid(&mut self, adapter: &mut BluetoothAdapter, characteristic_id: &str, @@ -379,10 +319,13 @@ impl BluetoothManager { send_error!(sender, "No device found"); } - match devices.into_iter().find(|ref d| matches_filters(d, options.get_filters())) { - Some(device) => { + let matched_devices: Vec = devices.into_iter() + .filter(|d| matches_filters(d, options.get_filters())) + .collect(); + for device in matched_devices { + if let Ok(address) = device.get_address() { let message = BluetoothObjectMsg::BluetoothDevice { - id: device.get_address().unwrap_or("".to_owned()), + id: address, name: device.get_name().ok(), device_class: device.get_class().ok(), vendor_id_source: device.get_vendor_id_source().ok(), @@ -399,10 +342,10 @@ impl BluetoothManager { Err(_) => None, }, }; - sender.send(message).unwrap(); - }, - None => send_error!(sender, "No device found, that matches the given options"), + return sender.send(message).unwrap(); + } } + send_error!(sender, "No device found, that matches the given options"); } pub fn gatt_server_connect(&mut self, device_id: String, sender: IpcSender) { @@ -456,19 +399,23 @@ impl BluetoothManager { Some(a) => a, None => send_error!(sender, "No adapter found"), }; - let service = match self.get_gatt_service_by_uuid(&mut adapter, &device_id, &uuid) { - Some(s) => s, - None => send_error!(sender, "No primary service found") - }; - if !service.is_primary().unwrap_or(false) { + let services = self.get_gatt_services_by_uuid(&mut adapter, &device_id, &uuid); + if services.is_empty() { send_error!(sender, "No primary service found"); } - let message = BluetoothObjectMsg::BluetoothService { - uuid: service.get_uuid().unwrap_or("".to_owned()), - is_primary: true, - instance_id: service.get_object_path(), - }; - sender.send(message).unwrap(); + for service in services { + if service.is_primary().unwrap_or(false) { + if let Ok(uuid) = service.get_uuid() { + let message = BluetoothObjectMsg::BluetoothService { + uuid: uuid, + is_primary: true, + instance_id: service.get_object_path(), + }; + return sender.send(message).unwrap(); + } + } + } + send_error!(sender, "No primary service found"); } pub fn get_primary_services(&mut self, @@ -508,25 +455,30 @@ impl BluetoothManager { Some(a) => a, None => send_error!(sender, "No adapter found"), }; - let characteristic = match self.get_gatt_characteristic_by_uuid(&mut adapter, &service_id, &uuid) { - Some(c) => c, - None => send_error!(sender, "No characteristic found"), - }; - let properties = self.get_characteristic_properties(&characteristic); - let message = BluetoothObjectMsg::BluetoothCharacteristic { - uuid: characteristic.get_uuid().unwrap_or("".to_owned()), - instance_id: characteristic.get_object_path(), - broadcast: properties[0], - read: properties[1], - write_without_response: properties[2], - write: properties[3], - notify: properties[4], - indicate: properties[5], - authenticated_signed_writes: properties[6], - reliable_write: properties[7], - writable_auxiliaries: properties[8], - }; - sender.send(message).unwrap(); + let characteristics = self.get_gatt_characteristics_by_uuid(&mut adapter, &service_id, &uuid); + if characteristics.is_empty() { + send_error!(sender, "No characteristic found"); + } + for characteristic in characteristics { + if let Ok(uuid) = characteristic.get_uuid() { + let properties = self.get_characteristic_properties(&characteristic); + let message = BluetoothObjectMsg::BluetoothCharacteristic { + uuid: uuid, + instance_id: characteristic.get_object_path(), + broadcast: properties[0], + read: properties[1], + write_without_response: properties[2], + write: properties[3], + notify: properties[4], + indicate: properties[5], + authenticated_signed_writes: properties[6], + reliable_write: properties[7], + writable_auxiliaries: properties[8], + }; + return sender.send(message).unwrap(); + } + } + send_error!(sender, "No characteristic found"); } pub fn get_characteristics(&mut self, @@ -576,16 +528,20 @@ impl BluetoothManager { Some(a) => a, None => send_error!(sender, "No adapter found"), }; - - let descriptor = match self.get_gatt_descriptor_by_uuid(&mut adapter, &characteristic_id, &uuid) { - Some(d) => d, - None => send_error!(sender, "No descriptor found"), - }; - let message = BluetoothObjectMsg::BluetoothDescriptor { - uuid: descriptor.get_uuid().unwrap_or("".to_owned()), - instance_id: descriptor.get_object_path(), - }; - sender.send(message).unwrap(); + let descriptors = self.get_gatt_descriptors_by_uuid(&mut adapter, &characteristic_id, &uuid); + if descriptors.is_empty() { + send_error!(sender, "No descriptor found"); + } + for descriptor in descriptors { + if let Ok(uuid) = descriptor.get_uuid() { + let message = BluetoothObjectMsg::BluetoothDescriptor { + uuid: uuid, + instance_id: descriptor.get_object_path(), + }; + return sender.send(message).unwrap(); + } + } + send_error!(sender, "No descriptor found"); } pub fn get_descriptors(&mut self, From 27ad1437a1af0b784a0c6dde91a936e6f55d0782 Mon Sep 17 00:00:00 2001 From: zakorgy Date: Wed, 6 Apr 2016 16:31:29 +0200 Subject: [PATCH 07/15] Error handling --- .../dom/bluetoothremotegattcharacteristic.rs | 15 ++---- .../dom/bluetoothremotegattdescriptor.rs | 17 +++--- .../script/dom/bluetoothremotegattserver.rs | 52 ++++++++----------- .../script/dom/bluetoothremotegattservice.rs | 37 ++++++------- .../BluetoothRemoteGATTCharacteristic.webidl | 1 + .../BluetoothRemoteGATTDescriptor.webidl | 1 + .../webidls/BluetoothRemoteGATTServer.webidl | 8 ++- .../webidls/BluetoothRemoteGATTService.webidl | 6 ++- 8 files changed, 61 insertions(+), 76 deletions(-) diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs index db487bb70bc..6d3bc5fe4f0 100644 --- a/components/script/dom/bluetoothremotegattcharacteristic.rs +++ b/components/script/dom/bluetoothremotegattcharacteristic.rs @@ -188,10 +188,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris }, BluetoothObjectMsg::Error { error - } => { - println!("{}", error); - None - }, + } => return Err(Type(error)), _ => unreachable!() }; *self.value.borrow_mut() = value; @@ -200,19 +197,17 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue - fn WriteValue(&self, value: Vec) { + fn WriteValue(&self, value: Vec) -> Fallible<()> { let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( BluetoothMethodMsg::WriteValue(self.get_instance_id(), value, sender)).unwrap(); let result = receiver.recv().unwrap(); match result { - BluetoothObjectMsg::BluetoothWriteValue => (), + BluetoothObjectMsg::BluetoothWriteValue => Ok(()), BluetoothObjectMsg::Error { error - } => { - println!("{}", error); - }, + } => Err(Type(error)), _ => unreachable!() - }; + } } } diff --git a/components/script/dom/bluetoothremotegattdescriptor.rs b/components/script/dom/bluetoothremotegattdescriptor.rs index 7b55e1d962e..9a48ee8395f 100644 --- a/components/script/dom/bluetoothremotegattdescriptor.rs +++ b/components/script/dom/bluetoothremotegattdescriptor.rs @@ -10,7 +10,7 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTDescriptorBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTDescriptorBinding::BluetoothRemoteGATTDescriptorMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods; -use dom::bindings::error::Error::Network; +use dom::bindings::error::Error::{Type, Network}; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; @@ -103,10 +103,7 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor { }, BluetoothObjectMsg::Error { error - } => { - println!("{}", error); - None - }, + } => return Err(Type(error)), _ => unreachable!() }; *self.value.borrow_mut() = value; @@ -115,19 +112,17 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue - fn WriteValue(&self, value: Vec) { + fn WriteValue(&self, value: Vec) -> Fallible<()> { let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( BluetoothMethodMsg::WriteValue(self.get_instance_id(), value, sender)).unwrap(); let result = receiver.recv().unwrap(); match result { - BluetoothObjectMsg::BluetoothWriteValue => (), + BluetoothObjectMsg::BluetoothWriteValue => Ok(()), BluetoothObjectMsg::Error { error - } => { - println!("{}", error); - }, + } => Err(Type(error)), _ => unreachable!() - }; + } } } diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs index e3b0e5bd8c9..a52482f2106 100644 --- a/components/script/dom/bluetoothremotegattserver.rs +++ b/components/script/dom/bluetoothremotegattserver.rs @@ -6,6 +6,8 @@ use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMet use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; use dom::bindings::codegen::UnionTypes::StringOrUnsignedLong; +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}; @@ -60,29 +62,28 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect - fn Connect(&self) -> Root { + fn Connect(&self) -> Fallible> { let (sender, receiver) = ipc::channel().unwrap(); - self.get_bluetooth_thread().send( - BluetoothMethodMsg::GATTServerConnect(String::from(self.Device().Id()), sender)).unwrap(); + self.get_bluetooth_thread() + .send(BluetoothMethodMsg::GATTServerConnect(String::from(self.Device().Id()), sender)) + .unwrap(); let server = receiver.recv().unwrap(); match server { BluetoothObjectMsg::BluetoothServer { connected } => { self.connected.set(connected); + Ok(Root::from_ref(self)) }, BluetoothObjectMsg::Error { error - } => { - println!("{}", error); - }, + } => Err(Type(error)), _ => unreachable!() } - Root::from_ref(self) } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-disconnect - fn Disconnect(&self) { + fn Disconnect(&self) -> Fallible<()>{ let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( BluetoothMethodMsg::GATTServerDisconnect(String::from(self.Device().Id()), sender)).unwrap(); @@ -92,24 +93,20 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { connected } => { self.connected.set(connected); + Ok(()) }, BluetoothObjectMsg::Error { error - } => { - println!("{}", error); - }, + } => Err(Type(error)), _ => unreachable!() } } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice - fn GetPrimaryService(&self, service: StringOrUnsignedLong) -> Option> { + fn GetPrimaryService(&self, service: StringOrUnsignedLong) -> Fallible> { let uuid: String = match BluetoothUUID::GetService(self.global().r(), service.clone()) { Ok(domstring) => domstring.to_string(), - Err(_) => { - println!("No UUID provided!"); - return None; - }, + Err(error) => return Err(error), }; let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( @@ -121,7 +118,7 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { is_primary, instance_id, } => { - Some(BluetoothRemoteGATTService::new(self.global().r(), + Ok(BluetoothRemoteGATTService::new(self.global().r(), &self.device.get(), DOMString::from(uuid), is_primary, @@ -129,28 +126,26 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { }, BluetoothObjectMsg::Error { error - } => { - println!("{}", error); - None - }, + } => Err(Type(error)), _ => unreachable!(), } } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices fn GetPrimaryServices(&self, service: Option) - -> Option>> { + -> Fallible>> { let uuid: Option = match service { Some(s) => match BluetoothUUID::GetService(self.global().r(), s.clone()) { Ok(domstring) => Some(domstring.to_string()), - Err(_) => None, + Err(error) => return Err(error), }, None => None, }; let mut services: Vec> = vec!(); let (sender, receiver) = ipc::channel().unwrap(); - self.get_bluetooth_thread().send( - BluetoothMethodMsg::GetPrimaryServices(String::from(self.Device().Id()), uuid, sender)).unwrap(); + self.get_bluetooth_thread() + .send(BluetoothMethodMsg::GetPrimaryServices(String::from(self.Device().Id()), uuid, sender)) + .unwrap(); let services_vec = receiver.recv().unwrap(); match services_vec { BluetoothObjectMsg::BluetoothServices { @@ -172,14 +167,11 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { _ => unreachable!(), } } - Some(services) + Ok(services) }, BluetoothObjectMsg::Error { error - } => { - println!("{}", error); - None - }, + } => Err(Type(error)), _ => unreachable!(), } } diff --git a/components/script/dom/bluetoothremotegattservice.rs b/components/script/dom/bluetoothremotegattservice.rs index 8d4afe48ed3..de98f887f0c 100644 --- a/components/script/dom/bluetoothremotegattservice.rs +++ b/components/script/dom/bluetoothremotegattservice.rs @@ -5,6 +5,8 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods; use dom::bindings::codegen::UnionTypes::StringOrUnsignedLong; +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}; @@ -84,18 +86,16 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic fn GetCharacteristic(&self, characteristic: StringOrUnsignedLong) - -> Option> { + -> Fallible> { let uuid: String = match BluetoothUUID::GetCharacteristic(self.global().r(), characteristic.clone()) { Ok(domstring) => domstring.to_string(), - Err(_) => { - println!("No UUID provided!"); - return None; - }, + Err(error) => return Err(error), }; let (sender, receiver) = ipc::channel().unwrap(); - self.get_bluetooth_thread().send( - BluetoothMethodMsg::GetCharacteristic(self.get_instance_id(), uuid, sender)).unwrap(); + self.get_bluetooth_thread() + .send(BluetoothMethodMsg::GetCharacteristic(self.get_instance_id(), uuid, sender)) + .unwrap(); let characteristic = receiver.recv().unwrap(); match characteristic { BluetoothObjectMsg::BluetoothCharacteristic { @@ -121,7 +121,7 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { authenticated_signed_writes, reliable_write, writable_auxiliaries); - Some(BluetoothRemoteGATTCharacteristic::new(self.global().r(), + Ok(BluetoothRemoteGATTCharacteristic::new(self.global().r(), &self, DOMString::from(uuid), properties, @@ -129,28 +129,26 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { }, BluetoothObjectMsg::Error { error - } => { - println!("{}", error); - None - }, + } => return Err(Type(error)), _ => unreachable!(), } } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics fn GetCharacteristics(&self, characteristic: Option) - -> Option>> { + -> Fallible>> { let uuid: Option = match characteristic { Some(c) => match BluetoothUUID::GetCharacteristic(self.global().r(), c.clone()) { Ok(domstring) => Some(domstring.to_string()), - Err(_) => None, + Err(error) => return Err(error), }, None => None, }; let mut characteristics: Vec> = vec!(); let (sender, receiver) = ipc::channel().unwrap(); - self.get_bluetooth_thread().send( - BluetoothMethodMsg::GetCharacteristics(self.get_instance_id(), uuid, sender)).unwrap(); + self.get_bluetooth_thread() + .send(BluetoothMethodMsg::GetCharacteristics(self.get_instance_id(), uuid, sender)) + .unwrap(); let characteristics_vec = receiver.recv().unwrap(); match characteristics_vec { BluetoothObjectMsg::BluetoothCharacteristics { @@ -192,14 +190,11 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { _ => unreachable!(), } } - Some(characteristics) + Ok(characteristics) }, BluetoothObjectMsg::Error { error - } => { - println!("{}", error); - None - }, + } => return Err(Type(error)), _ => unreachable!(), } } diff --git a/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl b/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl index 3024b3bc7f2..294e00e1b85 100644 --- a/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl +++ b/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl @@ -20,6 +20,7 @@ interface BluetoothRemoteGATTCharacteristic { [Throws] ByteString readValue(); //Promise readValue(); + [Throws] void writeValue(sequence value); //Promise writeValue(BufferSource value); //Promise startNotifications(); diff --git a/components/script/dom/webidls/BluetoothRemoteGATTDescriptor.webidl b/components/script/dom/webidls/BluetoothRemoteGATTDescriptor.webidl index 77becb830bf..853054f6e3a 100644 --- a/components/script/dom/webidls/BluetoothRemoteGATTDescriptor.webidl +++ b/components/script/dom/webidls/BluetoothRemoteGATTDescriptor.webidl @@ -12,6 +12,7 @@ interface BluetoothRemoteGATTDescriptor { [Throws] ByteString readValue(); //Promise readValue(); + [Throws] void writeValue(sequence value); //Promise writeValue(BufferSource value); }; diff --git a/components/script/dom/webidls/BluetoothRemoteGATTServer.webidl b/components/script/dom/webidls/BluetoothRemoteGATTServer.webidl index ac6af9649b1..835a6444103 100644 --- a/components/script/dom/webidls/BluetoothRemoteGATTServer.webidl +++ b/components/script/dom/webidls/BluetoothRemoteGATTServer.webidl @@ -8,10 +8,14 @@ interface BluetoothRemoteGATTServer { readonly attribute BluetoothDevice device; readonly attribute boolean connected; + [Throws] BluetoothRemoteGATTServer connect(); + [Throws] void disconnect(); - BluetoothRemoteGATTService? getPrimaryService((DOMString or unsigned long) service); - sequence? getPrimaryServices(optional (DOMString or unsigned long) service); + [Throws] + BluetoothRemoteGATTService getPrimaryService((DOMString or unsigned long) service); + [Throws] + sequence getPrimaryServices(optional (DOMString or unsigned long) service); //Promise getPrimaryService(BluetoothServiceUUID service); //Promise>getPrimaryServices(optional BluetoothServiceUUID service); //Promise connect(); diff --git a/components/script/dom/webidls/BluetoothRemoteGATTService.webidl b/components/script/dom/webidls/BluetoothRemoteGATTService.webidl index 1cc34ba41a3..e6673f69397 100644 --- a/components/script/dom/webidls/BluetoothRemoteGATTService.webidl +++ b/components/script/dom/webidls/BluetoothRemoteGATTService.webidl @@ -9,8 +9,10 @@ interface BluetoothRemoteGATTService { readonly attribute BluetoothDevice device; readonly attribute DOMString uuid; readonly attribute boolean isPrimary; - BluetoothRemoteGATTCharacteristic? getCharacteristic((DOMString or unsigned long) characteristic); - sequence? getCharacteristics + [Throws] + BluetoothRemoteGATTCharacteristic getCharacteristic((DOMString or unsigned long) characteristic); + [Throws] + sequence getCharacteristics (optional (DOMString or unsigned long) characteristic); //PromisegetCharacteristic(BluetoothCharacteristicUUID characteristic); //Promise> From f47f8d1a5cf26613082a97e6ad84e27674fd5f27 Mon Sep 17 00:00:00 2001 From: fokinv Date: Fri, 15 Apr 2016 15:32:13 +0200 Subject: [PATCH 08/15] Style fix --- components/net/bluetooth_thread.rs | 182 ++++++++++-------- components/script/dom/bluetooth.rs | 33 ++-- .../dom/bluetoothremotegattcharacteristic.rs | 43 +++-- .../dom/bluetoothremotegattdescriptor.rs | 15 +- .../script/dom/bluetoothremotegattserver.rs | 53 ++--- .../script/dom/bluetoothremotegattservice.rs | 77 ++++---- components/script/dom/bluetoothuuid.rs | 17 +- 7 files changed, 220 insertions(+), 200 deletions(-) diff --git a/components/net/bluetooth_thread.rs b/components/net/bluetooth_thread.rs index b298e78acab..82fe4891ee9 100644 --- a/components/net/bluetooth_thread.rs +++ b/components/net/bluetooth_thread.rs @@ -15,6 +15,14 @@ use std::collections::HashMap; use std::string::String; 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 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"; + macro_rules! send_error( ($sender:expr, $error:expr) => ( return $sender.send(BluetoothObjectMsg::Error { error: String::from($error) }).unwrap(); @@ -79,40 +87,40 @@ impl BluetoothManager { match self.receiver.recv().unwrap() { BluetoothMethodMsg::RequestDevice(options, sender) => { self.request_device(options, sender) - } + }, BluetoothMethodMsg::GATTServerConnect(device_id, sender) => { self.gatt_server_connect(device_id, sender) - } + }, BluetoothMethodMsg::GATTServerDisconnect(device_id, sender) => { 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::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) - } + }, BluetoothMethodMsg::GetDescriptors(characteristic_id, uuid, sender) => { self.get_descriptors(characteristic_id, uuid, sender) - } + }, BluetoothMethodMsg::ReadValue(id, sender) => { self.read_value(id, sender) - } + }, BluetoothMethodMsg::WriteValue(id, value, sender) => { self.write_value(id, value, sender) - } + }, BluetoothMethodMsg::Exit => { break - } + }, } } } @@ -132,7 +140,9 @@ impl BluetoothManager { fn get_devices(&mut self, adapter: &mut BluetoothAdapter) -> Vec { let devices = adapter.get_devices().unwrap_or(vec!()); for device in &devices { - self.cached_devices.insert(device.get_address().unwrap_or("".to_owned()), device.clone()); + if let Ok(address) = device.get_address() { + self.cached_devices.insert(address, device.clone()); + } } devices } @@ -159,10 +169,7 @@ impl BluetoothManager { services } - fn get_gatt_service(&mut self, - adapter: &mut BluetoothAdapter, - service_id: &str) - -> Option<&BluetoothGATTService> { + fn get_gatt_service(&mut self, adapter: &mut BluetoothAdapter, service_id: &str) -> Option<&BluetoothGATTService> { check_cache!(self.cached_services, service_id); let device_id = match self.service_to_device.get_mut(service_id) { Some(d) => d.clone(), @@ -182,8 +189,10 @@ impl BluetoothManager { let mut services_vec: Vec = vec!(); let services = self.get_gatt_services(adapter, device_id); for service in services { - if service.get_uuid().unwrap_or("".to_owned()) == service_uuid { - services_vec.push(service.clone()); + if let Ok(uuid) = service.get_uuid() { + if uuid == service_uuid { + services_vec.push(service.clone()); + } } } services_vec @@ -230,8 +239,10 @@ impl BluetoothManager { let mut characteristics_vec: Vec = vec!(); let characteristics = self.get_gatt_characteristics(adapter, service_id); for characteristic in characteristics { - if characteristic.get_uuid().unwrap_or("".to_owned()) == characteristic_uuid { - characteristics_vec.push(characteristic.clone()); + if let Ok(uuid) = characteristic.get_uuid() { + if uuid == characteristic_uuid { + characteristics_vec.push(characteristic.clone()); + } } } characteristics_vec @@ -298,8 +309,10 @@ impl BluetoothManager { let mut descriptors_vec: Vec = vec!(); let descriptors = self.get_gatt_descriptors(adapter, characteristic_id); for descriptor in descriptors { - if descriptor.get_uuid().unwrap_or("".to_owned()) == descriptor_uuid { - descriptors_vec.push(descriptor.clone()); + if let Ok(uuid) = descriptor.get_uuid() { + if uuid == descriptor_uuid { + descriptors_vec.push(descriptor.clone()); + } } } descriptors_vec @@ -307,16 +320,14 @@ impl BluetoothManager { // Methods - fn request_device(&mut self, - options: RequestDeviceoptions, - sender: IpcSender) { + fn request_device(&mut self, options: RequestDeviceoptions, sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, - None => send_error!(sender, "No adapter found"), + None => send_error!(sender, ADAPTER_ERROR), }; let devices = self.get_devices(&mut adapter); if devices.is_empty() { - send_error!(sender, "No device found"); + send_error!(sender, DEVICE_ERROR); } let matched_devices: Vec = devices.into_iter() @@ -345,13 +356,13 @@ impl BluetoothManager { return sender.send(message).unwrap(); } } - send_error!(sender, "No device found, that matches the given options"); + send_error!(sender, DEVICE_MATCH_ERROR); } pub fn gatt_server_connect(&mut self, device_id: String, sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, - None => send_error!(sender, "No adapter found"), + None => send_error!(sender, ADAPTER_ERROR), }; let connected = match self.get_device(&mut adapter, &device_id) { @@ -361,8 +372,8 @@ impl BluetoothManager { } else { !d.connect().is_err() } - } - None => send_error!(sender, "No device found"), + }, + None => send_error!(sender, DEVICE_ERROR), }; let message = BluetoothObjectMsg::BluetoothServer { @@ -374,7 +385,7 @@ impl BluetoothManager { pub fn gatt_server_disconnect(&mut self, device_id: String, sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, - None => send_error!(sender, "No adapter found"), + None => send_error!(sender, ADAPTER_ERROR), }; let connected = match self.get_device(&mut adapter, &device_id) { @@ -384,8 +395,8 @@ impl BluetoothManager { } else { false } - } - None => send_error!(sender, "No device found"), + }, + None => send_error!(sender, DEVICE_ERROR), }; let message = BluetoothObjectMsg::BluetoothServer { @@ -397,11 +408,11 @@ impl BluetoothManager { pub fn get_primary_service(&mut self, device_id: String, uuid: String, sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, - None => send_error!(sender, "No adapter found"), + None => send_error!(sender, ADAPTER_ERROR), }; let services = self.get_gatt_services_by_uuid(&mut adapter, &device_id, &uuid); if services.is_empty() { - send_error!(sender, "No primary service found"); + send_error!(sender, PRIMARY_SERVICE_ERROR); } for service in services { if service.is_primary().unwrap_or(false) { @@ -415,7 +426,7 @@ impl BluetoothManager { } } } - send_error!(sender, "No primary service found"); + send_error!(sender, PRIMARY_SERVICE_ERROR); } pub fn get_primary_services(&mut self, @@ -424,27 +435,29 @@ impl BluetoothManager { sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, - None => send_error!(sender, "No adapter found"), + None => send_error!(sender, ADAPTER_ERROR), }; let services: Vec = match uuid { Some(id) => self.get_gatt_services_by_uuid(&mut adapter, &device_id, &id), None => self.get_gatt_services(&mut adapter, &device_id), }; if services.is_empty() { - send_error!(sender, "No service found"); + send_error!(sender, PRIMARY_SERVICE_ERROR); } let mut services_vec: Vec = vec!(); for service in services { if service.is_primary().unwrap_or(false) { - services_vec.push(BluetoothObjectMsg::BluetoothService { - uuid: service.get_uuid().unwrap_or("".to_owned()), - is_primary: true, - instance_id: service.get_object_path(), - }); + if let Ok(uuid) = service.get_uuid() { + services_vec.push(BluetoothObjectMsg::BluetoothService { + uuid: uuid, + is_primary: true, + instance_id: service.get_object_path(), + }); + } } } if services_vec.is_empty() { - send_error!(sender, "No service found"); + send_error!(sender, PRIMARY_SERVICE_ERROR); } let message = BluetoothObjectMsg::BluetoothServices { services_vec: services_vec }; sender.send(message).unwrap(); @@ -453,11 +466,11 @@ impl BluetoothManager { pub fn get_characteristic(&mut self, service_id: String, uuid: String, sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, - None => send_error!(sender, "No adapter found"), + None => send_error!(sender, ADAPTER_ERROR), }; let characteristics = self.get_gatt_characteristics_by_uuid(&mut adapter, &service_id, &uuid); if characteristics.is_empty() { - send_error!(sender, "No characteristic found"); + send_error!(sender, CHARACTERISTIC_ERROR); } for characteristic in characteristics { if let Ok(uuid) = characteristic.get_uuid() { @@ -478,7 +491,7 @@ impl BluetoothManager { return sender.send(message).unwrap(); } } - send_error!(sender, "No characteristic found"); + send_error!(sender, CHARACTERISTIC_ERROR); } pub fn get_characteristics(&mut self, @@ -487,50 +500,49 @@ impl BluetoothManager { sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, - None => send_error!(sender, "No adapter found"), + None => send_error!(sender, ADAPTER_ERROR), }; let characteristics = match uuid { Some(id) => self.get_gatt_characteristics_by_uuid(&mut adapter, &service_id, &id), None => self.get_gatt_characteristics(&mut adapter, &service_id), }; if characteristics.is_empty() { - send_error!(sender, "No characteristic found"); + send_error!(sender, CHARACTERISTIC_ERROR); } let mut characteristics_vec: Vec = vec!(); for characteristic in characteristics { - let properties = self.get_characteristic_properties(&characteristic); - characteristics_vec.push(BluetoothObjectMsg::BluetoothCharacteristic { - uuid: characteristic.get_uuid().unwrap_or("".to_owned()), - instance_id: characteristic.get_object_path(), - broadcast: properties[0], - read: properties[1], - write_without_response: properties[2], - write: properties[3], - notify: properties[4], - indicate: properties[5], - authenticated_signed_writes: properties[6], - reliable_write: properties[7], - writable_auxiliaries: properties[8], - }); + if let Ok(uuid) = characteristic.get_uuid() { + let properties = self.get_characteristic_properties(&characteristic); + characteristics_vec.push(BluetoothObjectMsg::BluetoothCharacteristic { + uuid: uuid, + instance_id: characteristic.get_object_path(), + broadcast: properties[0], + read: properties[1], + write_without_response: properties[2], + write: properties[3], + notify: properties[4], + indicate: properties[5], + authenticated_signed_writes: properties[6], + reliable_write: properties[7], + writable_auxiliaries: properties[8], + }); + } } if characteristics_vec.is_empty() { - send_error!(sender, "No characteristic found"); + send_error!(sender, CHARACTERISTIC_ERROR); } let message = BluetoothObjectMsg::BluetoothCharacteristics { characteristics_vec: characteristics_vec }; sender.send(message).unwrap(); } - pub fn get_descriptor(&mut self, - characteristic_id: String, - uuid: String, - sender: IpcSender) { + pub fn get_descriptor(&mut self, characteristic_id: String, uuid: String, sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, - None => send_error!(sender, "No adapter found"), + None => send_error!(sender, ADAPTER_ERROR), }; let descriptors = self.get_gatt_descriptors_by_uuid(&mut adapter, &characteristic_id, &uuid); if descriptors.is_empty() { - send_error!(sender, "No descriptor found"); + send_error!(sender, DESCRIPTOR_ERROR); } for descriptor in descriptors { if let Ok(uuid) = descriptor.get_uuid() { @@ -541,7 +553,7 @@ impl BluetoothManager { return sender.send(message).unwrap(); } } - send_error!(sender, "No descriptor found"); + send_error!(sender, DESCRIPTOR_ERROR); } pub fn get_descriptors(&mut self, @@ -550,24 +562,26 @@ impl BluetoothManager { sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, - None => send_error!(sender, "No adapter found"), + None => send_error!(sender, ADAPTER_ERROR), }; let descriptors = match uuid { Some(id) => self.get_gatt_descriptors_by_uuid(&mut adapter, &characteristic_id, &id), None => self.get_gatt_descriptors(&mut adapter, &characteristic_id), }; if descriptors.is_empty() { - send_error!(sender, "No descriptor found"); + send_error!(sender, DESCRIPTOR_ERROR); } let mut descriptors_vec: Vec = vec!(); for descriptor in descriptors { - descriptors_vec.push(BluetoothObjectMsg::BluetoothDescriptor { - uuid: descriptor.get_uuid().unwrap_or("".to_owned()), - instance_id: descriptor.get_object_path(), - }); + if let Ok(uuid) = descriptor.get_uuid() { + descriptors_vec.push(BluetoothObjectMsg::BluetoothDescriptor { + uuid: uuid, + instance_id: descriptor.get_object_path(), + }); + } } if descriptors_vec.is_empty() { - send_error!(sender, "No descriptor found"); + send_error!(sender, DESCRIPTOR_ERROR); } let message = BluetoothObjectMsg::BluetoothDescriptors { descriptors_vec: descriptors_vec }; sender.send(message).unwrap(); @@ -576,7 +590,7 @@ impl BluetoothManager { pub fn read_value(&mut self, id: String, sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, - None => send_error!(sender, "No adapter found"), + None => send_error!(sender, ADAPTER_ERROR), }; let mut value = match self.get_gatt_characteristic(&mut adapter, &id) { Some(c) => Some(c.read_value().unwrap_or(vec!())), @@ -591,7 +605,7 @@ impl BluetoothManager { let message = match value { Some(v) => BluetoothObjectMsg::BluetoothReadValue { value: v }, - None => send_error!(sender, "No characteristic or descriptor found with that id"), + None => send_error!(sender, VALUE_ERROR), }; sender.send(message).unwrap(); @@ -600,7 +614,7 @@ impl BluetoothManager { pub fn write_value(&mut self, id: String, value: Vec, sender: IpcSender) { let mut adapter = match self.get_adapter() { Some(a) => a, - None => send_error!(sender, "No adapter found"), + None => send_error!(sender, ADAPTER_ERROR), }; let mut result = match self.get_gatt_characteristic(&mut adapter, &id) { Some(c) => Some(c.write_value(value.clone())), @@ -618,7 +632,7 @@ impl BluetoothManager { Ok(_) => BluetoothObjectMsg::BluetoothWriteValue, Err(e) => send_error!(sender, e.to_string()), }, - None => send_error!(sender, "No characteristic or descriptor found with that id"), + None => send_error!(sender, VALUE_ERROR), }; sender.send(message).unwrap(); diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs index b66a427864a..d56528d845a 100644 --- a/components/script/dom/bluetooth.rs +++ b/components/script/dom/bluetooth.rs @@ -23,13 +23,13 @@ use util::str::DOMString; // A device name can never be longer than 29 bytes. An adv packet is at most // 31 bytes long. The length and identifier of the length field take 2 bytes. -// That least 29 bytes for the name. -const MAX_FILTER_NAME_LENGTH: usize = 29; -// 248 is the maximum number of UTF-8 code units in a Bluetooth Device Name. -const MAX_DEVICE_NAME_LENGTH: usize = 248; const FILTER_EMPTY_ERROR: &'static str = "'filters' member must be non - empty to find any devices."; const FILTER_ERROR: &'static str = "A filter must restrict the devices in some way."; const FILTER_NAME_TOO_LONG_ERROR: &'static str = "A 'name' or 'namePrefix' can't be longer then 29 bytes."; +// 248 is the maximum number of UTF-8 code units in a Bluetooth Device Name. +const MAX_DEVICE_NAME_LENGTH: usize = 248; +// That least 29 bytes for the name. +const MAX_FILTER_NAME_LENGTH: usize = 29; const NAME_PREFIX_ERROR: &'static str = "'namePrefix', if present, must be non - empty."; const NAME_TOO_LONG_ERROR: &'static str = "A device name can't be longer than 248 bytes."; const SERVICE_ERROR: &'static str = "'services', if present, must contain at least one service."; @@ -79,11 +79,8 @@ impl Clone for RequestDeviceOptions { } } -fn canonicalize_filter(filter: &BluetoothScanFilter, global: GlobalRef) - -> Fallible { - if !(filter.services.is_some() || - filter.name.is_some() || - filter.namePrefix.is_some()) { +fn canonicalize_filter(filter: &BluetoothScanFilter, global: GlobalRef) -> Fallible { + if !(filter.services.is_some() || filter.name.is_some() || filter.namePrefix.is_some()) { return Err(Type(FILTER_ERROR.to_owned())); } @@ -129,8 +126,9 @@ fn canonicalize_filter(filter: &BluetoothScanFilter, global: GlobalRef) Ok(BluetoothScanfilter::new(name, name_prefix, services_vec)) } -fn convert_request_device_options(options: &RequestDeviceOptions, global: GlobalRef) - -> Fallible { +fn convert_request_device_options(options: &RequestDeviceOptions, + global: GlobalRef) + -> Fallible { if options.filters.is_empty() { return Err(Type(FILTER_EMPTY_ERROR.to_owned())); } @@ -160,15 +158,12 @@ fn convert_request_device_options(options: &RequestDeviceOptions, global: Global impl BluetoothMethods for Bluetooth { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice - fn RequestDevice(&self, - option: &RequestDeviceOptions) - -> Fallible> { + fn RequestDevice(&self, option: &RequestDeviceOptions) -> Fallible> { let (sender, receiver) = ipc::channel().unwrap(); match convert_request_device_options(option, self.global().r()) { Ok(option) => { - self.get_bluetooth_thread() - .send(BluetoothMethodMsg::RequestDevice(option, sender)) - .unwrap(); + self.get_bluetooth_thread().send( + BluetoothMethodMsg::RequestDevice(option, sender)).unwrap(); let device = receiver.recv().unwrap(); match device { BluetoothObjectMsg::BluetoothDevice { @@ -211,7 +206,9 @@ impl BluetoothMethods for Bluetooth { }, BluetoothObjectMsg::Error { error - } => return Err(Type(error)), + } => { + Err(Type(error)) + }, _ => unreachable!() } }, diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs index 6d3bc5fe4f0..19e78e09f84 100644 --- a/components/script/dom/bluetoothremotegattcharacteristic.rs +++ b/components/script/dom/bluetoothremotegattcharacteristic.rs @@ -11,7 +11,7 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::Bluetoot use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods; use dom::bindings::codegen::UnionTypes::StringOrUnsignedLong; use dom::bindings::error::Error::{Network, Type}; -use dom::bindings::error::Fallible; +use dom::bindings::error::{Fallible, ErrorResult}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; @@ -61,8 +61,8 @@ impl BluetoothRemoteGATTCharacteristic { uuid, properties, instanceID), - global, - BluetoothRemoteGATTCharacteristicBinding::Wrap) + global, + BluetoothRemoteGATTCharacteristicBinding::Wrap) } fn get_bluetooth_thread(&self) -> IpcSender { @@ -94,9 +94,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor - fn GetDescriptor(&self, - descriptor: StringOrUnsignedLong) - -> Fallible> { + fn GetDescriptor(&self, descriptor: StringOrUnsignedLong) -> Fallible> { let uuid: String = match BluetoothUUID::GetDescriptor(self.global().r(), descriptor.clone()) { Ok(domstring) => domstring.to_string(), Err(error) => return Err(error), @@ -117,7 +115,9 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris }, BluetoothObjectMsg::Error { error - } => Err(Type(error)), + } => { + Err(Type(error)) + }, _ => unreachable!() } } @@ -126,12 +126,12 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris fn GetDescriptors(&self, descriptor: Option) -> Fallible>> { - let uuid: Option = match descriptor { - Some(d) => match BluetoothUUID::GetDescriptor(self.global().r(), d.clone()) { - Ok(domstring) => Some(domstring.to_string()), + let mut uuid: Option = None; + if let Some(d)= descriptor { + match BluetoothUUID::GetCharacteristic(self.global().r(), d.clone()) { + Ok(domstring) => uuid = Some(domstring.to_string()), Err(error) => return Err(error), - }, - None => None, + } }; let (sender, receiver) = ipc::channel().unwrap(); let mut descriptors: Vec> = vec!(); @@ -151,7 +151,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris descriptors.push(BluetoothRemoteGATTDescriptor::new(self.global().r(), &self, DOMString::from(uuid), - instance_id)) + instance_id)); }, _ => unreachable!(), } @@ -160,7 +160,9 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris }, BluetoothObjectMsg::Error { error - } => Err(Type(error)), + } => { + Err(Type(error)) + }, _ => unreachable!(), } } @@ -175,8 +177,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris let (sender, receiver) = ipc::channel().unwrap(); if !self.Service().Device().Gatt().Connected() { Err(Network) - } - else { + } else { self.get_bluetooth_thread().send( BluetoothMethodMsg::ReadValue(self.get_instance_id(), sender)).unwrap(); let result = receiver.recv().unwrap(); @@ -188,7 +189,9 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris }, BluetoothObjectMsg::Error { error - } => return Err(Type(error)), + } => { + return Err(Type(error)) + }, _ => unreachable!() }; *self.value.borrow_mut() = value; @@ -197,7 +200,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue - fn WriteValue(&self, value: Vec) -> Fallible<()> { + fn WriteValue(&self, value: Vec) -> ErrorResult { let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( BluetoothMethodMsg::WriteValue(self.get_instance_id(), value, sender)).unwrap(); @@ -206,7 +209,9 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris BluetoothObjectMsg::BluetoothWriteValue => Ok(()), BluetoothObjectMsg::Error { error - } => Err(Type(error)), + } => { + Err(Type(error)) + }, _ => unreachable!() } } diff --git a/components/script/dom/bluetoothremotegattdescriptor.rs b/components/script/dom/bluetoothremotegattdescriptor.rs index 9a48ee8395f..edbc61f9e3a 100644 --- a/components/script/dom/bluetoothremotegattdescriptor.rs +++ b/components/script/dom/bluetoothremotegattdescriptor.rs @@ -11,7 +11,7 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTDescriptorBinding::Blue use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods; use dom::bindings::error::Error::{Type, Network}; -use dom::bindings::error::Fallible; +use dom::bindings::error::{Fallible, ErrorResult}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; @@ -90,8 +90,7 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor { let (sender, receiver) = ipc::channel().unwrap(); if !self.Characteristic().Service().Device().Gatt().Connected() { Err(Network) - } - else { + } else { self.get_bluetooth_thread().send( BluetoothMethodMsg::ReadValue(self.get_instance_id(), sender)).unwrap(); let result = receiver.recv().unwrap(); @@ -103,7 +102,9 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor { }, BluetoothObjectMsg::Error { error - } => return Err(Type(error)), + } => { + return Err(Type(error)) + }, _ => unreachable!() }; *self.value.borrow_mut() = value; @@ -112,7 +113,7 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue - fn WriteValue(&self, value: Vec) -> Fallible<()> { + fn WriteValue(&self, value: Vec) -> ErrorResult { let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( BluetoothMethodMsg::WriteValue(self.get_instance_id(), value, sender)).unwrap(); @@ -121,7 +122,9 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor { BluetoothObjectMsg::BluetoothWriteValue => Ok(()), BluetoothObjectMsg::Error { error - } => Err(Type(error)), + } => { + Err(Type(error)) + }, _ => unreachable!() } } diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs index a52482f2106..a6c6f42769f 100644 --- a/components/script/dom/bluetoothremotegattserver.rs +++ b/components/script/dom/bluetoothremotegattserver.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; use dom::bindings::codegen::UnionTypes::StringOrUnsignedLong; use dom::bindings::error::Error::Type; -use dom::bindings::error::Fallible; +use dom::bindings::error::{Fallible, ErrorResult}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; @@ -64,9 +64,8 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect fn Connect(&self) -> Fallible> { let (sender, receiver) = ipc::channel().unwrap(); - self.get_bluetooth_thread() - .send(BluetoothMethodMsg::GATTServerConnect(String::from(self.Device().Id()), sender)) - .unwrap(); + self.get_bluetooth_thread().send( + BluetoothMethodMsg::GATTServerConnect(String::from(self.Device().Id()), sender)).unwrap(); let server = receiver.recv().unwrap(); match server { BluetoothObjectMsg::BluetoothServer { @@ -77,13 +76,15 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { }, BluetoothObjectMsg::Error { error - } => Err(Type(error)), + } => { + Err(Type(error)) + }, _ => unreachable!() } } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-disconnect - fn Disconnect(&self) -> Fallible<()>{ + fn Disconnect(&self) -> ErrorResult { let (sender, receiver) = ipc::channel().unwrap(); self.get_bluetooth_thread().send( BluetoothMethodMsg::GATTServerDisconnect(String::from(self.Device().Id()), sender)).unwrap(); @@ -97,7 +98,9 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { }, BluetoothObjectMsg::Error { error - } => Err(Type(error)), + } => { + Err(Type(error)) + }, _ => unreachable!() } } @@ -119,33 +122,35 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { instance_id, } => { Ok(BluetoothRemoteGATTService::new(self.global().r(), - &self.device.get(), - DOMString::from(uuid), - is_primary, - instance_id)) + &self.device.get(), + DOMString::from(uuid), + is_primary, + instance_id)) }, BluetoothObjectMsg::Error { error - } => Err(Type(error)), + } => { + Err(Type(error)) + }, _ => unreachable!(), } } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices - fn GetPrimaryServices(&self, service: Option) + fn GetPrimaryServices(&self, + service: Option) -> Fallible>> { - let uuid: Option = match service { - Some(s) => match BluetoothUUID::GetService(self.global().r(), s.clone()) { - Ok(domstring) => Some(domstring.to_string()), + let mut uuid: Option = None; + if let Some(s)= service { + match BluetoothUUID::GetService(self.global().r(), s.clone()) { + Ok(domstring) => uuid = Some(domstring.to_string()), Err(error) => return Err(error), - }, - None => None, + } }; let mut services: Vec> = vec!(); let (sender, receiver) = ipc::channel().unwrap(); - self.get_bluetooth_thread() - .send(BluetoothMethodMsg::GetPrimaryServices(String::from(self.Device().Id()), uuid, sender)) - .unwrap(); + self.get_bluetooth_thread().send( + BluetoothMethodMsg::GetPrimaryServices(String::from(self.Device().Id()), uuid, sender)).unwrap(); let services_vec = receiver.recv().unwrap(); match services_vec { BluetoothObjectMsg::BluetoothServices { @@ -162,7 +167,7 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { &self.device.get(), DOMString::from(uuid), is_primary, - instance_id)) + instance_id)); }, _ => unreachable!(), } @@ -171,7 +176,9 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { }, BluetoothObjectMsg::Error { error - } => Err(Type(error)), + } => { + Err(Type(error)) + }, _ => unreachable!(), } } diff --git a/components/script/dom/bluetoothremotegattservice.rs b/components/script/dom/bluetoothremotegattservice.rs index de98f887f0c..77820521552 100644 --- a/components/script/dom/bluetoothremotegattservice.rs +++ b/components/script/dom/bluetoothremotegattservice.rs @@ -85,17 +85,16 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic - fn GetCharacteristic(&self, characteristic: StringOrUnsignedLong) + fn GetCharacteristic(&self, + characteristic: StringOrUnsignedLong) -> Fallible> { - let uuid: String = match BluetoothUUID::GetCharacteristic(self.global().r(), - characteristic.clone()) { + let uuid: String = match BluetoothUUID::GetCharacteristic(self.global().r(), characteristic.clone()) { Ok(domstring) => domstring.to_string(), Err(error) => return Err(error), }; let (sender, receiver) = ipc::channel().unwrap(); - self.get_bluetooth_thread() - .send(BluetoothMethodMsg::GetCharacteristic(self.get_instance_id(), uuid, sender)) - .unwrap(); + self.get_bluetooth_thread().send( + BluetoothMethodMsg::GetCharacteristic(self.get_instance_id(), uuid, sender)).unwrap(); let characteristic = receiver.recv().unwrap(); match characteristic { BluetoothObjectMsg::BluetoothCharacteristic { @@ -122,33 +121,35 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { reliable_write, writable_auxiliaries); Ok(BluetoothRemoteGATTCharacteristic::new(self.global().r(), - &self, - DOMString::from(uuid), - properties, - instance_id)) + &self, + DOMString::from(uuid), + properties, + instance_id)) }, BluetoothObjectMsg::Error { error - } => return Err(Type(error)), + } => { + Err(Type(error)) + }, _ => unreachable!(), } } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics - fn GetCharacteristics(&self, characteristic: Option) + fn GetCharacteristics(&self, + characteristic: Option) -> Fallible>> { - let uuid: Option = match characteristic { - Some(c) => match BluetoothUUID::GetCharacteristic(self.global().r(), c.clone()) { - Ok(domstring) => Some(domstring.to_string()), + let mut uuid: Option = None; + if let Some(c)= characteristic { + match BluetoothUUID::GetCharacteristic(self.global().r(), c.clone()) { + Ok(domstring) => uuid = Some(domstring.to_string()), Err(error) => return Err(error), - }, - None => None, + } }; let mut characteristics: Vec> = vec!(); let (sender, receiver) = ipc::channel().unwrap(); - self.get_bluetooth_thread() - .send(BluetoothMethodMsg::GetCharacteristics(self.get_instance_id(), uuid, sender)) - .unwrap(); + self.get_bluetooth_thread().send( + BluetoothMethodMsg::GetCharacteristics(self.get_instance_id(), uuid, sender)).unwrap(); let characteristics_vec = receiver.recv().unwrap(); match characteristics_vec { BluetoothObjectMsg::BluetoothCharacteristics { @@ -169,23 +170,21 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { reliable_write, writable_auxiliaries, } => { - let properties = &BluetoothCharacteristicProperties::new( - self.global().r(), - broadcast, - read, - write_without_response, - write, - notify, - indicate, - authenticated_signed_writes, - reliable_write, - writable_auxiliaries); - characteristics.push(BluetoothRemoteGATTCharacteristic::new( - self.global().r(), - &self, - DOMString::from(uuid), - properties, - instance_id)) + let properties = &BluetoothCharacteristicProperties::new(self.global().r(), + broadcast, + read, + write_without_response, + write, + notify, + indicate, + authenticated_signed_writes, + reliable_write, + writable_auxiliaries); + characteristics.push(BluetoothRemoteGATTCharacteristic::new(self.global().r(), + &self, + DOMString::from(uuid), + properties, + instance_id)); }, _ => unreachable!(), } @@ -194,7 +193,9 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { }, BluetoothObjectMsg::Error { error - } => return Err(Type(error)), + } => { + Err(Type(error)) + }, _ => unreachable!(), } } diff --git a/components/script/dom/bluetoothuuid.rs b/components/script/dom/bluetoothuuid.rs index 91c581d5d3b..e916c6ebded 100644 --- a/components/script/dom/bluetoothuuid.rs +++ b/components/script/dom/bluetoothuuid.rs @@ -274,9 +274,7 @@ impl BluetoothUUID { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-getservice - pub fn GetService(globalref: GlobalRef, - name: StringOrUnsignedLong) - -> Fallible { + pub fn GetService(globalref: GlobalRef, name: StringOrUnsignedLong) -> Fallible { BluetoothUUID::resolve_uuid_name(globalref, name, BLUETOOTH_ASSIGNED_SERVICES, @@ -284,9 +282,7 @@ impl BluetoothUUID { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-getcharacteristic - pub fn GetCharacteristic(globalref: GlobalRef, - name: StringOrUnsignedLong) - -> Fallible { + pub fn GetCharacteristic(globalref: GlobalRef, name: StringOrUnsignedLong) -> Fallible { BluetoothUUID::resolve_uuid_name(globalref, name, BLUETOOTH_ASSIGNED_CHARCTERISTICS, @@ -294,9 +290,7 @@ impl BluetoothUUID { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-getdescriptor - pub fn GetDescriptor(globalref: GlobalRef, - name: StringOrUnsignedLong) - -> Fallible { + pub fn GetDescriptor(globalref: GlobalRef, name: StringOrUnsignedLong) -> Fallible { BluetoothUUID::resolve_uuid_name(globalref, name, BLUETOOTH_ASSIGNED_DESCRIPTORS, @@ -311,7 +305,7 @@ impl BluetoothUUID { -> Fallible { match name { // Step 1 - StringOrUnsignedLong::UnsignedLong(unsigned32) =>{ + StringOrUnsignedLong::UnsignedLong(unsigned32) => { Ok(BluetoothUUID::CanonicalUUID(globalref, unsigned32)) }, StringOrUnsignedLong::String(dstring) => { @@ -322,8 +316,7 @@ impl BluetoothUUID { } else { // Step 3 let concatenated = format!("{}.{}", prefix, dstring); - let is_in_table = assigned_numbers_table.iter() - .find(|p| p.0 == concatenated); + let is_in_table = assigned_numbers_table.iter().find(|p| p.0 == concatenated); match is_in_table { Some(&(_, alias)) => Ok(BluetoothUUID::CanonicalUUID(globalref, alias)), None => Err(Syntax), From 76d6685d7f982bef2642a6356ecab358178d4184 Mon Sep 17 00:00:00 2001 From: zakorgyula Date: Mon, 21 Mar 2016 13:56:56 +0100 Subject: [PATCH 09/15] Add html tests --- tests/html/bluetooth_battery_level.html | 61 ++++++++++++ tests/html/bluetooth_characteristic_info.html | 69 ++++++++++++++ tests/html/bluetooth_descriptor_info.html | 68 ++++++++++++++ tests/html/bluetooth_device_disconnect.html | 94 +++++++++++++++++++ tests/html/bluetooth_device_info.html | 59 ++++++++++++ .../html/bluetooth_primary_service_info.html | 57 +++++++++++ 6 files changed, 408 insertions(+) create mode 100644 tests/html/bluetooth_battery_level.html create mode 100644 tests/html/bluetooth_characteristic_info.html create mode 100644 tests/html/bluetooth_descriptor_info.html create mode 100644 tests/html/bluetooth_device_disconnect.html create mode 100644 tests/html/bluetooth_device_info.html create mode 100644 tests/html/bluetooth_primary_service_info.html diff --git a/tests/html/bluetooth_battery_level.html b/tests/html/bluetooth_battery_level.html new file mode 100644 index 00000000000..8618df07859 --- /dev/null +++ b/tests/html/bluetooth_battery_level.html @@ -0,0 +1,61 @@ + + +Battery Level + + + + +

+    
+
+
diff --git a/tests/html/bluetooth_characteristic_info.html b/tests/html/bluetooth_characteristic_info.html
new file mode 100644
index 00000000000..84cebd83014
--- /dev/null
+++ b/tests/html/bluetooth_characteristic_info.html
@@ -0,0 +1,69 @@
+
+
+Characteristic info
+
+    
+    
+    
+    

+    
+
+
diff --git a/tests/html/bluetooth_descriptor_info.html b/tests/html/bluetooth_descriptor_info.html
new file mode 100644
index 00000000000..c657d217697
--- /dev/null
+++ b/tests/html/bluetooth_descriptor_info.html
@@ -0,0 +1,68 @@
+
+
+Descriptor info
+
+    
+    
+    
+    
+    

+    
+
+
diff --git a/tests/html/bluetooth_device_disconnect.html b/tests/html/bluetooth_device_disconnect.html
new file mode 100644
index 00000000000..715d3d16a24
--- /dev/null
+++ b/tests/html/bluetooth_device_disconnect.html
@@ -0,0 +1,94 @@
+
+
+Device Disconnect
+
+    
+    
+    
+    
+    
+    
+    

+    
+
+
diff --git a/tests/html/bluetooth_device_info.html b/tests/html/bluetooth_device_info.html
new file mode 100644
index 00000000000..0cdc09a95ab
--- /dev/null
+++ b/tests/html/bluetooth_device_info.html
@@ -0,0 +1,59 @@
+
+
+Device Info
+
+    
+    
+    
+    
+    

+    
+
+
diff --git a/tests/html/bluetooth_primary_service_info.html b/tests/html/bluetooth_primary_service_info.html
new file mode 100644
index 00000000000..606d342c85d
--- /dev/null
+++ b/tests/html/bluetooth_primary_service_info.html
@@ -0,0 +1,57 @@
+
+
+Primary Service info
+
+    
+    
+    
+    
+    

+    
+
+

From 402bc552cae3840993e10def211c16440e5bc005 Mon Sep 17 00:00:00 2001
From: zakorgy 
Date: Fri, 22 Apr 2016 12:49:38 +0200
Subject: [PATCH 10/15] Replace the union types with the correct typedefs in
 the webidl files and the API classes.

---
 .../script/dom/bluetoothremotegattcharacteristic.rs      | 7 +++----
 components/script/dom/bluetoothremotegattserver.rs       | 7 +++----
 components/script/dom/bluetoothremotegattservice.rs      | 7 +++----
 components/script/dom/bluetoothuuid.rs                   | 9 ++++++---
 .../dom/webidls/BluetoothRemoteGATTCharacteristic.webidl | 4 ++--
 .../script/dom/webidls/BluetoothRemoteGATTServer.webidl  | 4 ++--
 .../script/dom/webidls/BluetoothRemoteGATTService.webidl | 4 ++--
 7 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs
index 19e78e09f84..1a0e9c02010 100644
--- a/components/script/dom/bluetoothremotegattcharacteristic.rs
+++ b/components/script/dom/bluetoothremotegattcharacteristic.rs
@@ -9,7 +9,6 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding::
     BluetoothRemoteGATTCharacteristicMethods;
 use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
 use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
-use dom::bindings::codegen::UnionTypes::StringOrUnsignedLong;
 use dom::bindings::error::Error::{Network, Type};
 use dom::bindings::error::{Fallible, ErrorResult};
 use dom::bindings::global::GlobalRef;
@@ -19,7 +18,7 @@ use dom::bindings::str::ByteString;
 use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties;
 use dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor;
 use dom::bluetoothremotegattservice::BluetoothRemoteGATTService;
-use dom::bluetoothuuid::BluetoothUUID;
+use dom::bluetoothuuid::{BluetoothDescriptorUUID, BluetoothUUID};
 use ipc_channel::ipc::{self, IpcSender};
 use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg};
 use util::str::DOMString;
@@ -94,7 +93,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor
-    fn GetDescriptor(&self, descriptor: StringOrUnsignedLong) -> Fallible> {
+    fn GetDescriptor(&self, descriptor: BluetoothDescriptorUUID) -> Fallible> {
         let uuid: String = match BluetoothUUID::GetDescriptor(self.global().r(), descriptor.clone()) {
             Ok(domstring) => domstring.to_string(),
             Err(error) => return Err(error),
@@ -124,7 +123,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors
     fn GetDescriptors(&self,
-                      descriptor: Option)
+                      descriptor: Option)
                       -> Fallible>> {
         let mut uuid: Option = None;
         if let Some(d)= descriptor {
diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs
index a6c6f42769f..f34261eb54b 100644
--- a/components/script/dom/bluetoothremotegattserver.rs
+++ b/components/script/dom/bluetoothremotegattserver.rs
@@ -5,7 +5,6 @@
 use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
 use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding;
 use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
-use dom::bindings::codegen::UnionTypes::StringOrUnsignedLong;
 use dom::bindings::error::Error::Type;
 use dom::bindings::error::{Fallible, ErrorResult};
 use dom::bindings::global::GlobalRef;
@@ -13,7 +12,7 @@ use dom::bindings::js::{JS, MutHeap, Root};
 use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
 use dom::bluetoothdevice::BluetoothDevice;
 use dom::bluetoothremotegattservice::BluetoothRemoteGATTService;
-use dom::bluetoothuuid::BluetoothUUID;
+use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID};
 use ipc_channel::ipc::{self, IpcSender};
 use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg};
 use std::cell::Cell;
@@ -106,7 +105,7 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice
-    fn GetPrimaryService(&self, service: StringOrUnsignedLong) -> Fallible> {
+    fn GetPrimaryService(&self, service: BluetoothServiceUUID) -> Fallible> {
         let uuid: String = match BluetoothUUID::GetService(self.global().r(), service.clone()) {
             Ok(domstring) => domstring.to_string(),
             Err(error) => return Err(error),
@@ -138,7 +137,7 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices
     fn GetPrimaryServices(&self,
-                          service: Option)
+                          service: Option)
                           -> Fallible>> {
         let mut uuid: Option = None;
         if let Some(s)= service {
diff --git a/components/script/dom/bluetoothremotegattservice.rs b/components/script/dom/bluetoothremotegattservice.rs
index 77820521552..c8d46c29904 100644
--- a/components/script/dom/bluetoothremotegattservice.rs
+++ b/components/script/dom/bluetoothremotegattservice.rs
@@ -4,7 +4,6 @@
 
 use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding;
 use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
-use dom::bindings::codegen::UnionTypes::StringOrUnsignedLong;
 use dom::bindings::error::Error::Type;
 use dom::bindings::error::Fallible;
 use dom::bindings::global::GlobalRef;
@@ -13,7 +12,7 @@ use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
 use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties;
 use dom::bluetoothdevice::BluetoothDevice;
 use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic;
-use dom::bluetoothuuid::BluetoothUUID;
+use dom::bluetoothuuid::{BluetoothCharacteristicUUID, BluetoothUUID};
 use ipc_channel::ipc::{self, IpcSender};
 use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg};
 use util::str::DOMString;
@@ -86,7 +85,7 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic
     fn GetCharacteristic(&self,
-                         characteristic: StringOrUnsignedLong)
+                         characteristic: BluetoothCharacteristicUUID)
                          -> Fallible> {
         let uuid: String = match BluetoothUUID::GetCharacteristic(self.global().r(), characteristic.clone()) {
             Ok(domstring) => domstring.to_string(),
@@ -137,7 +136,7 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics
     fn GetCharacteristics(&self,
-                          characteristic: Option)
+                          characteristic: Option)
                           -> Fallible>> {
         let mut uuid: Option = None;
         if let Some(c)= characteristic {
diff --git a/components/script/dom/bluetoothuuid.rs b/components/script/dom/bluetoothuuid.rs
index e916c6ebded..d4ed2b5e6a7 100644
--- a/components/script/dom/bluetoothuuid.rs
+++ b/components/script/dom/bluetoothuuid.rs
@@ -11,6 +11,9 @@ use regex::Regex;
 use util::str::DOMString;
 
 pub type UUID = DOMString;
+pub type BluetoothServiceUUID = StringOrUnsignedLong;
+pub type BluetoothCharacteristicUUID = StringOrUnsignedLong;
+pub type BluetoothDescriptorUUID = StringOrUnsignedLong;
 
 // https://webbluetoothcg.github.io/web-bluetooth/#bluetoothuuid
  #[dom_struct]
@@ -274,7 +277,7 @@ impl BluetoothUUID {
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-getservice
-    pub fn GetService(globalref: GlobalRef, name: StringOrUnsignedLong) -> Fallible {
+    pub fn GetService(globalref: GlobalRef, name: BluetoothServiceUUID) -> Fallible {
       BluetoothUUID::resolve_uuid_name(globalref,
                                        name,
                                        BLUETOOTH_ASSIGNED_SERVICES,
@@ -282,7 +285,7 @@ impl BluetoothUUID {
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-getcharacteristic
-    pub fn GetCharacteristic(globalref: GlobalRef, name: StringOrUnsignedLong) -> Fallible {
+    pub fn GetCharacteristic(globalref: GlobalRef, name: BluetoothCharacteristicUUID) -> Fallible {
         BluetoothUUID::resolve_uuid_name(globalref,
                                          name,
                                          BLUETOOTH_ASSIGNED_CHARCTERISTICS,
@@ -290,7 +293,7 @@ impl BluetoothUUID {
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothuuid-getdescriptor
-    pub fn GetDescriptor(globalref: GlobalRef, name: StringOrUnsignedLong) -> Fallible {
+    pub fn GetDescriptor(globalref: GlobalRef, name: BluetoothDescriptorUUID) -> Fallible {
         BluetoothUUID::resolve_uuid_name(globalref,
                                          name,
                                          BLUETOOTH_ASSIGNED_DESCRIPTORS,
diff --git a/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl b/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl
index 294e00e1b85..2f721203ee1 100644
--- a/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl
+++ b/components/script/dom/webidls/BluetoothRemoteGATTCharacteristic.webidl
@@ -11,9 +11,9 @@ interface BluetoothRemoteGATTCharacteristic {
   readonly attribute BluetoothCharacteristicProperties properties;
   readonly attribute ByteString? value;
   [Throws]
-  BluetoothRemoteGATTDescriptor getDescriptor((DOMString or unsigned long) descriptor);
+  BluetoothRemoteGATTDescriptor getDescriptor(BluetoothDescriptorUUID descriptor);
   [Throws]
-  sequence getDescriptors(optional (DOMString or unsigned long) descriptor);
+  sequence getDescriptors(optional BluetoothDescriptorUUID descriptor);
   //Promise getDescriptor(BluetoothDescriptorUUID descriptor);
   //Promise>
   //getDescriptors(optional BluetoothDescriptorUUID descriptor);
diff --git a/components/script/dom/webidls/BluetoothRemoteGATTServer.webidl b/components/script/dom/webidls/BluetoothRemoteGATTServer.webidl
index 835a6444103..1d48a19a173 100644
--- a/components/script/dom/webidls/BluetoothRemoteGATTServer.webidl
+++ b/components/script/dom/webidls/BluetoothRemoteGATTServer.webidl
@@ -13,9 +13,9 @@ interface BluetoothRemoteGATTServer {
   [Throws]
   void disconnect();
   [Throws]
-  BluetoothRemoteGATTService getPrimaryService((DOMString or unsigned long) service);
+  BluetoothRemoteGATTService getPrimaryService(BluetoothServiceUUID service);
   [Throws]
-  sequence getPrimaryServices(optional (DOMString or unsigned long) service);
+  sequence getPrimaryServices(optional BluetoothServiceUUID service);
   //Promise getPrimaryService(BluetoothServiceUUID service);
   //Promise>getPrimaryServices(optional BluetoothServiceUUID service);
   //Promise connect();
diff --git a/components/script/dom/webidls/BluetoothRemoteGATTService.webidl b/components/script/dom/webidls/BluetoothRemoteGATTService.webidl
index e6673f69397..3a41865de1e 100644
--- a/components/script/dom/webidls/BluetoothRemoteGATTService.webidl
+++ b/components/script/dom/webidls/BluetoothRemoteGATTService.webidl
@@ -10,10 +10,10 @@ interface BluetoothRemoteGATTService {
     readonly attribute DOMString uuid;
     readonly attribute boolean isPrimary;
     [Throws]
-    BluetoothRemoteGATTCharacteristic getCharacteristic((DOMString or unsigned long) characteristic);
+    BluetoothRemoteGATTCharacteristic getCharacteristic(BluetoothCharacteristicUUID characteristic);
     [Throws]
     sequence getCharacteristics
-        (optional (DOMString or unsigned long) characteristic);
+        (optional BluetoothCharacteristicUUID characteristic);
     //PromisegetCharacteristic(BluetoothCharacteristicUUID characteristic);
     //Promise>
     //getCharacteristics(optional BluetoothCharacteristicUUID characteristic);

From ef296b86e8cd47ff40b088edc9859a01598017da Mon Sep 17 00:00:00 2001
From: zakorgy 
Date: Mon, 25 Apr 2016 14:29:47 +0200
Subject: [PATCH 11/15] Refactor scan filter

---
 components/net/bluetooth_thread.rs            | 43 ++++++++-
 components/net_traits/bluetooth_scanfilter.rs | 96 ++++++-------------
 components/script/dom/bluetooth.rs            | 78 +++++----------
 3 files changed, 91 insertions(+), 126 deletions(-)

diff --git a/components/net/bluetooth_thread.rs b/components/net/bluetooth_thread.rs
index 82fe4891ee9..e6068fa37a9 100644
--- a/components/net/bluetooth_thread.rs
+++ b/components/net/bluetooth_thread.rs
@@ -8,7 +8,7 @@ use device::bluetooth::BluetoothGATTCharacteristic;
 use device::bluetooth::BluetoothGATTDescriptor;
 use device::bluetooth::BluetoothGATTService;
 use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
-use net_traits::bluetooth_scanfilter::{RequestDeviceoptions, matches_filters};
+use net_traits::bluetooth_scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence, RequestDeviceoptions};
 use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg};
 use std::borrow::ToOwned;
 use std::collections::HashMap;
@@ -55,6 +55,47 @@ impl BluetoothThreadFactory for IpcSender {
     }
 }
 
+fn matches_filter(device: &BluetoothDevice, filter: &BluetoothScanfilter) -> bool {
+    if filter.is_empty_or_invalid() {
+        return false;
+    }
+
+    if !filter.get_name().is_empty() {
+        if device.get_name().ok() != Some(filter.get_name().to_string()) {
+            return false;
+        }
+    }
+
+    if !filter.get_name_prefix().is_empty() {
+        if let Ok(device_name) = device.get_name() {
+            if !device_name.starts_with(filter.get_name_prefix()) {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    if !filter.get_services().is_empty() {
+        if let Ok(device_uuids) = device.get_uuids() {
+            for service in filter.get_services() {
+                if device_uuids.iter().find(|x| x == &service).is_none() {
+                    return false;
+                }
+            }
+        }
+    }
+    return true;
+}
+
+fn matches_filters(device: &BluetoothDevice, filters: &BluetoothScanfilterSequence) -> bool {
+    if filters.has_empty_or_invalid_filter() {
+        return false;
+    }
+
+    return filters.iter().any(|f| matches_filter(device, f))
+}
+
 pub struct BluetoothManager {
     receiver: IpcReceiver,
     adapter: Option,
diff --git a/components/net_traits/bluetooth_scanfilter.rs b/components/net_traits/bluetooth_scanfilter.rs
index 58eb72f518e..b332c1a52b2 100644
--- a/components/net_traits/bluetooth_scanfilter.rs
+++ b/components/net_traits/bluetooth_scanfilter.rs
@@ -2,11 +2,11 @@
  * 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 device::bluetooth::BluetoothDevice;
+use std::slice::Iter;
 
 // A device name can never be longer than 29 bytes. An adv packet is at most
 // 31 bytes long. The length and identifier of the length field take 2 bytes.
-// That least 29 bytes for the name.
+// That leaves 29 bytes for the name.
 const MAX_NAME_LENGTH: usize = 29;
 
 #[derive(Deserialize, Serialize)]
@@ -16,10 +16,6 @@ impl ServiceUUIDSequence {
     pub fn new(vec: Vec) -> ServiceUUIDSequence {
         ServiceUUIDSequence(vec)
     }
-
-    fn is_empty(&self) -> bool {
-        self.0.is_empty()
-    }
 }
 
 #[derive(Deserialize, Serialize)]
@@ -30,14 +26,6 @@ pub struct BluetoothScanfilter {
 }
 
 impl BluetoothScanfilter {
-    fn is_empty_or_invalid_filter(&self) -> bool {
-        self.name.is_empty() &&
-        self.name_prefix.is_empty() &&
-        self.services.is_empty() &&
-        self.name.len() > MAX_NAME_LENGTH &&
-        self.name_prefix.len() > MAX_NAME_LENGTH
-    }
-
     pub fn new(name: String, name_prefix: String, services: Vec) -> BluetoothScanfilter {
         BluetoothScanfilter {
             name: name,
@@ -45,6 +33,24 @@ impl BluetoothScanfilter {
             services: ServiceUUIDSequence::new(services),
         }
     }
+
+    pub fn get_name(&self) -> &str {
+        &self.name
+    }
+
+    pub fn get_name_prefix(&self) -> &str {
+        &self.name_prefix
+    }
+
+    pub fn get_services(&self) -> &[String] {
+        &self.services.0
+    }
+
+    pub fn is_empty_or_invalid(&self) -> bool {
+        (self.name.is_empty() && self.name_prefix.is_empty() && self.get_services().is_empty()) ||
+        self.name.len() > MAX_NAME_LENGTH ||
+        self.name_prefix.len() > MAX_NAME_LENGTH
+    }
 }
 
 #[derive(Deserialize, Serialize)]
@@ -54,12 +60,14 @@ impl BluetoothScanfilterSequence {
     pub fn new(vec: Vec) -> BluetoothScanfilterSequence {
         BluetoothScanfilterSequence(vec)
     }
-}
 
-impl BluetoothScanfilterSequence {
-    fn has_empty_or_invalid_filter(&self) -> bool {
-        self.0.is_empty() &&
-        self.0.iter().all(|x| !(x.is_empty_or_invalid_filter()))
+    pub fn has_empty_or_invalid_filter(&self) -> bool {
+        self.0.is_empty() ||
+        self.0.iter().any(BluetoothScanfilter::is_empty_or_invalid)
+    }
+
+    pub fn iter(&self) -> Iter {
+        self.0.iter()
     }
 }
 
@@ -83,53 +91,3 @@ impl RequestDeviceoptions {
         &self.filters
     }
 }
-
-pub fn matches_filter(device: &BluetoothDevice, filter: &BluetoothScanfilter) -> bool {
-    if filter.is_empty_or_invalid_filter() {
-        return false;
-    }
-
-     if !filter.name.is_empty() {
-        if let Ok(device_name) = device.get_name() {
-            if !device_name.eq(&filter.name) {
-                return false;
-            }
-        } else {
-            return false;
-        }
-    }
-
-    if !filter.name_prefix.is_empty() {
-        if let Ok(device_name) = device.get_name() {
-            if !device_name.starts_with(&*filter.name_prefix) {
-                return false;
-            }
-        } else {
-            return false;
-        }
-    }
-
-    if !filter.services.is_empty() {
-        if let Ok(stringvec) = device.get_uuids() {
-            for service in &filter.services.0 {
-                if !stringvec.iter().any(|x| x == service) {
-                    return false;
-                }
-            }
-        }
-    }
-    return true;
-}
-
-pub fn matches_filters(device: &BluetoothDevice, filters: &BluetoothScanfilterSequence) -> bool {
-    if filters.has_empty_or_invalid_filter() {
-        return false;
-    }
-
-    for filter in &filters.0 {
-        if matches_filter(device, filter) {
-            return true;
-        }
-    }
-    return false;
-}
diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs
index d56528d845a..46602b4bbf3 100644
--- a/components/script/dom/bluetooth.rs
+++ b/components/script/dom/bluetooth.rs
@@ -21,14 +21,15 @@ use net_traits::bluetooth_scanfilter::{RequestDeviceoptions, ServiceUUIDSequence
 use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg};
 use util::str::DOMString;
 
-// A device name can never be longer than 29 bytes. An adv packet is at most
-// 31 bytes long. The length and identifier of the length field take 2 bytes.
 const FILTER_EMPTY_ERROR: &'static str = "'filters' member must be non - empty to find any devices.";
 const FILTER_ERROR: &'static str = "A filter must restrict the devices in some way.";
 const FILTER_NAME_TOO_LONG_ERROR: &'static str = "A 'name' or 'namePrefix' can't be longer then 29 bytes.";
 // 248 is the maximum number of UTF-8 code units in a Bluetooth Device Name.
 const MAX_DEVICE_NAME_LENGTH: usize = 248;
-// That least 29 bytes for the name.
+// A device name can never be longer than 29 bytes.
+// An advertising packet is at most 31 bytes long.
+// The length and identifier of the length field take 2 bytes.
+// That leaves 29 bytes for the name.
 const MAX_FILTER_NAME_LENGTH: usize = 29;
 const NAME_PREFIX_ERROR: &'static str = "'namePrefix', if present, must be non - empty.";
 const NAME_TOO_LONG_ERROR: &'static str = "A device name can't be longer than 248 bytes.";
@@ -60,45 +61,23 @@ impl Bluetooth {
     }
 }
 
-impl Clone for BluetoothScanFilter {
-    fn clone(&self) -> BluetoothScanFilter {
-        BluetoothScanFilter {
-            name: self.name.clone(),
-            namePrefix: self.namePrefix.clone(),
-            services: self.services.clone(),
-        }
-    }
-}
-
-impl Clone for RequestDeviceOptions {
-    fn clone(&self) -> RequestDeviceOptions {
-        RequestDeviceOptions {
-            filters: self.filters.clone(),
-            optionalServices: self.optionalServices.clone(),
-        }
-    }
-}
-
 fn canonicalize_filter(filter: &BluetoothScanFilter, global: GlobalRef) -> Fallible {
-    if !(filter.services.is_some() || filter.name.is_some() || filter.namePrefix.is_some()) {
+    if filter.services.is_none() && filter.name.is_none() && filter.namePrefix.is_none() {
         return Err(Type(FILTER_ERROR.to_owned()));
     }
 
-    let mut services_vec: Vec = vec!();
-    if let Some(services) = filter.services.clone() {
+    let mut services_vec = vec!();
+    if let Some(ref services) = filter.services {
         if services.is_empty() {
             return Err(Type(SERVICE_ERROR.to_owned()));
         }
         for service in services {
-            match BluetoothUUID::GetService(global, service) {
-                Ok(valid) => services_vec.push(valid.to_string()),
-                Err(err) => return Err(err),
-            }
+            services_vec.push(try!(BluetoothUUID::GetService(global, service.clone())).to_string());
         }
     }
 
     let mut name = String::new();
-    if let Some(filter_name) = filter.name.clone() {
+    if let Some(ref filter_name) = filter.name {
         //NOTE: DOMString::len() gives back the size in bytes
         if filter_name.len() > MAX_DEVICE_NAME_LENGTH {
             return Err(Type(NAME_TOO_LONG_ERROR.to_owned()));
@@ -110,8 +89,8 @@ fn canonicalize_filter(filter: &BluetoothScanFilter, global: GlobalRef) -> Falli
     }
 
     let mut name_prefix = String::new();
-    if let Some(filter_name_prefix) = filter.namePrefix.clone() {
-        if filter_name_prefix.len() == 0 {
+    if let Some(ref filter_name_prefix) = filter.namePrefix {
+        if filter_name_prefix.is_empty() {
             return Err(Type(NAME_PREFIX_ERROR.to_owned()));
         }
         if filter_name_prefix.len() > MAX_DEVICE_NAME_LENGTH {
@@ -135,19 +114,13 @@ fn convert_request_device_options(options: &RequestDeviceOptions,
 
     let mut filters = vec!();
     for filter in &options.filters {
-        match canonicalize_filter(&filter, global) {
-            Ok(canonicalized_filter) => filters.push(canonicalized_filter),
-            Err(err) => return Err(err),
-        }
+        filters.push(try!(canonicalize_filter(&filter, global)));
     }
 
     let mut optional_services = vec!();
-    if let Some(opt_services) = options.optionalServices.clone() {
+    if let Some(ref opt_services) = options.optionalServices {
         for opt_service in opt_services {
-            match BluetoothUUID::GetService(global, opt_service) {
-                Ok(valid_service) => optional_services.push(valid_service.to_string()),
-                Err(err) => return Err(err),
-            }
+            optional_services.push(try!(BluetoothUUID::GetService(global, opt_service.clone())).to_string());
         }
     }
 
@@ -160,8 +133,8 @@ impl BluetoothMethods for Bluetooth {
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice
     fn RequestDevice(&self, option: &RequestDeviceOptions) -> Fallible> {
         let (sender, receiver) = ipc::channel().unwrap();
-        match convert_request_device_options(option, self.global().r()) {
-            Ok(option) => {
+        match try!(convert_request_device_options(option, self.global().r())) {
+            option => {
                 self.get_bluetooth_thread().send(
                     BluetoothMethodMsg::RequestDevice(option, sender)).unwrap();
                 let device = receiver.recv().unwrap();
@@ -182,18 +155,12 @@ impl BluetoothMethods for Bluetooth {
                                                                      appearance,
                                                                      tx_power,
                                                                      rssi);
-                        let vendor_id_source = match vendor_id_source {
-                            Some(vid) => match vid.as_ref() {
-                                "bluetooth" => Some(VendorIDSource::Bluetooth),
-                                "usb" => Some(VendorIDSource::Usb),
-                                _ => Some(VendorIDSource::Unknown),
-                            },
-                            None => None,
-                        };
-                        let name = match name {
-                            Some(n) => Some(DOMString::from(n)),
-                            None => None,
-                        };
+                        let vendor_id_source = vendor_id_source.map(|vid| match vid.as_str() {
+                            "bluetooth" => VendorIDSource::Bluetooth,
+                            "usb" => VendorIDSource::Usb,
+                            _ => VendorIDSource::Unknown,
+                        });
+                        let name = name.map(DOMString::from);
                         Ok(BluetoothDevice::new(self.global().r(),
                                                 DOMString::from(id),
                                                 name,
@@ -212,7 +179,6 @@ impl BluetoothMethods for Bluetooth {
                     _ => unreachable!()
                 }
             },
-            Err(err) => Err(err),
         }
     }
 }

From ecf4c942da979729748bbf58b471b2d0d6a95ffe Mon Sep 17 00:00:00 2001
From: Attila Dusnoki 
Date: Mon, 25 Apr 2016 16:34:20 +0200
Subject: [PATCH 12/15] BluetoothThread refactor

---
 components/net/Cargo.toml          |   1 +
 components/net/bluetooth_thread.rs | 300 ++++++++++++++---------------
 components/net/lib.rs              |   2 +
 components/servo/Cargo.lock        |   6 +
 ports/cef/Cargo.lock               |   6 +
 ports/gonk/Cargo.lock              |   6 +
 6 files changed, 162 insertions(+), 159 deletions(-)

diff --git a/components/net/Cargo.toml b/components/net/Cargo.toml
index 5d139ea5191..14b9914d51f 100644
--- a/components/net/Cargo.toml
+++ b/components/net/Cargo.toml
@@ -18,6 +18,7 @@ msg = {path = "../msg"}
 ipc-channel = {git = "https://github.com/servo/ipc-channel"}
 webrender_traits = {git = "https://github.com/servo/webrender_traits"}
 device = {git = "https://github.com/servo/devices"}
+bitflags = "0.6.0"
 cookie = { version = "0.2.4", features = [ "serialize-rustc" ] }
 flate2 = "0.2.0"
 hyper = { version = "0.9", features = [ "serde-serialization" ] }
diff --git a/components/net/bluetooth_thread.rs b/components/net/bluetooth_thread.rs
index e6068fa37a9..d5bd8bf58c4 100644
--- a/components/net/bluetooth_thread.rs
+++ b/components/net/bluetooth_thread.rs
@@ -23,13 +23,27 @@ 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";
 
+bitflags! {
+    flags Flags: u32 {
+        const BROADCAST                   = 0b000000001,
+        const READ                        = 0b000000010,
+        const WRITE_WITHOUT_RESPONSE      = 0b000000100,
+        const WRITE                       = 0b000001000,
+        const NOTIFY                      = 0b000010000,
+        const INDICATE                    = 0b000100000,
+        const AUTHENTICATED_SIGNED_WRITES = 0b001000000,
+        const RELIABLE_WRITE              = 0b010000000,
+        const WRITABLE_AUXILIARIES        = 0b100000000,
+    }
+}
+
 macro_rules! send_error(
     ($sender:expr, $error:expr) => (
         return $sender.send(BluetoothObjectMsg::Error { error: String::from($error) }).unwrap();
     );
 );
 
-macro_rules! check_cache(
+macro_rules! return_if_cached(
     ($cache:expr, $key:expr) => (
         if $cache.contains_key($key) {
             return $cache.get($key);
@@ -44,10 +58,7 @@ pub trait BluetoothThreadFactory {
 impl BluetoothThreadFactory for IpcSender {
     fn new() -> IpcSender {
         let (sender, receiver) = ipc::channel().unwrap();
-        let adapter = match BluetoothAdapter::init() {
-            Ok(a) => Some(a),
-            Err(_) => None,
-        };
+        let adapter = BluetoothAdapter::init().ok();
         spawn_named("BluetoothThread".to_owned(), move || {
             BluetoothManager::new(receiver, adapter).start();
         });
@@ -124,8 +135,8 @@ impl BluetoothManager {
     }
 
     fn start(&mut self) {
-        loop {
-            match self.receiver.recv().unwrap() {
+        while let Ok(msg) = self.receiver.recv() {
+            match msg {
                 BluetoothMethodMsg::RequestDevice(options, sender) => {
                     self.request_device(options, sender)
                 },
@@ -168,9 +179,9 @@ impl BluetoothManager {
 
     // Adapter
 
-    fn get_adapter(&mut self) -> Option {
-        if self.adapter.is_none()
-        || self.adapter.clone().unwrap().get_address().is_err() {
+    fn get_or_create_adapter(&mut self) -> Option {
+        let adapter_valid = self.adapter.as_ref().map_or(false, |a| a.get_address().is_ok());
+        if !adapter_valid {
             self.adapter = BluetoothAdapter::init().ok();
         }
         self.adapter.clone()
@@ -178,27 +189,29 @@ impl BluetoothManager {
 
     // Device
 
-    fn get_devices(&mut self, adapter: &mut BluetoothAdapter) -> Vec {
+    fn get_and_cache_devices(&mut self, adapter: &mut BluetoothAdapter) -> Vec {
         let devices = adapter.get_devices().unwrap_or(vec!());
         for device in &devices {
             if let Ok(address) = device.get_address() {
                 self.cached_devices.insert(address, device.clone());
             }
         }
-        devices
+        self.cached_devices.iter().map(|(_, d)| d.clone()).collect()
     }
 
     fn get_device(&mut self, adapter: &mut BluetoothAdapter, device_id: &str) -> Option<&BluetoothDevice> {
-        check_cache!(self.cached_devices, device_id);
-        // Update cache
-        self.get_devices(adapter);
-        check_cache!(self.cached_devices, device_id);
+        return_if_cached!(self.cached_devices, device_id);
+        self.get_and_cache_devices(adapter);
+        return_if_cached!(self.cached_devices, device_id);
         None
     }
 
     // Service
 
-    fn get_gatt_services(&mut self, adapter: &mut BluetoothAdapter, device_id: &str) -> Vec {
+    fn get_and_cache_gatt_services(&mut self,
+                                   adapter: &mut BluetoothAdapter,
+                                   device_id: &str)
+                                   -> Vec {
         let services = match self.get_device(adapter, device_id) {
             Some(d) => d.get_gatt_services().unwrap_or(vec!()),
             None => vec!(),
@@ -211,14 +224,13 @@ impl BluetoothManager {
     }
 
     fn get_gatt_service(&mut self, adapter: &mut BluetoothAdapter, service_id: &str) -> Option<&BluetoothGATTService> {
-        check_cache!(self.cached_services, service_id);
-        let device_id = match self.service_to_device.get_mut(service_id) {
+        return_if_cached!(self.cached_services, service_id);
+        let device_id = match self.service_to_device.get(service_id) {
             Some(d) => d.clone(),
             None => return None,
         };
-        // Update cache
-        self.get_gatt_services(adapter, &device_id);
-        check_cache!(self.cached_services, service_id);
+        self.get_and_cache_gatt_services(adapter, &device_id);
+        return_if_cached!(self.cached_services, service_id);
         None
     }
 
@@ -227,24 +239,16 @@ impl BluetoothManager {
                                  device_id: &str,
                                  service_uuid: &str)
                                  -> Vec {
-        let mut services_vec: Vec = vec!();
-        let services = self.get_gatt_services(adapter, device_id);
-        for service in services {
-            if let Ok(uuid) = service.get_uuid() {
-                if uuid == service_uuid {
-                    services_vec.push(service.clone());
-                }
-            }
-        }
-        services_vec
+        let services = self.get_and_cache_gatt_services(adapter, device_id);
+        services.into_iter().filter(|s| s.get_uuid().ok() == Some(service_uuid.to_string())).collect()
     }
 
     // Characteristic
 
-    fn get_gatt_characteristics(&mut self,
-                                adapter: &mut BluetoothAdapter,
-                                service_id: &str)
-                                -> Vec {
+    fn get_and_cache_gatt_characteristics(&mut self,
+                                          adapter: &mut BluetoothAdapter,
+                                          service_id: &str)
+                                          -> Vec {
         let characteristics = match self.get_gatt_service(adapter, service_id) {
             Some(s) => s.get_gatt_characteristics().unwrap_or(vec!()),
             None => vec!(),
@@ -261,48 +265,41 @@ impl BluetoothManager {
                                adapter: &mut BluetoothAdapter,
                                characteristic_id: &str)
                                -> Option<&BluetoothGATTCharacteristic> {
-        check_cache!(self.cached_characteristics, characteristic_id);
-        let service_id = match self.characteristic_to_service.get_mut(characteristic_id) {
+        return_if_cached!(self.cached_characteristics, characteristic_id);
+        let service_id = match self.characteristic_to_service.get(characteristic_id) {
             Some(s) => s.clone(),
             None => return None,
         };
-        // Update cache
-        self.get_gatt_characteristics(adapter, &service_id);
-        check_cache!(self.cached_characteristics, characteristic_id);
+        self.get_and_cache_gatt_characteristics(adapter, &service_id);
+        return_if_cached!(self.cached_characteristics, characteristic_id);
         None
     }
 
     fn get_gatt_characteristics_by_uuid(&mut self,
-                                       adapter: &mut BluetoothAdapter,
-                                       service_id: &str,
-                                       characteristic_uuid: &str)
-                                       -> Vec {
-        let mut characteristics_vec: Vec = vec!();
-        let characteristics = self.get_gatt_characteristics(adapter, service_id);
-        for characteristic in characteristics {
-            if let Ok(uuid) = characteristic.get_uuid() {
-                if uuid == characteristic_uuid {
-                    characteristics_vec.push(characteristic.clone());
-                }
-            }
-        }
-        characteristics_vec
+                                        adapter: &mut BluetoothAdapter,
+                                        service_id: &str,
+                                        characteristic_uuid: &str)
+                                        -> Vec {
+        let characteristics = self.get_and_cache_gatt_characteristics(adapter, service_id);
+        characteristics.into_iter()
+                       .filter(|c| c.get_uuid().ok() == Some(characteristic_uuid.to_string()))
+                       .collect()
     }
 
-    fn get_characteristic_properties(&self, characteristic: &BluetoothGATTCharacteristic) -> [bool; 9] {
-        let mut props = [false; 9];
+    fn get_characteristic_properties(&self, characteristic: &BluetoothGATTCharacteristic) -> Flags {
+        let mut props: Flags = Flags::empty();
         let flags = characteristic.get_flags().unwrap_or(vec!());
         for flag in flags {
             match flag.as_ref() {
-                "broadcast" => props[0] = true,
-                "read" => props[1] = true,
-                "write_without_response" => props[2] = true,
-                "write" => props[3] = true,
-                "notify" => props[4] = true,
-                "indicate" => props[5] = true,
-                "authenticated_signed_writes" => props[6] = true,
-                "reliable_write" => props[7] = true,
-                "writable_auxiliaries" => props[8] = true,
+                "broadcast" => props.insert(BROADCAST),
+                "read" => props.insert(READ),
+                "write_without_response" => props.insert(WRITE_WITHOUT_RESPONSE),
+                "write" => props.insert(WRITE),
+                "notify" => props.insert(NOTIFY),
+                "indicate" => props.insert(INDICATE),
+                "authenticated_signed_writes" => props.insert(AUTHENTICATED_SIGNED_WRITES),
+                "reliable_write" => props.insert(RELIABLE_WRITE),
+                "writable_auxiliaries" => props.insert(WRITABLE_AUXILIARIES),
                 _ => (),
             }
         }
@@ -311,10 +308,10 @@ impl BluetoothManager {
 
     // Descriptor
 
-    fn get_gatt_descriptors(&mut self,
-                            adapter: &mut BluetoothAdapter,
-                            characteristic_id: &str)
-                            -> Vec {
+    fn get_and_cache_gatt_descriptors(&mut self,
+                                      adapter: &mut BluetoothAdapter,
+                                      characteristic_id: &str)
+                                      -> Vec {
         let descriptors = match self.get_gatt_characteristic(adapter, characteristic_id) {
             Some(c) => c.get_gatt_descriptors().unwrap_or(vec!()),
             None => vec!(),
@@ -331,14 +328,13 @@ impl BluetoothManager {
                            adapter: &mut BluetoothAdapter,
                            descriptor_id: &str)
                            -> Option<&BluetoothGATTDescriptor> {
-        check_cache!(self.cached_descriptors, descriptor_id);
-        let characteristic_id = match self.descriptor_to_characteristic.get_mut(descriptor_id) {
+        return_if_cached!(self.cached_descriptors, descriptor_id);
+        let characteristic_id = match self.descriptor_to_characteristic.get(descriptor_id) {
             Some(c) => c.clone(),
             None => return None,
         };
-        // Update cache
-        self.get_gatt_descriptors(adapter, &characteristic_id);
-        check_cache!(self.cached_descriptors, descriptor_id);
+        self.get_and_cache_gatt_descriptors(adapter, &characteristic_id);
+        return_if_cached!(self.cached_descriptors, descriptor_id);
         None
     }
 
@@ -347,26 +343,20 @@ impl BluetoothManager {
                                     characteristic_id: &str,
                                     descriptor_uuid: &str)
                                     -> Vec {
-        let mut descriptors_vec: Vec = vec!();
-        let descriptors = self.get_gatt_descriptors(adapter, characteristic_id);
-        for descriptor in descriptors {
-            if let Ok(uuid) = descriptor.get_uuid() {
-                if uuid == descriptor_uuid {
-                    descriptors_vec.push(descriptor.clone());
-                }
-            }
-        }
-        descriptors_vec
+        let descriptors = self.get_and_cache_gatt_descriptors(adapter, characteristic_id);
+        descriptors.into_iter()
+                   .filter(|d| d.get_uuid().ok() == Some(descriptor_uuid.to_string()))
+                   .collect()
     }
 
     // Methods
 
     fn request_device(&mut self, options: RequestDeviceoptions, sender: IpcSender) {
-        let mut adapter = match self.get_adapter() {
+        let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
             None => send_error!(sender, ADAPTER_ERROR),
         };
-        let devices = self.get_devices(&mut adapter);
+        let devices = self.get_and_cache_devices(&mut adapter);
         if devices.is_empty() {
             send_error!(sender, DEVICE_ERROR);
         }
@@ -400,8 +390,8 @@ impl BluetoothManager {
         send_error!(sender, DEVICE_MATCH_ERROR);
     }
 
-    pub fn gatt_server_connect(&mut self, device_id: String, sender: IpcSender) {
-        let mut adapter = match self.get_adapter() {
+    fn gatt_server_connect(&mut self, device_id: String, sender: IpcSender) {
+        let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
             None => send_error!(sender, ADAPTER_ERROR),
         };
@@ -411,7 +401,7 @@ impl BluetoothManager {
                 if d.is_connected().unwrap_or(false) {
                     true
                 } else {
-                    !d.connect().is_err()
+                    d.connect().is_ok()
                 }
             },
             None => send_error!(sender, DEVICE_ERROR),
@@ -423,8 +413,8 @@ impl BluetoothManager {
         sender.send(message).unwrap();
     }
 
-    pub fn gatt_server_disconnect(&mut self, device_id: String, sender: IpcSender) {
-        let mut adapter = match self.get_adapter() {
+    fn gatt_server_disconnect(&mut self, device_id: String, sender: IpcSender) {
+        let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
             None => send_error!(sender, ADAPTER_ERROR),
         };
@@ -432,7 +422,7 @@ impl BluetoothManager {
         let connected = match self.get_device(&mut adapter, &device_id) {
             Some(d) => {
                 if d.is_connected().unwrap_or(false) {
-                    d.disconnect().is_err()
+                    d.disconnect().is_ok()
                 } else {
                     false
                 }
@@ -446,8 +436,8 @@ impl BluetoothManager {
         sender.send(message).unwrap();
     }
 
-    pub fn get_primary_service(&mut self, device_id: String, uuid: String, sender: IpcSender) {
-        let mut adapter = match self.get_adapter() {
+    fn get_primary_service(&mut self, device_id: String, uuid: String, sender: IpcSender) {
+        let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
             None => send_error!(sender, ADAPTER_ERROR),
         };
@@ -470,22 +460,22 @@ impl BluetoothManager {
         send_error!(sender, PRIMARY_SERVICE_ERROR);
     }
 
-    pub fn get_primary_services(&mut self,
-                                device_id: String,
-                                uuid: Option,
-                                sender: IpcSender) {
-        let mut adapter = match self.get_adapter() {
+    fn get_primary_services(&mut self,
+                            device_id: String,
+                            uuid: Option,
+                            sender: IpcSender) {
+        let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
             None => send_error!(sender, ADAPTER_ERROR),
         };
-        let services: Vec = match uuid {
+        let services = match uuid {
             Some(id) => self.get_gatt_services_by_uuid(&mut adapter, &device_id, &id),
-            None => self.get_gatt_services(&mut adapter, &device_id),
+            None => self.get_and_cache_gatt_services(&mut adapter, &device_id),
         };
         if services.is_empty() {
             send_error!(sender, PRIMARY_SERVICE_ERROR);
         }
-        let mut services_vec: Vec = vec!();
+        let mut services_vec = vec!();
         for service in services {
             if service.is_primary().unwrap_or(false) {
                 if let Ok(uuid) = service.get_uuid() {
@@ -504,8 +494,8 @@ impl BluetoothManager {
         sender.send(message).unwrap();
     }
 
-    pub fn get_characteristic(&mut self, service_id: String, uuid: String, sender: IpcSender) {
-        let mut adapter = match self.get_adapter() {
+    fn get_characteristic(&mut self, service_id: String, uuid: String, sender: IpcSender) {
+        let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
             None => send_error!(sender, ADAPTER_ERROR),
         };
@@ -519,15 +509,15 @@ impl BluetoothManager {
                 let message = BluetoothObjectMsg::BluetoothCharacteristic {
                     uuid: uuid,
                     instance_id: characteristic.get_object_path(),
-                    broadcast: properties[0],
-                    read: properties[1],
-                    write_without_response: properties[2],
-                    write: properties[3],
-                    notify: properties[4],
-                    indicate: properties[5],
-                    authenticated_signed_writes: properties[6],
-                    reliable_write: properties[7],
-                    writable_auxiliaries: properties[8],
+                    broadcast: properties.contains(BROADCAST),
+                    read: properties.contains(READ),
+                    write_without_response: properties.contains(WRITE_WITHOUT_RESPONSE),
+                    write: properties.contains(WRITE),
+                    notify: properties.contains(NOTIFY),
+                    indicate: properties.contains(INDICATE),
+                    authenticated_signed_writes: properties.contains(AUTHENTICATED_SIGNED_WRITES),
+                    reliable_write: properties.contains(RELIABLE_WRITE),
+                    writable_auxiliaries: properties.contains(WRITABLE_AUXILIARIES),
                 };
                 return sender.send(message).unwrap();
             }
@@ -535,37 +525,37 @@ impl BluetoothManager {
         send_error!(sender, CHARACTERISTIC_ERROR);
     }
 
-    pub fn get_characteristics(&mut self,
-                               service_id: String,
-                               uuid: Option,
-                               sender: IpcSender) {
-        let mut adapter = match self.get_adapter() {
+    fn get_characteristics(&mut self,
+                           service_id: String,
+                           uuid: Option,
+                           sender: IpcSender) {
+        let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
             None => send_error!(sender, ADAPTER_ERROR),
         };
         let characteristics = match uuid {
             Some(id) => self.get_gatt_characteristics_by_uuid(&mut adapter, &service_id, &id),
-            None => self.get_gatt_characteristics(&mut adapter, &service_id),
+            None => self.get_and_cache_gatt_characteristics(&mut adapter, &service_id),
         };
         if characteristics.is_empty() {
             send_error!(sender, CHARACTERISTIC_ERROR);
         }
-        let mut characteristics_vec: Vec = vec!();
+        let mut characteristics_vec = vec!();
         for characteristic in characteristics {
             if let Ok(uuid) = characteristic.get_uuid() {
                 let properties = self.get_characteristic_properties(&characteristic);
                 characteristics_vec.push(BluetoothObjectMsg::BluetoothCharacteristic {
                     uuid: uuid,
                     instance_id: characteristic.get_object_path(),
-                    broadcast: properties[0],
-                    read: properties[1],
-                    write_without_response: properties[2],
-                    write: properties[3],
-                    notify: properties[4],
-                    indicate: properties[5],
-                    authenticated_signed_writes: properties[6],
-                    reliable_write: properties[7],
-                    writable_auxiliaries: properties[8],
+                    broadcast: properties.contains(BROADCAST),
+                    read: properties.contains(READ),
+                    write_without_response: properties.contains(WRITE_WITHOUT_RESPONSE),
+                    write: properties.contains(WRITE),
+                    notify: properties.contains(NOTIFY),
+                    indicate: properties.contains(INDICATE),
+                    authenticated_signed_writes: properties.contains(AUTHENTICATED_SIGNED_WRITES),
+                    reliable_write: properties.contains(RELIABLE_WRITE),
+                    writable_auxiliaries: properties.contains(WRITABLE_AUXILIARIES),
                 });
             }
         }
@@ -576,8 +566,8 @@ impl BluetoothManager {
         sender.send(message).unwrap();
     }
 
-    pub fn get_descriptor(&mut self, characteristic_id: String, uuid: String, sender: IpcSender) {
-        let mut adapter = match self.get_adapter() {
+    fn get_descriptor(&mut self, characteristic_id: String, uuid: String, sender: IpcSender) {
+        let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
             None => send_error!(sender, ADAPTER_ERROR),
         };
@@ -597,22 +587,22 @@ impl BluetoothManager {
         send_error!(sender, DESCRIPTOR_ERROR);
     }
 
-    pub fn get_descriptors(&mut self,
-                           characteristic_id: String,
-                           uuid: Option,
-                           sender: IpcSender) {
-        let mut adapter = match self.get_adapter() {
+    fn get_descriptors(&mut self,
+                       characteristic_id: String,
+                       uuid: Option,
+                       sender: IpcSender) {
+        let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
             None => send_error!(sender, ADAPTER_ERROR),
         };
         let descriptors = match uuid {
             Some(id) => self.get_gatt_descriptors_by_uuid(&mut adapter, &characteristic_id, &id),
-            None => self.get_gatt_descriptors(&mut adapter, &characteristic_id),
+            None => self.get_and_cache_gatt_descriptors(&mut adapter, &characteristic_id),
         };
         if descriptors.is_empty() {
             send_error!(sender, DESCRIPTOR_ERROR);
         }
-        let mut descriptors_vec: Vec = vec!();
+        let mut descriptors_vec = vec!();
         for descriptor in descriptors {
             if let Ok(uuid) = descriptor.get_uuid() {
                 descriptors_vec.push(BluetoothObjectMsg::BluetoothDescriptor {
@@ -628,20 +618,16 @@ impl BluetoothManager {
         sender.send(message).unwrap();
     }
 
-    pub fn read_value(&mut self, id: String, sender: IpcSender) {
-        let mut adapter = match self.get_adapter() {
+    fn read_value(&mut self, id: String, sender: IpcSender) {
+        let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
             None => send_error!(sender, ADAPTER_ERROR),
         };
-        let mut value = match self.get_gatt_characteristic(&mut adapter, &id) {
-            Some(c) => Some(c.read_value().unwrap_or(vec!())),
-            None => None,
-        };
+        let mut value = self.get_gatt_characteristic(&mut adapter, &id)
+                            .map(|c| c.read_value().unwrap_or(vec![]));
         if value.is_none() {
-            value = match self.get_gatt_descriptor(&mut adapter, &id) {
-                Some(d) => Some(d.read_value().unwrap_or(vec!())),
-                None => None,
-            };
+            value = self.get_gatt_descriptor(&mut adapter, &id)
+                        .map(|d| d.read_value().unwrap_or(vec![]));
         }
 
         let message = match value {
@@ -652,20 +638,16 @@ impl BluetoothManager {
         sender.send(message).unwrap();
     }
 
-    pub fn write_value(&mut self, id: String, value: Vec, sender: IpcSender) {
-        let mut adapter = match self.get_adapter() {
+    fn write_value(&mut self, id: String, value: Vec, sender: IpcSender) {
+        let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
             None => send_error!(sender, ADAPTER_ERROR),
         };
-        let mut result = match self.get_gatt_characteristic(&mut adapter, &id) {
-            Some(c) => Some(c.write_value(value.clone())),
-            None => None,
-        };
+        let mut result = self.get_gatt_characteristic(&mut adapter, &id)
+                             .map(|c| c.write_value(value.clone()));
         if result.is_none() {
-            result = match self.get_gatt_descriptor(&mut adapter, &id) {
-                Some(d) => Some(d.write_value(value.clone())),
-                None => None,
-            };
+            result = self.get_gatt_descriptor(&mut adapter, &id)
+                         .map(|d| d.write_value(value.clone()));
         }
 
         let message = match result {
diff --git a/components/net/lib.rs b/components/net/lib.rs
index 0f6c508fc0a..27b9d8f4dae 100644
--- a/components/net/lib.rs
+++ b/components/net/lib.rs
@@ -11,6 +11,8 @@
 
 #![deny(unsafe_code)]
 
+#[macro_use]
+extern crate bitflags;
 extern crate brotli;
 extern crate cookie as cookie_rs;
 extern crate device;
diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock
index 97bb0b56d8a..5943b8626a9 100644
--- a/components/servo/Cargo.lock
+++ b/components/servo/Cargo.lock
@@ -162,6 +162,11 @@ name = "bitflags"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "bitflags"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "block"
 version = "0.1.5"
@@ -1331,6 +1336,7 @@ dependencies = [
 name = "net"
 version = "0.0.1"
 dependencies = [
+ "bitflags 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "brotli 0.3.20 (git+https://github.com/ende76/brotli-rs)",
  "cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "device 0.0.1 (git+https://github.com/dati91/devices?branch=device-api)",
diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock
index 0c52ffcddee..7392afbf524 100644
--- a/ports/cef/Cargo.lock
+++ b/ports/cef/Cargo.lock
@@ -148,6 +148,11 @@ name = "bitflags"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "bitflags"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "block"
 version = "0.1.5"
@@ -1219,6 +1224,7 @@ dependencies = [
 name = "net"
 version = "0.0.1"
 dependencies = [
+ "bitflags 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "brotli 0.3.20 (git+https://github.com/ende76/brotli-rs)",
  "cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "devtools_traits 0.0.1",
diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock
index c535617e7ee..9140388c5ac 100644
--- a/ports/gonk/Cargo.lock
+++ b/ports/gonk/Cargo.lock
@@ -141,6 +141,11 @@ name = "bitflags"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "bitflags"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "block"
 version = "0.1.5"
@@ -1202,6 +1207,7 @@ dependencies = [
 name = "net"
 version = "0.0.1"
 dependencies = [
+ "bitflags 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "brotli 0.3.20 (git+https://github.com/ende76/brotli-rs)",
  "cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "devtools_traits 0.0.1",

From c8672ed0afafe36632f9c8ddd44b0b540fdc2a9f Mon Sep 17 00:00:00 2001
From: fokinv 
Date: Mon, 25 Apr 2016 13:54:06 +0200
Subject: [PATCH 13/15] Refactor IPC-message sending

---
 components/net/bluetooth_thread.rs            | 262 +++++++++---------
 components/net_traits/bluetooth_thread.rs     | 135 +++++----
 components/script/dom/bluetooth.rs            |  73 ++---
 .../dom/bluetoothremotegattcharacteristic.rs  | 102 +++----
 .../dom/bluetoothremotegattdescriptor.rs      |  43 ++-
 .../script/dom/bluetoothremotegattserver.rs   |  83 ++----
 .../script/dom/bluetoothremotegattservice.rs  | 121 +++-----
 7 files changed, 326 insertions(+), 493 deletions(-)

diff --git a/components/net/bluetooth_thread.rs b/components/net/bluetooth_thread.rs
index d5bd8bf58c4..14bb72f2bcf 100644
--- a/components/net/bluetooth_thread.rs
+++ b/components/net/bluetooth_thread.rs
@@ -9,7 +9,10 @@ use device::bluetooth::BluetoothGATTDescriptor;
 use device::bluetooth::BluetoothGATTService;
 use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
 use net_traits::bluetooth_scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence, RequestDeviceoptions};
-use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg};
+use net_traits::bluetooth_thread::{BluetoothCharacteristicMsg, BluetoothCharacteristicsMsg};
+use net_traits::bluetooth_thread::{BluetoothDescriptorMsg, BluetoothDescriptorsMsg};
+use net_traits::bluetooth_thread::{BluetoothDeviceMsg, BluetoothMethodMsg};
+use net_traits::bluetooth_thread::{BluetoothResult, BluetoothServiceMsg, BluetoothServicesMsg};
 use std::borrow::ToOwned;
 use std::collections::HashMap;
 use std::string::String;
@@ -37,12 +40,6 @@ bitflags! {
     }
 }
 
-macro_rules! send_error(
-    ($sender:expr, $error:expr) => (
-        return $sender.send(BluetoothObjectMsg::Error { error: String::from($error) }).unwrap();
-    );
-);
-
 macro_rules! return_if_cached(
     ($cache:expr, $key:expr) => (
         if $cache.contains_key($key) {
@@ -351,14 +348,16 @@ impl BluetoothManager {
 
     // Methods
 
-    fn request_device(&mut self, options: RequestDeviceoptions, sender: IpcSender) {
+    fn request_device(&mut self,
+                      options: RequestDeviceoptions,
+                      sender: IpcSender>) {
         let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
-            None => send_error!(sender, ADAPTER_ERROR),
+            None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
         };
         let devices = self.get_and_cache_devices(&mut adapter);
         if devices.is_empty() {
-            send_error!(sender, DEVICE_ERROR);
+            return drop(sender.send(Err(String::from(DEVICE_ERROR))));
         }
 
         let matched_devices: Vec = devices.into_iter()
@@ -366,34 +365,28 @@ impl BluetoothManager {
                                                            .collect();
         for device in matched_devices {
             if let Ok(address) = device.get_address() {
-                let message = BluetoothObjectMsg::BluetoothDevice {
-                    id: address,
-                    name: device.get_name().ok(),
-                    device_class: device.get_class().ok(),
-                    vendor_id_source: device.get_vendor_id_source().ok(),
-                    vendor_id: device.get_vendor_id().ok(),
-                    product_id: device.get_product_id().ok(),
-                    product_version: device.get_device_id().ok(),
-                    appearance: device.get_appearance().ok(),
-                    tx_power: match device.get_tx_power() {
-                        Ok(p) => Some(p as i8),
-                        Err(_) => None,
-                    },
-                    rssi: match device.get_rssi() {
-                        Ok(p) => Some(p as i8),
-                        Err(_) => None,
-                    },
-                };
-                return sender.send(message).unwrap();
+                let message = Ok(BluetoothDeviceMsg {
+                                     id: address,
+                                     name: device.get_name().ok(),
+                                     device_class: device.get_class().ok(),
+                                     vendor_id_source: device.get_vendor_id_source().ok(),
+                                     vendor_id: device.get_vendor_id().ok(),
+                                     product_id: device.get_product_id().ok(),
+                                     product_version: device.get_device_id().ok(),
+                                     appearance: device.get_appearance().ok(),
+                                     tx_power: device.get_tx_power().ok().map(|p| p as i8),
+                                     rssi: device.get_rssi().ok().map(|p| p as i8),
+                                 });
+                return drop(sender.send(message));
             }
         }
-        send_error!(sender, DEVICE_MATCH_ERROR);
+        return drop(sender.send(Err(String::from(DEVICE_MATCH_ERROR))));
     }
 
-    fn gatt_server_connect(&mut self, device_id: String, sender: IpcSender) {
+    fn gatt_server_connect(&mut self, device_id: String, sender: IpcSender>) {
         let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
-            None => send_error!(sender, ADAPTER_ERROR),
+            None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
         };
 
         let connected = match self.get_device(&mut adapter, &device_id) {
@@ -404,19 +397,16 @@ impl BluetoothManager {
                     d.connect().is_ok()
                 }
             },
-            None => send_error!(sender, DEVICE_ERROR),
+            None => return drop(sender.send(Err(String::from(DEVICE_ERROR)))),
         };
 
-        let message = BluetoothObjectMsg::BluetoothServer {
-            connected: connected
-        };
-        sender.send(message).unwrap();
+        let _ = sender.send(Ok(connected));
     }
 
-    fn gatt_server_disconnect(&mut self, device_id: String, sender: IpcSender) {
+    fn gatt_server_disconnect(&mut self, device_id: String, sender: IpcSender>) {
         let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
-            None => send_error!(sender, ADAPTER_ERROR),
+            None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
         };
 
         let connected = match self.get_device(&mut adapter, &device_id) {
@@ -427,201 +417,205 @@ impl BluetoothManager {
                     false
                 }
             },
-            None => send_error!(sender, DEVICE_ERROR),
+            None => return drop(sender.send(Err(String::from(DEVICE_ERROR)))),
         };
 
-        let message = BluetoothObjectMsg::BluetoothServer {
-            connected: connected
-        };
-        sender.send(message).unwrap();
+        let _ = sender.send(Ok(connected));
     }
 
-    fn get_primary_service(&mut self, device_id: String, uuid: String, sender: IpcSender) {
+    fn get_primary_service(&mut self,
+                           device_id: String,
+                           uuid: String,
+                           sender: IpcSender>) {
         let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
-            None => send_error!(sender, ADAPTER_ERROR),
+            None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
         };
         let services = self.get_gatt_services_by_uuid(&mut adapter, &device_id, &uuid);
         if services.is_empty() {
-            send_error!(sender, PRIMARY_SERVICE_ERROR);
+            return drop(sender.send(Err(String::from(PRIMARY_SERVICE_ERROR))));
         }
         for service in services {
             if service.is_primary().unwrap_or(false) {
                 if let Ok(uuid) = service.get_uuid() {
-                    let message = BluetoothObjectMsg::BluetoothService {
-                        uuid: uuid,
-                        is_primary: true,
-                        instance_id: service.get_object_path(),
-                    };
-                    return sender.send(message).unwrap();
+                    return drop(sender.send(Ok(BluetoothServiceMsg {
+                                                   uuid: uuid,
+                                                   is_primary: true,
+                                                   instance_id: service.get_object_path(),
+                                               })));
                 }
             }
         }
-        send_error!(sender, PRIMARY_SERVICE_ERROR);
+        return drop(sender.send(Err(String::from(PRIMARY_SERVICE_ERROR))));
     }
 
     fn get_primary_services(&mut self,
                             device_id: String,
                             uuid: Option,
-                            sender: IpcSender) {
+                            sender: IpcSender>) {
         let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
-            None => send_error!(sender, ADAPTER_ERROR),
+            None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
         };
         let services = match uuid {
             Some(id) => self.get_gatt_services_by_uuid(&mut adapter, &device_id, &id),
             None => self.get_and_cache_gatt_services(&mut adapter, &device_id),
         };
         if services.is_empty() {
-            send_error!(sender, PRIMARY_SERVICE_ERROR);
+            return drop(sender.send(Err(String::from(PRIMARY_SERVICE_ERROR))));
         }
         let mut services_vec = vec!();
         for service in services {
             if service.is_primary().unwrap_or(false) {
                 if let Ok(uuid) = service.get_uuid() {
-                    services_vec.push(BluetoothObjectMsg::BluetoothService {
-                        uuid: uuid,
-                        is_primary: true,
-                        instance_id: service.get_object_path(),
-                    });
+                    services_vec.push(BluetoothServiceMsg {
+                                          uuid: uuid,
+                                          is_primary: true,
+                                          instance_id: service.get_object_path(),
+                                      });
                 }
             }
         }
         if services_vec.is_empty() {
-            send_error!(sender, PRIMARY_SERVICE_ERROR);
+            return drop(sender.send(Err(String::from(PRIMARY_SERVICE_ERROR))));
         }
-        let message = BluetoothObjectMsg::BluetoothServices { services_vec: services_vec };
-        sender.send(message).unwrap();
+
+        let _ = sender.send(Ok(services_vec));
     }
 
-    fn get_characteristic(&mut self, service_id: String, uuid: String, sender: IpcSender) {
+    fn get_characteristic(&mut self,
+                          service_id: String,
+                          uuid: String,
+                          sender: IpcSender>) {
         let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
-            None => send_error!(sender, ADAPTER_ERROR),
+            None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
         };
         let characteristics = self.get_gatt_characteristics_by_uuid(&mut adapter, &service_id, &uuid);
         if characteristics.is_empty() {
-            send_error!(sender, CHARACTERISTIC_ERROR);
+            return drop(sender.send(Err(String::from(CHARACTERISTIC_ERROR))));
         }
         for characteristic in characteristics {
             if let Ok(uuid) = characteristic.get_uuid() {
                 let properties = self.get_characteristic_properties(&characteristic);
-                let message = BluetoothObjectMsg::BluetoothCharacteristic {
-                    uuid: uuid,
-                    instance_id: characteristic.get_object_path(),
-                    broadcast: properties.contains(BROADCAST),
-                    read: properties.contains(READ),
-                    write_without_response: properties.contains(WRITE_WITHOUT_RESPONSE),
-                    write: properties.contains(WRITE),
-                    notify: properties.contains(NOTIFY),
-                    indicate: properties.contains(INDICATE),
-                    authenticated_signed_writes: properties.contains(AUTHENTICATED_SIGNED_WRITES),
-                    reliable_write: properties.contains(RELIABLE_WRITE),
-                    writable_auxiliaries: properties.contains(WRITABLE_AUXILIARIES),
-                };
-                return sender.send(message).unwrap();
+                let message = Ok(BluetoothCharacteristicMsg {
+                                     uuid: uuid,
+                                     instance_id: characteristic.get_object_path(),
+                                     broadcast: properties.contains(BROADCAST),
+                                     read: properties.contains(READ),
+                                     write_without_response: properties.contains(WRITE_WITHOUT_RESPONSE),
+                                     write: properties.contains(WRITE),
+                                     notify: properties.contains(NOTIFY),
+                                     indicate: properties.contains(INDICATE),
+                                     authenticated_signed_writes: properties.contains(AUTHENTICATED_SIGNED_WRITES),
+                                     reliable_write: properties.contains(RELIABLE_WRITE),
+                                     writable_auxiliaries: properties.contains(WRITABLE_AUXILIARIES),
+                                 });
+                return drop(sender.send(message));
             }
         }
-        send_error!(sender, CHARACTERISTIC_ERROR);
+        return drop(sender.send(Err(String::from(CHARACTERISTIC_ERROR))));
     }
 
     fn get_characteristics(&mut self,
                            service_id: String,
                            uuid: Option,
-                           sender: IpcSender) {
+                           sender: IpcSender>) {
         let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
-            None => send_error!(sender, ADAPTER_ERROR),
+            None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
         };
         let characteristics = match uuid {
             Some(id) => self.get_gatt_characteristics_by_uuid(&mut adapter, &service_id, &id),
             None => self.get_and_cache_gatt_characteristics(&mut adapter, &service_id),
         };
         if characteristics.is_empty() {
-            send_error!(sender, CHARACTERISTIC_ERROR);
+            return drop(sender.send(Err(String::from(CHARACTERISTIC_ERROR))));
         }
         let mut characteristics_vec = vec!();
         for characteristic in characteristics {
             if let Ok(uuid) = characteristic.get_uuid() {
                 let properties = self.get_characteristic_properties(&characteristic);
-                characteristics_vec.push(BluetoothObjectMsg::BluetoothCharacteristic {
-                    uuid: uuid,
-                    instance_id: characteristic.get_object_path(),
-                    broadcast: properties.contains(BROADCAST),
-                    read: properties.contains(READ),
-                    write_without_response: properties.contains(WRITE_WITHOUT_RESPONSE),
-                    write: properties.contains(WRITE),
-                    notify: properties.contains(NOTIFY),
-                    indicate: properties.contains(INDICATE),
-                    authenticated_signed_writes: properties.contains(AUTHENTICATED_SIGNED_WRITES),
-                    reliable_write: properties.contains(RELIABLE_WRITE),
-                    writable_auxiliaries: properties.contains(WRITABLE_AUXILIARIES),
-                });
+                characteristics_vec.push(
+                                BluetoothCharacteristicMsg {
+                                    uuid: uuid,
+                                    instance_id: characteristic.get_object_path(),
+                                    broadcast: properties.contains(BROADCAST),
+                                    read: properties.contains(READ),
+                                    write_without_response: properties.contains(WRITE_WITHOUT_RESPONSE),
+                                    write: properties.contains(WRITE),
+                                    notify: properties.contains(NOTIFY),
+                                    indicate: properties.contains(INDICATE),
+                                    authenticated_signed_writes: properties.contains(AUTHENTICATED_SIGNED_WRITES),
+                                    reliable_write: properties.contains(RELIABLE_WRITE),
+                                    writable_auxiliaries: properties.contains(WRITABLE_AUXILIARIES),
+                                });
             }
         }
         if characteristics_vec.is_empty() {
-            send_error!(sender, CHARACTERISTIC_ERROR);
+            return drop(sender.send(Err(String::from(CHARACTERISTIC_ERROR))));
         }
-        let message = BluetoothObjectMsg::BluetoothCharacteristics { characteristics_vec: characteristics_vec };
-        sender.send(message).unwrap();
+
+        let _ = sender.send(Ok(characteristics_vec));
     }
 
-    fn get_descriptor(&mut self, characteristic_id: String, uuid: String, sender: IpcSender) {
+    fn get_descriptor(&mut self,
+                      characteristic_id: String,
+                      uuid: String,
+                      sender: IpcSender>) {
         let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
-            None => send_error!(sender, ADAPTER_ERROR),
+            None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
         };
         let descriptors = self.get_gatt_descriptors_by_uuid(&mut adapter, &characteristic_id, &uuid);
         if descriptors.is_empty() {
-            send_error!(sender, DESCRIPTOR_ERROR);
+            return drop(sender.send(Err(String::from(DESCRIPTOR_ERROR))));
         }
         for descriptor in descriptors {
             if let Ok(uuid) = descriptor.get_uuid() {
-                let message = BluetoothObjectMsg::BluetoothDescriptor {
-                    uuid: uuid,
-                    instance_id: descriptor.get_object_path(),
-                };
-                return sender.send(message).unwrap();
+                return drop(sender.send(Ok(BluetoothDescriptorMsg {
+                                               uuid: uuid,
+                                               instance_id: descriptor.get_object_path(),
+                                           })));
             }
         }
-        send_error!(sender, DESCRIPTOR_ERROR);
+        return drop(sender.send(Err(String::from(DESCRIPTOR_ERROR))));
     }
 
     fn get_descriptors(&mut self,
                        characteristic_id: String,
                        uuid: Option,
-                       sender: IpcSender) {
+                       sender: IpcSender>) {
         let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
-            None => send_error!(sender, ADAPTER_ERROR),
+            None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
         };
         let descriptors = match uuid {
             Some(id) => self.get_gatt_descriptors_by_uuid(&mut adapter, &characteristic_id, &id),
             None => self.get_and_cache_gatt_descriptors(&mut adapter, &characteristic_id),
         };
         if descriptors.is_empty() {
-            send_error!(sender, DESCRIPTOR_ERROR);
+            return drop(sender.send(Err(String::from(DESCRIPTOR_ERROR))));
         }
         let mut descriptors_vec = vec!();
         for descriptor in descriptors {
             if let Ok(uuid) = descriptor.get_uuid() {
-                descriptors_vec.push(BluetoothObjectMsg::BluetoothDescriptor {
-                    uuid: uuid,
-                    instance_id: descriptor.get_object_path(),
-                });
+                descriptors_vec.push(BluetoothDescriptorMsg {
+                                         uuid: uuid,
+                                         instance_id: descriptor.get_object_path(),
+                                     });
             }
         }
         if descriptors_vec.is_empty() {
-            send_error!(sender, DESCRIPTOR_ERROR);
+            return drop(sender.send(Err(String::from(DESCRIPTOR_ERROR))));
         }
-        let message = BluetoothObjectMsg::BluetoothDescriptors { descriptors_vec: descriptors_vec };
-        sender.send(message).unwrap();
+        let _ = sender.send(Ok(descriptors_vec));
     }
 
-    fn read_value(&mut self, id: String, sender: IpcSender) {
+    fn read_value(&mut self, id: String, sender: IpcSender>>) {
         let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
-            None => send_error!(sender, ADAPTER_ERROR),
+            None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
         };
         let mut value = self.get_gatt_characteristic(&mut adapter, &id)
                             .map(|c| c.read_value().unwrap_or(vec![]));
@@ -629,19 +623,13 @@ impl BluetoothManager {
             value = self.get_gatt_descriptor(&mut adapter, &id)
                         .map(|d| d.read_value().unwrap_or(vec![]));
         }
-
-        let message = match value {
-            Some(v) => BluetoothObjectMsg::BluetoothReadValue { value: v },
-            None => send_error!(sender, VALUE_ERROR),
-        };
-
-        sender.send(message).unwrap();
+        let _ = sender.send(value.ok_or(String::from(VALUE_ERROR)));
     }
 
-    fn write_value(&mut self, id: String, value: Vec, sender: IpcSender) {
+    fn write_value(&mut self, id: String, value: Vec, sender: IpcSender>) {
         let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
-            None => send_error!(sender, ADAPTER_ERROR),
+            None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
         };
         let mut result = self.get_gatt_characteristic(&mut adapter, &id)
                              .map(|c| c.write_value(value.clone()));
@@ -649,15 +637,13 @@ impl BluetoothManager {
             result = self.get_gatt_descriptor(&mut adapter, &id)
                          .map(|d| d.write_value(value.clone()));
         }
-
         let message = match result {
             Some(v) => match v {
-                Ok(_) => BluetoothObjectMsg::BluetoothWriteValue,
-                Err(e) => send_error!(sender, e.to_string()),
+                Ok(_) => Ok(true),
+                Err(e) => return drop(sender.send(Err(e.to_string()))),
             },
-            None => send_error!(sender, VALUE_ERROR),
+            None => return drop(sender.send(Err(String::from(VALUE_ERROR)))),
         };
-
-        sender.send(message).unwrap();
+        let _ = sender.send(message);
     }
 }
diff --git a/components/net_traits/bluetooth_thread.rs b/components/net_traits/bluetooth_thread.rs
index 6437027e144..34019528a1e 100644
--- a/components/net_traits/bluetooth_thread.rs
+++ b/components/net_traits/bluetooth_thread.rs
@@ -5,78 +5,71 @@ use bluetooth_scanfilter::RequestDeviceoptions;
 use ipc_channel::ipc::IpcSender;
 
 #[derive(Deserialize, Serialize)]
-pub enum BluetoothMethodMsg {
-    RequestDevice(RequestDeviceoptions, IpcSender),
-    GATTServerConnect(String, IpcSender),
-    GATTServerDisconnect(String, IpcSender),
-    GetPrimaryService(String, String, IpcSender),
-    GetPrimaryServices(String, Option, IpcSender),
-    GetCharacteristic(String, String, IpcSender),
-    GetCharacteristics(String, Option, IpcSender),
-    GetDescriptor(String, String, IpcSender),
-    GetDescriptors(String, Option, IpcSender),
-    ReadValue(String, IpcSender),
-    WriteValue(String, Vec, IpcSender),
-    Exit,
+pub struct BluetoothDeviceMsg {
+    // Bluetooth Device properties
+    pub id: String,
+    pub name: Option,
+    pub device_class: Option,
+    pub vendor_id_source: Option,
+    pub vendor_id: Option,
+    pub product_id: Option,
+    pub product_version: Option,
+    // Advertisiong Data properties
+    pub appearance: Option,
+    pub tx_power: Option,
+    pub rssi: Option,
 }
 
 #[derive(Deserialize, Serialize)]
-pub enum BluetoothObjectMsg {
-    BluetoothDevice {
-        // Bluetooth Device properties
-        id: String,
-        name: Option,
-        device_class: Option,
-        vendor_id_source: Option,
-        vendor_id: Option,
-        product_id: Option,
-        product_version: Option,
-        // Advertisiong Data properties
-        appearance: Option,
-        tx_power: Option,
-        rssi: Option
-    },
-    BluetoothServer {
-        connected: bool
-    },
-    BluetoothService {
-        uuid: String,
-        is_primary: bool,
-        instance_id: String
-    },
-    BluetoothServices {
-        services_vec: Vec
-    },
-    BluetoothCharacteristic {
-        // Characteristic
-        uuid: String,
-        instance_id: String,
-        // Characteristic properties
-        broadcast: bool,
-        read: bool,
-        write_without_response: bool,
-        write: bool,
-        notify: bool,
-        indicate: bool,
-        authenticated_signed_writes: bool,
-        reliable_write: bool,
-        writable_auxiliaries: bool
-    },
-    BluetoothCharacteristics {
-        characteristics_vec: Vec
-    },
-    BluetoothDescriptor {
-        uuid: String,
-        instance_id: String
-    },
-    BluetoothDescriptors {
-        descriptors_vec: Vec,
-    },
-    BluetoothReadValue {
-        value: Vec
-    },
-    BluetoothWriteValue,
-    Error {
-        error: String
-    },
+pub struct BluetoothServiceMsg {
+    pub uuid: String,
+    pub is_primary: bool,
+    pub instance_id: String,
+}
+
+#[derive(Deserialize, Serialize)]
+pub struct BluetoothCharacteristicMsg {
+    // Characteristic
+    pub uuid: String,
+    pub instance_id: String,
+    // Characteristic properties
+    pub broadcast: bool,
+    pub read: bool,
+    pub write_without_response: bool,
+    pub write: bool,
+    pub notify: bool,
+    pub indicate: bool,
+    pub authenticated_signed_writes: bool,
+    pub reliable_write: bool,
+    pub writable_auxiliaries: bool,
+}
+
+#[derive(Deserialize, Serialize)]
+pub struct BluetoothDescriptorMsg {
+    pub uuid: String,
+    pub instance_id: String,
+}
+
+pub type BluetoothServicesMsg = Vec;
+
+pub type BluetoothCharacteristicsMsg = Vec;
+
+pub type BluetoothDescriptorsMsg = Vec;
+
+pub type BluetoothResult = Result;
+
+#[derive(Deserialize, Serialize)]
+pub enum BluetoothMethodMsg {
+    RequestDevice(RequestDeviceoptions, IpcSender>),
+    GATTServerConnect(String, IpcSender>),
+    GATTServerDisconnect(String, IpcSender>),
+    GetPrimaryService(String, String, IpcSender>),
+    GetPrimaryServices(String, Option, IpcSender>),
+    GetCharacteristic(String, String, IpcSender>),
+    GetCharacteristics(String, Option, IpcSender>),
+    GetDescriptor(String, String, IpcSender>),
+    GetDescriptors(String, Option, IpcSender>),
+    ReadValue(String, IpcSender>>),
+    WriteValue(String, Vec, IpcSender>),
+    Exit,
 }
diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs
index 46602b4bbf3..1e1ae3b147d 100644
--- a/components/script/dom/bluetooth.rs
+++ b/components/script/dom/bluetooth.rs
@@ -18,7 +18,7 @@ use dom::bluetoothuuid::BluetoothUUID;
 use ipc_channel::ipc::{self, IpcSender};
 use net_traits::bluetooth_scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence};
 use net_traits::bluetooth_scanfilter::{RequestDeviceoptions, ServiceUUIDSequence};
-use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg};
+use net_traits::bluetooth_thread::BluetoothMethodMsg;
 use util::str::DOMString;
 
 const FILTER_EMPTY_ERROR: &'static str = "'filters' member must be non - empty to find any devices.";
@@ -133,51 +133,32 @@ impl BluetoothMethods for Bluetooth {
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice
     fn RequestDevice(&self, option: &RequestDeviceOptions) -> Fallible> {
         let (sender, receiver) = ipc::channel().unwrap();
-        match try!(convert_request_device_options(option, self.global().r())) {
-            option => {
-                self.get_bluetooth_thread().send(
-                    BluetoothMethodMsg::RequestDevice(option, sender)).unwrap();
-                let device = receiver.recv().unwrap();
-                match device {
-                    BluetoothObjectMsg::BluetoothDevice {
-                        id,
-                        name,
-                        device_class,
-                        vendor_id_source,
-                        vendor_id,
-                        product_id,
-                        product_version,
-                        appearance,
-                        tx_power,
-                        rssi,
-                    } => {
-                        let ad_data = &BluetoothAdvertisingData::new(self.global().r(),
-                                                                     appearance,
-                                                                     tx_power,
-                                                                     rssi);
-                        let vendor_id_source = vendor_id_source.map(|vid| match vid.as_str() {
-                            "bluetooth" => VendorIDSource::Bluetooth,
-                            "usb" => VendorIDSource::Usb,
-                            _ => VendorIDSource::Unknown,
-                        });
-                        let name = name.map(DOMString::from);
-                        Ok(BluetoothDevice::new(self.global().r(),
-                                                DOMString::from(id),
-                                                name,
-                                                ad_data,
-                                                device_class,
-                                                vendor_id_source,
-                                                vendor_id,
-                                                product_id,
-                                                product_version))
-                    },
-                    BluetoothObjectMsg::Error {
-                        error
-                    } => {
-                        Err(Type(error))
-                    },
-                    _ => unreachable!()
-                }
+        let option = try!(convert_request_device_options(option, self.global().r()));
+        self.get_bluetooth_thread().send(BluetoothMethodMsg::RequestDevice(option, sender)).unwrap();
+        let device = receiver.recv().unwrap();
+        match device {
+            Ok(device) => {
+                let ad_data = BluetoothAdvertisingData::new(self.global().r(),
+                                                            device.appearance,
+                                                            device.tx_power,
+                                                            device.rssi);
+                let vendor_id_source = device.vendor_id_source.map(|vid| match vid.as_str() {
+                    "bluetooth" => VendorIDSource::Bluetooth,
+                    "usb" => VendorIDSource::Usb,
+                    _ => VendorIDSource::Unknown,
+                });
+                Ok(BluetoothDevice::new(self.global().r(),
+                                        DOMString::from(device.id),
+                                        device.name.map(DOMString::from),
+                                        &ad_data,
+                                        device.device_class,
+                                        vendor_id_source,
+                                        device.vendor_id,
+                                        device.product_id,
+                                        device.product_version))
+            },
+            Err(error) => {
+                Err(Type(error))
             },
         }
     }
diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs
index 1a0e9c02010..9ae6c6596ba 100644
--- a/components/script/dom/bluetoothremotegattcharacteristic.rs
+++ b/components/script/dom/bluetoothremotegattcharacteristic.rs
@@ -20,7 +20,7 @@ use dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor;
 use dom::bluetoothremotegattservice::BluetoothRemoteGATTService;
 use dom::bluetoothuuid::{BluetoothDescriptorUUID, BluetoothUUID};
 use ipc_channel::ipc::{self, IpcSender};
-use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg};
+use net_traits::bluetooth_thread::BluetoothMethodMsg;
 use util::str::DOMString;
 
 // https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattcharacteristic
@@ -94,30 +94,21 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor
     fn GetDescriptor(&self, descriptor: BluetoothDescriptorUUID) -> Fallible> {
-        let uuid: String = match BluetoothUUID::GetDescriptor(self.global().r(), descriptor.clone()) {
-            Ok(domstring) => domstring.to_string(),
-            Err(error) => return Err(error),
-        };
+        let uuid = try!(BluetoothUUID::GetDescriptor(self.global().r(), descriptor)).to_string();
         let (sender, receiver) = ipc::channel().unwrap();
         self.get_bluetooth_thread().send(
             BluetoothMethodMsg::GetDescriptor(self.get_instance_id(), uuid, sender)).unwrap();
         let descriptor = receiver.recv().unwrap();
         match descriptor {
-            BluetoothObjectMsg::BluetoothDescriptor {
-                uuid,
-                instance_id
-            } => {
+            Ok(descriptor) => {
                 Ok(BluetoothRemoteGATTDescriptor::new(self.global().r(),
-                                                      &self,
-                                                      DOMString::from(uuid),
-                                                      instance_id))
+                                                      self,
+                                                      DOMString::from(descriptor.uuid),
+                                                      descriptor.instance_id))
             },
-            BluetoothObjectMsg::Error {
-                error
-            } => {
+            Err(error) => {
                 Err(Type(error))
             },
-            _ => unreachable!()
         }
     }
 
@@ -126,43 +117,25 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
                       descriptor: Option)
                       -> Fallible>> {
         let mut uuid: Option = None;
-        if let Some(d)= descriptor {
-            match BluetoothUUID::GetCharacteristic(self.global().r(), d.clone()) {
-                Ok(domstring) => uuid = Some(domstring.to_string()),
-                Err(error) => return Err(error),
-            }
+        if let Some(d) = descriptor {
+            uuid = Some(try!(BluetoothUUID::GetDescriptor(self.global().r(), d)).to_string())
         };
         let (sender, receiver) = ipc::channel().unwrap();
-        let mut descriptors: Vec> = vec!();
         self.get_bluetooth_thread().send(
             BluetoothMethodMsg::GetDescriptors(self.get_instance_id(), uuid, sender)).unwrap();
         let descriptors_vec = receiver.recv().unwrap();
         match descriptors_vec {
-            BluetoothObjectMsg::BluetoothDescriptors {
-                descriptors_vec
-            } => {
-                for d in descriptors_vec {
-                    match d {
-                        BluetoothObjectMsg::BluetoothDescriptor {
-                            uuid,
-                            instance_id,
-                        } => {
-                            descriptors.push(BluetoothRemoteGATTDescriptor::new(self.global().r(),
-                                                                                &self,
-                                                                                DOMString::from(uuid),
-                                                                                instance_id));
-                        },
-                        _ => unreachable!(),
-                    }
-                }
-                Ok(descriptors)
+            Ok(descriptor_vec) => {
+                Ok(descriptor_vec.into_iter()
+                                 .map(|desc| BluetoothRemoteGATTDescriptor::new(self.global().r(),
+                                                                                self,
+                                                                                DOMString::from(desc.uuid),
+                                                                                desc.instance_id))
+                                 .collect())
             },
-            BluetoothObjectMsg::Error {
-                error
-            } => {
+            Err(error) => {
                 Err(Type(error))
             },
-            _ => unreachable!(),
         }
     }
 
@@ -175,27 +148,21 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
     fn ReadValue(&self) -> Fallible {
         let (sender, receiver) = ipc::channel().unwrap();
         if !self.Service().Device().Gatt().Connected() {
-            Err(Network)
-        } else {
-            self.get_bluetooth_thread().send(
-                BluetoothMethodMsg::ReadValue(self.get_instance_id(), sender)).unwrap();
-            let result = receiver.recv().unwrap();
-            let value = match result {
-                BluetoothObjectMsg::BluetoothReadValue {
-                    value
-                } => {
-                    Some(ByteString::new(value))
-                },
-                BluetoothObjectMsg::Error {
-                    error
-                } => {
-                    return Err(Type(error))
-                },
-                _ => unreachable!()
-            };
-            *self.value.borrow_mut() = value;
-            Ok(self.GetValue().unwrap())
+            return Err(Network)
         }
+        self.get_bluetooth_thread().send(
+            BluetoothMethodMsg::ReadValue(self.get_instance_id(), sender)).unwrap();
+        let result = receiver.recv().unwrap();
+        let value = match result {
+            Ok(val) => {
+                ByteString::new(val)
+            },
+            Err(error) => {
+                return Err(Type(error))
+            },
+        };
+        *self.value.borrow_mut() = Some(value.clone());
+        Ok(value)
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue
@@ -205,13 +172,10 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
             BluetoothMethodMsg::WriteValue(self.get_instance_id(), value, sender)).unwrap();
         let result = receiver.recv().unwrap();
         match result {
-            BluetoothObjectMsg::BluetoothWriteValue => Ok(()),
-            BluetoothObjectMsg::Error {
-                error
-            } => {
+            Ok(_) => Ok(()),
+            Err(error) => {
                 Err(Type(error))
             },
-            _ => unreachable!()
         }
     }
 }
diff --git a/components/script/dom/bluetoothremotegattdescriptor.rs b/components/script/dom/bluetoothremotegattdescriptor.rs
index edbc61f9e3a..8e5a106cd05 100644
--- a/components/script/dom/bluetoothremotegattdescriptor.rs
+++ b/components/script/dom/bluetoothremotegattdescriptor.rs
@@ -18,7 +18,7 @@ use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
 use dom::bindings::str::ByteString;
 use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic;
 use ipc_channel::ipc::{self, IpcSender};
-use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg};
+use net_traits::bluetooth_thread::BluetoothMethodMsg;
 use util::str::DOMString;
 
 // http://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattdescriptor
@@ -89,27 +89,21 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
     fn ReadValue(&self) -> Fallible {
         let (sender, receiver) = ipc::channel().unwrap();
         if !self.Characteristic().Service().Device().Gatt().Connected() {
-            Err(Network)
-        } else {
-            self.get_bluetooth_thread().send(
-                BluetoothMethodMsg::ReadValue(self.get_instance_id(), sender)).unwrap();
-            let result = receiver.recv().unwrap();
-            let value = match result {
-                BluetoothObjectMsg::BluetoothReadValue {
-                    value
-                } => {
-                    Some(ByteString::new(value))
-                },
-                BluetoothObjectMsg::Error {
-                    error
-                } => {
-                    return Err(Type(error))
-                },
-                _ => unreachable!()
-            };
-            *self.value.borrow_mut() = value;
-            Ok(self.GetValue().unwrap())
+            return Err(Network)
         }
+        self.get_bluetooth_thread().send(
+            BluetoothMethodMsg::ReadValue(self.get_instance_id(), sender)).unwrap();
+        let result = receiver.recv().unwrap();
+        let value = match result {
+            Ok(val) => {
+                ByteString::new(val)
+            },
+            Err(error) => {
+                return Err(Type(error))
+            },
+        };
+        *self.value.borrow_mut() = Some(value.clone());
+        Ok(value)
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue
@@ -119,13 +113,10 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
             BluetoothMethodMsg::WriteValue(self.get_instance_id(), value, sender)).unwrap();
         let result = receiver.recv().unwrap();
         match result {
-            BluetoothObjectMsg::BluetoothWriteValue => Ok(()),
-            BluetoothObjectMsg::Error {
-                error
-            } => {
+            Ok(_) => Ok(()),
+            Err(error) => {
                 Err(Type(error))
             },
-            _ => unreachable!()
         }
     }
 }
diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs
index f34261eb54b..e4f4b20a9dc 100644
--- a/components/script/dom/bluetoothremotegattserver.rs
+++ b/components/script/dom/bluetoothremotegattserver.rs
@@ -14,7 +14,7 @@ use dom::bluetoothdevice::BluetoothDevice;
 use dom::bluetoothremotegattservice::BluetoothRemoteGATTService;
 use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID};
 use ipc_channel::ipc::{self, IpcSender};
-use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg};
+use net_traits::bluetooth_thread::BluetoothMethodMsg;
 use std::cell::Cell;
 use util::str::DOMString;
 
@@ -67,18 +67,13 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
             BluetoothMethodMsg::GATTServerConnect(String::from(self.Device().Id()), sender)).unwrap();
         let server = receiver.recv().unwrap();
         match server {
-            BluetoothObjectMsg::BluetoothServer {
-                connected
-            } => {
+            Ok(connected) => {
                 self.connected.set(connected);
                 Ok(Root::from_ref(self))
             },
-            BluetoothObjectMsg::Error {
-                error
-            } => {
+            Err(error) => {
                 Err(Type(error))
             },
-            _ => unreachable!()
         }
     }
 
@@ -89,49 +84,34 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
             BluetoothMethodMsg::GATTServerDisconnect(String::from(self.Device().Id()), sender)).unwrap();
         let server = receiver.recv().unwrap();
         match server {
-            BluetoothObjectMsg::BluetoothServer {
-                connected
-            } => {
+            Ok(connected) => {
                 self.connected.set(connected);
                 Ok(())
             },
-            BluetoothObjectMsg::Error {
-                error
-            } => {
+            Err(error) => {
                 Err(Type(error))
             },
-            _ => unreachable!()
         }
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice
     fn GetPrimaryService(&self, service: BluetoothServiceUUID) -> Fallible> {
-        let uuid: String = match BluetoothUUID::GetService(self.global().r(), service.clone()) {
-            Ok(domstring) => domstring.to_string(),
-            Err(error) => return Err(error),
-        };
+        let uuid = try!(BluetoothUUID::GetService(self.global().r(), service)).to_string();
         let (sender, receiver) = ipc::channel().unwrap();
         self.get_bluetooth_thread().send(
             BluetoothMethodMsg::GetPrimaryService(String::from(self.Device().Id()), uuid, sender)).unwrap();
         let service = receiver.recv().unwrap();
         match service {
-            BluetoothObjectMsg::BluetoothService {
-                uuid,
-                is_primary,
-                instance_id,
-            } => {
+            Ok(service) => {
                 Ok(BluetoothRemoteGATTService::new(self.global().r(),
                                                    &self.device.get(),
-                                                   DOMString::from(uuid),
-                                                   is_primary,
-                                                   instance_id))
+                                                   DOMString::from(service.uuid),
+                                                   service.is_primary,
+                                                   service.instance_id))
             },
-            BluetoothObjectMsg::Error {
-                error
-            } => {
+            Err(error) => {
                 Err(Type(error))
             },
-            _ => unreachable!(),
         }
     }
 
@@ -140,45 +120,26 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
                           service: Option)
                           -> Fallible>> {
         let mut uuid: Option = None;
-        if let Some(s)= service {
-            match BluetoothUUID::GetService(self.global().r(), s.clone()) {
-                Ok(domstring) => uuid = Some(domstring.to_string()),
-                Err(error) => return Err(error),
-            }
+        if let Some(s) = service {
+            uuid = Some(try!(BluetoothUUID::GetService(self.global().r(), s)).to_string())
         };
-        let mut services: Vec> = vec!();
         let (sender, receiver) = ipc::channel().unwrap();
         self.get_bluetooth_thread().send(
             BluetoothMethodMsg::GetPrimaryServices(String::from(self.Device().Id()), uuid, sender)).unwrap();
         let services_vec = receiver.recv().unwrap();
         match services_vec {
-            BluetoothObjectMsg::BluetoothServices {
-                services_vec
-            } => {
-                for s in services_vec {
-                    match s {
-                        BluetoothObjectMsg::BluetoothService {
-                            uuid,
-                            is_primary,
-                            instance_id,
-                        } => {
-                            services.push(BluetoothRemoteGATTService::new(self.global().r(),
-                                                                          &self.device.get(),
-                                                                          DOMString::from(uuid),
-                                                                          is_primary,
-                                                                          instance_id));
-                        },
-                        _ => unreachable!(),
-                    }
-                }
-                Ok(services)
+            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())
             },
-            BluetoothObjectMsg::Error {
-                error
-            } => {
+            Err(error) => {
                 Err(Type(error))
             },
-            _ => unreachable!(),
         }
     }
 }
diff --git a/components/script/dom/bluetoothremotegattservice.rs b/components/script/dom/bluetoothremotegattservice.rs
index c8d46c29904..92a5edc2f28 100644
--- a/components/script/dom/bluetoothremotegattservice.rs
+++ b/components/script/dom/bluetoothremotegattservice.rs
@@ -14,7 +14,7 @@ use dom::bluetoothdevice::BluetoothDevice;
 use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic;
 use dom::bluetoothuuid::{BluetoothCharacteristicUUID, BluetoothUUID};
 use ipc_channel::ipc::{self, IpcSender};
-use net_traits::bluetooth_thread::{BluetoothMethodMsg, BluetoothObjectMsg};
+use net_traits::bluetooth_thread::BluetoothMethodMsg;
 use util::str::DOMString;
 
 // https://webbluetoothcg.github.io/web-bluetooth/#bluetoothremotegattservice
@@ -87,50 +87,32 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
     fn GetCharacteristic(&self,
                          characteristic: BluetoothCharacteristicUUID)
                          -> Fallible> {
-        let uuid: String = match BluetoothUUID::GetCharacteristic(self.global().r(), characteristic.clone()) {
-            Ok(domstring) => domstring.to_string(),
-            Err(error) => return Err(error),
-        };
+        let uuid = try!(BluetoothUUID::GetCharacteristic(self.global().r(), characteristic)).to_string();
         let (sender, receiver) = ipc::channel().unwrap();
         self.get_bluetooth_thread().send(
             BluetoothMethodMsg::GetCharacteristic(self.get_instance_id(), uuid, sender)).unwrap();
         let characteristic = receiver.recv().unwrap();
         match characteristic {
-            BluetoothObjectMsg::BluetoothCharacteristic {
-                uuid,
-                instance_id,
-                broadcast,
-                read,
-                write_without_response,
-                write,
-                notify,
-                indicate,
-                authenticated_signed_writes,
-                reliable_write,
-                writable_auxiliaries,
-            } => {
-                let properties = &BluetoothCharacteristicProperties::new(self.global().r(),
-                                                                         broadcast,
-                                                                         read,
-                                                                         write_without_response,
-                                                                         write,
-                                                                         notify,
-                                                                         indicate,
-                                                                         authenticated_signed_writes,
-                                                                         reliable_write,
-                                                                         writable_auxiliaries);
+            Ok(characteristic) => {
+                let properties = BluetoothCharacteristicProperties::new(self.global().r(),
+                                                                        characteristic.broadcast,
+                                                                        characteristic.read,
+                                                                        characteristic.write_without_response,
+                                                                        characteristic.write,
+                                                                        characteristic.notify,
+                                                                        characteristic.indicate,
+                                                                        characteristic.authenticated_signed_writes,
+                                                                        characteristic.reliable_write,
+                                                                        characteristic.writable_auxiliaries);
                 Ok(BluetoothRemoteGATTCharacteristic::new(self.global().r(),
-                                                          &self,
-                                                          DOMString::from(uuid),
-                                                          properties,
-                                                          instance_id))
+                                                          self,
+                                                          DOMString::from(characteristic.uuid),
+                                                          &properties,
+                                                          characteristic.instance_id))
             },
-            BluetoothObjectMsg::Error {
-                error
-            } => {
+            Err(error) => {
                 Err(Type(error))
             },
-            _ => unreachable!(),
         }
     }
 
@@ -139,63 +121,38 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
                           characteristic: Option)
                           -> Fallible>> {
         let mut uuid: Option = None;
-        if let Some(c)= characteristic {
-            match BluetoothUUID::GetCharacteristic(self.global().r(), c.clone()) {
-                Ok(domstring) => uuid = Some(domstring.to_string()),
-                Err(error) => return Err(error),
-            }
+        if let Some(c) = characteristic {
+            uuid = Some(try!(BluetoothUUID::GetCharacteristic(self.global().r(), c)).to_string())
         };
-        let mut characteristics: Vec> = vec!();
+        let mut characteristics = vec!();
         let (sender, receiver) = ipc::channel().unwrap();
         self.get_bluetooth_thread().send(
             BluetoothMethodMsg::GetCharacteristics(self.get_instance_id(), uuid, sender)).unwrap();
         let characteristics_vec = receiver.recv().unwrap();
         match characteristics_vec {
-            BluetoothObjectMsg::BluetoothCharacteristics {
-                characteristics_vec
-            } => {
-                for characteristic in characteristics_vec {
-                    match characteristic {
-                        BluetoothObjectMsg::BluetoothCharacteristic {
-                            uuid,
-                            instance_id,
-                            broadcast,
-                            read,
-                            write_without_response,
-                            write,
-                            notify,
-                            indicate,
-                            authenticated_signed_writes,
-                            reliable_write,
-                            writable_auxiliaries,
-                        } => {
-                            let properties = &BluetoothCharacteristicProperties::new(self.global().r(),
-                                                                                     broadcast,
-                                                                                     read,
-                                                                                     write_without_response,
-                                                                                     write,
-                                                                                     notify,
-                                                                                     indicate,
-                                                                                     authenticated_signed_writes,
-                                                                                     reliable_write,
-                                                                                     writable_auxiliaries);
-                            characteristics.push(BluetoothRemoteGATTCharacteristic::new(self.global().r(),
-                                                                                        &self,
-                                                                                        DOMString::from(uuid),
-                                                                                        properties,
-                                                                                        instance_id));
-                        },
-                        _ => unreachable!(),
-                    }
+            Ok(characteristic_vec) => {
+                for characteristic in characteristic_vec {
+                    let properties = BluetoothCharacteristicProperties::new(self.global().r(),
+                                                                            characteristic.broadcast,
+                                                                            characteristic.read,
+                                                                            characteristic.write_without_response,
+                                                                            characteristic.write,
+                                                                            characteristic.notify,
+                                                                            characteristic.indicate,
+                                                                            characteristic.authenticated_signed_writes,
+                                                                            characteristic.reliable_write,
+                                                                            characteristic.writable_auxiliaries);
+                    characteristics.push(BluetoothRemoteGATTCharacteristic::new(self.global().r(),
+                                                                                self,
+                                                                                DOMString::from(characteristic.uuid),
+                                                                                &properties,
+                                                                                characteristic.instance_id));
                 }
                 Ok(characteristics)
             },
-            BluetoothObjectMsg::Error {
-                error
-            } => {
+            Err(error) => {
                 Err(Type(error))
             },
-            _ => unreachable!(),
         }
     }
 }

From f6799850904f44851b866fed76ce98cdc8eeab05 Mon Sep 17 00:00:00 2001
From: zakorgy 
Date: Fri, 22 Apr 2016 13:46:42 +0200
Subject: [PATCH 14/15] Update dependencies

---
 components/net_traits/Cargo.toml |  1 -
 components/net_traits/lib.rs     |  1 -
 components/servo/Cargo.lock      | 20 +++++++-------------
 ports/cef/Cargo.lock             | 32 +++++++++++++++++++++++++++-----
 ports/gonk/Cargo.lock            | 32 +++++++++++++++++++++++++++-----
 5 files changed, 61 insertions(+), 25 deletions(-)

diff --git a/components/net_traits/Cargo.toml b/components/net_traits/Cargo.toml
index f53bb989a35..2f0158fd020 100644
--- a/components/net_traits/Cargo.toml
+++ b/components/net_traits/Cargo.toml
@@ -12,7 +12,6 @@ path = "lib.rs"
 util = {path = "../util"}
 msg = {path = "../msg"}
 ipc-channel = {git = "https://github.com/servo/ipc-channel"}
-device = {git = "https://github.com/servo/devices"}
 heapsize = "0.3.0"
 heapsize_plugin = "0.1.2"
 hyper = { version = "0.9", features = [ "serde-serialization" ] }
diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs
index 17416d215dd..33ef19ef3bd 100644
--- a/components/net_traits/lib.rs
+++ b/components/net_traits/lib.rs
@@ -13,7 +13,6 @@
 
 #![deny(unsafe_code)]
 
-extern crate device;
 extern crate heapsize;
 extern crate hyper;
 extern crate image as piston_image;
diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock
index 5943b8626a9..34af5c0e36a 100644
--- a/components/servo/Cargo.lock
+++ b/components/servo/Cargo.lock
@@ -162,11 +162,6 @@ name = "bitflags"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "bitflags"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "block"
 version = "0.1.5"
@@ -174,11 +169,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "blurz"
-version = "0.1.4"
+version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "dbus 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -433,8 +428,8 @@ name = "dbus"
 version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -456,9 +451,9 @@ dependencies = [
 [[package]]
 name = "device"
 version = "0.0.1"
-source = "git+https://github.com/dati91/devices?branch=device-api#dccc5111e46124cef596cef10ce9056362892e59"
+source = "git+https://github.com/servo/devices#eeac5abfd548b63dcc48873261609922351551e1"
 dependencies = [
- "blurz 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "blurz 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1339,7 +1334,7 @@ dependencies = [
  "bitflags 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "brotli 0.3.20 (git+https://github.com/ende76/brotli-rs)",
  "cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "device 0.0.1 (git+https://github.com/dati91/devices?branch=device-api)",
+ "device 0.0.1 (git+https://github.com/servo/devices)",
  "devtools_traits 0.0.1",
  "flate2 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1400,7 +1395,6 @@ dependencies = [
 name = "net_traits"
 version = "0.0.1"
 dependencies = [
- "device 0.0.1 (git+https://github.com/dati91/devices?branch=device-api)",
  "heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_plugin 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock
index 7392afbf524..d268f18aa00 100644
--- a/ports/cef/Cargo.lock
+++ b/ports/cef/Cargo.lock
@@ -148,16 +148,20 @@ name = "bitflags"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "bitflags"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "block"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "blurz"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "dbus 0.3.2 (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"
 version = "0.3.20"
@@ -390,6 +394,15 @@ dependencies = [
  "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "dbus"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "debug_unreachable"
 version = "0.1.1"
@@ -406,6 +419,14 @@ 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#eeac5abfd548b63dcc48873261609922351551e1"
+dependencies = [
+ "blurz 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "devtools"
 version = "0.0.1"
@@ -1227,6 +1248,7 @@ dependencies = [
  "bitflags 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "brotli 0.3.20 (git+https://github.com/ende76/brotli-rs)",
  "cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "device 0.0.1 (git+https://github.com/servo/devices)",
  "devtools_traits 0.0.1",
  "flate2 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock
index 9140388c5ac..5283bf5983f 100644
--- a/ports/gonk/Cargo.lock
+++ b/ports/gonk/Cargo.lock
@@ -141,16 +141,20 @@ name = "bitflags"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "bitflags"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "block"
 version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "blurz"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "dbus 0.3.2 (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"
 version = "0.3.20"
@@ -383,6 +387,15 @@ dependencies = [
  "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "dbus"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "debug_unreachable"
 version = "0.1.1"
@@ -399,6 +412,14 @@ 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#eeac5abfd548b63dcc48873261609922351551e1"
+dependencies = [
+ "blurz 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "devtools"
 version = "0.0.1"
@@ -1210,6 +1231,7 @@ dependencies = [
  "bitflags 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "brotli 0.3.20 (git+https://github.com/ende76/brotli-rs)",
  "cookie 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "device 0.0.1 (git+https://github.com/servo/devices)",
  "devtools_traits 0.0.1",
  "flate2 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",

From 6828b3e720c5787a0affd466d12d1c5bc5c1e4e0 Mon Sep 17 00:00:00 2001
From: Attila Dusnoki 
Date: Mon, 18 Apr 2016 10:19:10 +0200
Subject: [PATCH 15/15] Add dbus lib to travis

---
 .travis.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.travis.yml b/.travis.yml
index 87bad747c60..ab91737d7a2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -34,6 +34,7 @@ matrix:
             - python-virtualenv
             - xorg-dev
             - ccache
+            - libdbus-glib-1-dev
 
 branches:
   only: