servo: Merge #12538 - Refactor Bluetooth error handling (from szeged:error-refactor); r=nox
authorzakorgy <zakorgy@inf.u-szeged.hu>
Thu, 28 Jul 2016 03:33:08 -0500
changeset 339385 e71a9c91cd9289120f62d100fae2b5dec35ee64a
parent 339384 b66411cd7c2160735dc4132a5806a72b954eb71c
child 339386 d59aae8f0362c90629d3711c18e961989e52d90c
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnox
servo: Merge #12538 - Refactor Bluetooth error handling (from szeged:error-refactor); r=nox <!-- Please describe your changes on the following line: --> Replace the error messages with an enum in `net/bluetooth_thread.rs`. Rename `bluetooth_blacklist.rs` to `bluetooth_utils.rs` and put the error conversion in it. With this the returned errors in DOM classes follow the specification. <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes do not require tests because there is no Web Bluetooth test API implementation yet. <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 45209b7ffea7b2355e227719ed29cb6aa6f00e0f
servo/components/net/bluetooth_thread.rs
servo/components/net_traits/bluetooth_thread.rs
servo/components/script/dom/bluetooth.rs
servo/components/script/dom/bluetoothremotegattcharacteristic.rs
servo/components/script/dom/bluetoothremotegattdescriptor.rs
servo/components/script/dom/bluetoothremotegattserver.rs
servo/components/script/dom/bluetoothremotegattservice.rs
--- a/servo/components/net/bluetooth_thread.rs
+++ b/servo/components/net/bluetooth_thread.rs
@@ -7,38 +7,30 @@ use device::bluetooth::BluetoothDevice;
 use device::bluetooth::BluetoothDiscoverySession;
 use device::bluetooth::BluetoothGATTCharacteristic;
 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::{BluetoothCharacteristicMsg, BluetoothCharacteristicsMsg};
 use net_traits::bluetooth_thread::{BluetoothDescriptorMsg, BluetoothDescriptorsMsg};
-use net_traits::bluetooth_thread::{BluetoothDeviceMsg, BluetoothMethodMsg};
+use net_traits::bluetooth_thread::{BluetoothDeviceMsg, BluetoothError, BluetoothMethodMsg};
 use net_traits::bluetooth_thread::{BluetoothResult, BluetoothServiceMsg, BluetoothServicesMsg};
 use rand::{self, Rng};
 use std::borrow::ToOwned;
 use std::collections::{HashMap, HashSet};
 use std::string::String;
 use std::thread;
 use std::time::Duration;
 #[cfg(target_os = "linux")]
 use tinyfiledialogs;
 use util::thread::spawn_named;
 
 const ADAPTER_ERROR: &'static str = "No adapter found";
-const DEVICE_ERROR: &'static str = "No device found";
-const DEVICE_MATCH_ERROR: &'static str = "No device found, that matches the given options";
-const PRIMARY_SERVICE_ERROR: &'static str = "No primary service found";
-const INCLUDED_SERVICE_ERROR: &'static str = "No included service found";
-const CHARACTERISTIC_ERROR: &'static str = "No characteristic found";
-const DESCRIPTOR_ERROR: &'static str = "No descriptor found";
-const VALUE_ERROR: &'static str = "No characteristic or descriptor found with that id";
-const SECURITY_ERROR: &'static str = "The operation is insecure";
-const NETWORK_ERROR: &'static str = "A network error occurred";
+
 // A transaction not completed within 30 seconds shall time out. Such a transaction shall be considered to have failed.
 // https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=286439 (Vol. 3, page 480)
 const MAXIMUM_TRANSACTION_TIME: u8 = 30;
 const CONNECTION_TIMEOUT_MS: u64 = 1000;
 // The discovery session needs some time to find any nearby devices
 const DISCOVERY_TIMEOUT_MS: u64 = 1500;
 #[cfg(target_os = "linux")]
 const DIALOG_TITLE: &'static str = "Choose a device";
@@ -68,17 +60,17 @@ macro_rules! return_if_cached(
         }
     );
 );
 
 macro_rules! get_adapter_or_return_error(
     ($bl_manager:expr, $sender:expr) => (
         match $bl_manager.get_or_create_adapter() {
             Some(adapter) => adapter,
-            None => return drop($sender.send(Err(String::from(ADAPTER_ERROR)))),
+            None => return drop($sender.send(Err(BluetoothError::Type(ADAPTER_ERROR.to_string())))),
         }
     );
 );
 
 pub trait BluetoothThreadFactory {
     fn new() -> Self;
 }
 
@@ -448,17 +440,17 @@ impl BluetoothManager {
         }
         let devices = self.get_and_cache_devices(&mut adapter);
         let matched_devices: Vec<BluetoothDevice> = devices.into_iter()
                                                            .filter(|d| matches_filters(d, options.get_filters()))
                                                            .collect();
         if let Some(address) = self.select_device(matched_devices) {
             let device_id = match self.address_to_id.get(&address) {
                 Some(id) => id.clone(),
-                None => return drop(sender.send(Err(String::from(DEVICE_MATCH_ERROR)))),
+                None => return drop(sender.send(Err(BluetoothError::NotFound))),
             };
             let mut services = options.get_services_set();
             if let Some(services_set) = self.allowed_services.get(&device_id) {
                 services = services_set | &services;
             }
             self.allowed_services.insert(device_id.clone(), services);
             if let Some(device) = self.get_device(&mut adapter, &device_id) {
                 let message = Ok(BluetoothDeviceMsg {
@@ -466,17 +458,17 @@ impl BluetoothManager {
                                      name: device.get_name().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));
             }
         }
-        return drop(sender.send(Err(String::from(DEVICE_MATCH_ERROR))));
+        return drop(sender.send(Err(BluetoothError::NotFound)));
     }
 
     fn gatt_server_connect(&mut self, device_id: String, sender: IpcSender<BluetoothResult<bool>>) {
         let mut adapter = get_adapter_or_return_error!(self, sender);
 
         match self.get_device(&mut adapter, &device_id) {
             Some(d) => {
                 if d.is_connected().unwrap_or(false) {
@@ -484,19 +476,19 @@ impl BluetoothManager {
                 }
                 let _ = d.connect();
                 for _ in 0..MAXIMUM_TRANSACTION_TIME {
                     match d.is_connected().unwrap_or(false) {
                         true => return drop(sender.send(Ok(true))),
                         false => thread::sleep(Duration::from_millis(CONNECTION_TIMEOUT_MS)),
                     }
                 }
-                return drop(sender.send(Err(String::from(NETWORK_ERROR))));
+                return drop(sender.send(Err(BluetoothError::Network)));
             },
-            None => return drop(sender.send(Err(String::from(DEVICE_ERROR)))),
+            None => return drop(sender.send(Err(BluetoothError::NotFound))),
         }
     }
 
     fn gatt_server_disconnect(&mut self, device_id: String, sender: IpcSender<BluetoothResult<bool>>) {
         let mut adapter = get_adapter_or_return_error!(self, sender);
 
         match self.get_device(&mut adapter, &device_id) {
             Some(d) => {
@@ -505,152 +497,152 @@ impl BluetoothManager {
                 }
                 let _ = d.disconnect();
                 for _ in 0..MAXIMUM_TRANSACTION_TIME {
                     match d.is_connected().unwrap_or(true) {
                         true => thread::sleep(Duration::from_millis(CONNECTION_TIMEOUT_MS)),
                         false => return drop(sender.send(Ok(false))),
                     }
                 }
-                return drop(sender.send(Err(String::from(NETWORK_ERROR))));
+                return drop(sender.send(Err(BluetoothError::Network)));
             },
-            None => return drop(sender.send(Err(String::from(DEVICE_ERROR)))),
+            None => return drop(sender.send(Err(BluetoothError::NotFound))),
         }
     }
 
     fn get_primary_service(&mut self,
                            device_id: String,
                            uuid: String,
                            sender: IpcSender<BluetoothResult<BluetoothServiceMsg>>) {
         let mut adapter = get_adapter_or_return_error!(self, sender);
         if !self.allowed_services.get(&device_id).map_or(false, |s| s.contains(&uuid)) {
-            return drop(sender.send(Err(String::from(SECURITY_ERROR))));
+            return drop(sender.send(Err(BluetoothError::Security)));
         }
         let services = self.get_gatt_services_by_uuid(&mut adapter, &device_id, &uuid);
         if services.is_empty() {
-            return drop(sender.send(Err(String::from(PRIMARY_SERVICE_ERROR))));
+            return drop(sender.send(Err(BluetoothError::NotFound)));
         }
         for service in services {
             if service.is_primary().unwrap_or(false) {
                 if let Ok(uuid) = service.get_uuid() {
                     return drop(sender.send(Ok(BluetoothServiceMsg {
                                                    uuid: uuid,
                                                    is_primary: true,
                                                    instance_id: service.get_object_path(),
                                                })));
                 }
             }
         }
-        return drop(sender.send(Err(String::from(PRIMARY_SERVICE_ERROR))));
+        return drop(sender.send(Err(BluetoothError::NotFound)));
     }
 
     fn get_primary_services(&mut self,
                             device_id: String,
                             uuid: Option<String>,
                             sender: IpcSender<BluetoothResult<BluetoothServicesMsg>>) {
         let mut adapter = get_adapter_or_return_error!(self, sender);
         let services = match uuid {
             Some(ref id) => {
                 if !self.allowed_services.get(&device_id).map_or(false, |s| s.contains(id)) {
-                    return drop(sender.send(Err(String::from(SECURITY_ERROR))))
+                    return drop(sender.send(Err(BluetoothError::Security)))
                 }
                 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() {
-            return drop(sender.send(Err(String::from(PRIMARY_SERVICE_ERROR))));
+            return drop(sender.send(Err(BluetoothError::NotFound)));
         }
         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(BluetoothServiceMsg {
                                           uuid: uuid,
                                           is_primary: true,
                                           instance_id: service.get_object_path(),
                                       });
                 }
             }
         }
         if services_vec.is_empty() {
-            return drop(sender.send(Err(String::from(PRIMARY_SERVICE_ERROR))));
+            return drop(sender.send(Err(BluetoothError::NotFound)));
         }
 
         let _ = sender.send(Ok(services_vec));
     }
 
     fn get_included_service(&mut self,
                             service_id: String,
                             uuid: String,
                             sender: IpcSender<BluetoothResult<BluetoothServiceMsg>>) {
         let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
-            None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
+            None => return drop(sender.send(Err(BluetoothError::Type(ADAPTER_ERROR.to_string())))),
         };
         let primary_service = match self.get_gatt_service(&mut adapter, &service_id) {
             Some(s) => s,
-            None => return drop(sender.send(Err(String::from(PRIMARY_SERVICE_ERROR)))),
+            None => return drop(sender.send(Err(BluetoothError::NotFound))),
         };
         let services = primary_service.get_includes().unwrap_or(vec!());
         for service in services {
             if let Ok(service_uuid) = service.get_uuid() {
                 if uuid == service_uuid {
                     return drop(sender.send(Ok(BluetoothServiceMsg {
                                                    uuid: uuid,
                                                    is_primary: service.is_primary().unwrap_or(false),
                                                    instance_id: service.get_object_path(),
                                                })));
                 }
             }
         }
-        return drop(sender.send(Err(String::from(INCLUDED_SERVICE_ERROR))));
+        return drop(sender.send(Err(BluetoothError::NotFound)));
     }
 
     fn get_included_services(&mut self,
                              service_id: String,
                              uuid: Option<String>,
                              sender: IpcSender<BluetoothResult<BluetoothServicesMsg>>) {
         let mut adapter = match self.get_or_create_adapter() {
             Some(a) => a,
-            None => return drop(sender.send(Err(String::from(ADAPTER_ERROR)))),
+            None => return drop(sender.send(Err(BluetoothError::Type(ADAPTER_ERROR.to_string())))),
         };
         let primary_service = match self.get_gatt_service(&mut adapter, &service_id) {
             Some(s) => s,
-            None => return drop(sender.send(Err(String::from(PRIMARY_SERVICE_ERROR)))),
+            None => return drop(sender.send(Err(BluetoothError::NotFound))),
         };
         let services = primary_service.get_includes().unwrap_or(vec!());
         let mut services_vec = vec!();
         for service in services {
             if let Ok(service_uuid) = service.get_uuid() {
                 services_vec.push(BluetoothServiceMsg {
                                       uuid: service_uuid,
                                       is_primary: service.is_primary().unwrap_or(false),
                                       instance_id: service.get_object_path(),
                                   });
             }
         }
         if let Some(uuid) = uuid {
             services_vec.retain(|ref s| s.uuid == uuid);
         }
         if services_vec.is_empty() {
-            return drop(sender.send(Err(String::from(INCLUDED_SERVICE_ERROR))));
+            return drop(sender.send(Err(BluetoothError::NotFound)));
         }
 
         let _ = sender.send(Ok(services_vec));
     }
 
     fn get_characteristic(&mut self,
                           service_id: String,
                           uuid: String,
                           sender: IpcSender<BluetoothResult<BluetoothCharacteristicMsg>>) {
         let mut adapter = get_adapter_or_return_error!(self, sender);
         let characteristics = self.get_gatt_characteristics_by_uuid(&mut adapter, &service_id, &uuid);
         if characteristics.is_empty() {
-            return drop(sender.send(Err(String::from(CHARACTERISTIC_ERROR))));
+            return drop(sender.send(Err(BluetoothError::NotFound)));
         }
         for characteristic in characteristics {
             if let Ok(uuid) = characteristic.get_uuid() {
                 let properties = self.get_characteristic_properties(&characteristic);
                 let message = Ok(BluetoothCharacteristicMsg {
                                      uuid: uuid,
                                      instance_id: characteristic.get_object_path(),
                                      broadcast: properties.contains(BROADCAST),
@@ -661,30 +653,30 @@ impl BluetoothManager {
                                      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));
             }
         }
-        return drop(sender.send(Err(String::from(CHARACTERISTIC_ERROR))));
+        return drop(sender.send(Err(BluetoothError::NotFound)));
     }
 
     fn get_characteristics(&mut self,
                            service_id: String,
                            uuid: Option<String>,
                            sender: IpcSender<BluetoothResult<BluetoothCharacteristicsMsg>>) {
         let mut adapter = get_adapter_or_return_error!(self, sender);
         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() {
-            return drop(sender.send(Err(String::from(CHARACTERISTIC_ERROR))));
+            return drop(sender.send(Err(BluetoothError::NotFound)));
         }
         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(
                                 BluetoothCharacteristicMsg {
                                     uuid: uuid,
@@ -697,90 +689,90 @@ impl BluetoothManager {
                                     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() {
-            return drop(sender.send(Err(String::from(CHARACTERISTIC_ERROR))));
+            return drop(sender.send(Err(BluetoothError::NotFound)));
         }
 
         let _ = sender.send(Ok(characteristics_vec));
     }
 
     fn get_descriptor(&mut self,
                       characteristic_id: String,
                       uuid: String,
                       sender: IpcSender<BluetoothResult<BluetoothDescriptorMsg>>) {
         let mut adapter = get_adapter_or_return_error!(self, sender);
         let descriptors = self.get_gatt_descriptors_by_uuid(&mut adapter, &characteristic_id, &uuid);
         if descriptors.is_empty() {
-            return drop(sender.send(Err(String::from(DESCRIPTOR_ERROR))));
+            return drop(sender.send(Err(BluetoothError::NotFound)));
         }
         for descriptor in descriptors {
             if let Ok(uuid) = descriptor.get_uuid() {
                 return drop(sender.send(Ok(BluetoothDescriptorMsg {
                                                uuid: uuid,
                                                instance_id: descriptor.get_object_path(),
                                            })));
             }
         }
-        return drop(sender.send(Err(String::from(DESCRIPTOR_ERROR))));
+        return drop(sender.send(Err(BluetoothError::NotFound)));
     }
 
     fn get_descriptors(&mut self,
                        characteristic_id: String,
                        uuid: Option<String>,
                        sender: IpcSender<BluetoothResult<BluetoothDescriptorsMsg>>) {
         let mut adapter = get_adapter_or_return_error!(self, sender);
         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() {
-            return drop(sender.send(Err(String::from(DESCRIPTOR_ERROR))));
+            return drop(sender.send(Err(BluetoothError::NotFound)));
         }
         let mut descriptors_vec = vec!();
         for descriptor in descriptors {
             if let Ok(uuid) = descriptor.get_uuid() {
                 descriptors_vec.push(BluetoothDescriptorMsg {
                                          uuid: uuid,
                                          instance_id: descriptor.get_object_path(),
                                      });
             }
         }
         if descriptors_vec.is_empty() {
-            return drop(sender.send(Err(String::from(DESCRIPTOR_ERROR))));
+            return drop(sender.send(Err(BluetoothError::NotFound)));
         }
         let _ = sender.send(Ok(descriptors_vec));
     }
 
     fn read_value(&mut self, id: String, sender: IpcSender<BluetoothResult<Vec<u8>>>) {
         let mut adapter = get_adapter_or_return_error!(self, sender);
         let mut value = self.get_gatt_characteristic(&mut adapter, &id)
                             .map(|c| c.read_value().unwrap_or(vec![]));
         if value.is_none() {
             value = self.get_gatt_descriptor(&mut adapter, &id)
                         .map(|d| d.read_value().unwrap_or(vec![]));
         }
-        let _ = sender.send(value.ok_or(String::from(VALUE_ERROR)));
+        let _ = sender.send(value.ok_or(BluetoothError::NotSupported));
     }
 
     fn write_value(&mut self, id: String, value: Vec<u8>, sender: IpcSender<BluetoothResult<bool>>) {
         let mut adapter = get_adapter_or_return_error!(self, sender);
         let mut result = self.get_gatt_characteristic(&mut adapter, &id)
                              .map(|c| c.write_value(value.clone()));
         if result.is_none() {
             result = self.get_gatt_descriptor(&mut adapter, &id)
                          .map(|d| d.write_value(value.clone()));
         }
         let message = match result {
             Some(v) => match v {
                 Ok(_) => Ok(true),
-                Err(e) => return drop(sender.send(Err(e.to_string()))),
+                Err(_) => return drop(sender.send(Err(BluetoothError::NotSupported))),
             },
-            None => return drop(sender.send(Err(String::from(VALUE_ERROR)))),
+            None => return drop(sender.send(Err(BluetoothError::NotSupported))),
         };
         let _ = sender.send(message);
     }
 }
--- a/servo/components/net_traits/bluetooth_thread.rs
+++ b/servo/components/net_traits/bluetooth_thread.rs
@@ -1,15 +1,25 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
 use bluetooth_scanfilter::RequestDeviceoptions;
 use ipc_channel::ipc::IpcSender;
 
 #[derive(Deserialize, Serialize)]
+pub enum BluetoothError {
+    Type(String),
+    Network,
+    NotFound,
+    NotSupported,
+    Security,
+}
+
+#[derive(Deserialize, Serialize)]
 pub struct BluetoothDeviceMsg {
     // Bluetooth Device properties
     pub id: String,
     pub name: Option<String>,
     // Advertisiong Data properties
     pub appearance: Option<u16>,
     pub tx_power: Option<i8>,
     pub rssi: Option<i8>,
@@ -46,17 +56,17 @@ pub struct BluetoothDescriptorMsg {
 }
 
 pub type BluetoothServicesMsg = Vec<BluetoothServiceMsg>;
 
 pub type BluetoothCharacteristicsMsg = Vec<BluetoothCharacteristicMsg>;
 
 pub type BluetoothDescriptorsMsg = Vec<BluetoothDescriptorMsg>;
 
-pub type BluetoothResult<T> = Result<T, String>;
+pub type BluetoothResult<T> = Result<T, BluetoothError>;
 
 #[derive(Deserialize, Serialize)]
 pub enum BluetoothMethodMsg {
     RequestDevice(RequestDeviceoptions, IpcSender<BluetoothResult<BluetoothDeviceMsg>>),
     GATTServerConnect(String, IpcSender<BluetoothResult<bool>>),
     GATTServerDisconnect(String, IpcSender<BluetoothResult<bool>>),
     GetPrimaryService(String, String, IpcSender<BluetoothResult<BluetoothServiceMsg>>),
     GetPrimaryServices(String, Option<String>, IpcSender<BluetoothResult<BluetoothServicesMsg>>),
--- a/servo/components/script/dom/bluetooth.rs
+++ b/servo/components/script/dom/bluetooth.rs
@@ -2,29 +2,29 @@
  * 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_blacklist::{Blacklist, uuid_is_blacklisted};
 use core::clone::Clone;
 use dom::bindings::codegen::Bindings::BluetoothBinding;
 use dom::bindings::codegen::Bindings::BluetoothBinding::RequestDeviceOptions;
 use dom::bindings::codegen::Bindings::BluetoothBinding::{BluetoothScanFilter, BluetoothMethods};
-use dom::bindings::error::Error::{Security, Type};
+use dom::bindings::error::Error::{self, Security, 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::bindings::str::DOMString;
 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;
+use net_traits::bluetooth_thread::{BluetoothError, BluetoothMethodMsg};
 
 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;
 // A device name can never be longer than 29 bytes.
 // An advertising packet is at most 31 bytes long.
@@ -130,16 +130,28 @@ fn convert_request_device_options(option
             }
         }
     }
 
     Ok(RequestDeviceoptions::new(BluetoothScanfilterSequence::new(filters),
                                  ServiceUUIDSequence::new(optional_services)))
 }
 
+impl From<BluetoothError> for Error {
+    fn from(error: BluetoothError) -> Self {
+        match error {
+            BluetoothError::Type(message) => Error::Type(message),
+            BluetoothError::Network => Error::Network,
+            BluetoothError::NotFound => Error::NotFound,
+            BluetoothError::NotSupported => Error::NotSupported,
+            BluetoothError::Security => Error::Security,
+        }
+    }
+}
+
 impl BluetoothMethods for Bluetooth {
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice
     fn RequestDevice(&self, option: &RequestDeviceOptions) -> Fallible<Root<BluetoothDevice>> {
         let (sender, receiver) = ipc::channel().unwrap();
         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 {
@@ -149,13 +161,13 @@ impl BluetoothMethods for Bluetooth {
                                                             device.tx_power,
                                                             device.rssi);
                 Ok(BluetoothDevice::new(self.global().r(),
                                         DOMString::from(device.id),
                                         device.name.map(DOMString::from),
                                         &ad_data))
             },
             Err(error) => {
-                Err(Type(error))
+                Err(Error::from(error))
             },
         }
     }
 }
--- a/servo/components/script/dom/bluetoothremotegattcharacteristic.rs
+++ b/servo/components/script/dom/bluetoothremotegattcharacteristic.rs
@@ -7,17 +7,17 @@ use dom::bindings::cell::DOMRefCell;
 use dom::bindings::codegen::Bindings::BluetoothCharacteristicPropertiesBinding::
     BluetoothCharacteristicPropertiesMethods;
 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::{InvalidModification, Network, NotSupported, Security, Type};
+use dom::bindings::error::Error::{self, InvalidModification, Network, NotSupported, Security};
 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};
 use dom::bindings::str::{ByteString, DOMString};
 use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties;
 use dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor;
 use dom::bluetoothremotegattservice::BluetoothRemoteGATTService;
@@ -110,17 +110,17 @@ impl BluetoothRemoteGATTCharacteristicMe
         match descriptor {
             Ok(descriptor) => {
                 Ok(BluetoothRemoteGATTDescriptor::new(self.global().r(),
                                                       self,
                                                       DOMString::from(descriptor.uuid),
                                                       descriptor.instance_id))
             },
             Err(error) => {
-                Err(Type(error))
+                Err(Error::from(error))
             },
         }
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors
     fn GetDescriptors(&self,
                       descriptor: Option<BluetoothDescriptorUUID>)
                       -> Fallible<Vec<Root<BluetoothRemoteGATTDescriptor>>> {
@@ -142,17 +142,17 @@ impl BluetoothRemoteGATTCharacteristicMe
                 Ok(descriptor_vec.into_iter()
                                  .map(|desc| BluetoothRemoteGATTDescriptor::new(self.global().r(),
                                                                                 self,
                                                                                 DOMString::from(desc.uuid),
                                                                                 desc.instance_id))
                                  .collect())
             },
             Err(error) => {
-                Err(Type(error))
+                Err(Error::from(error))
             },
         }
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-value
     fn GetValue(&self) -> Option<ByteString> {
         self.value.borrow().clone()
     }
@@ -172,17 +172,17 @@ impl BluetoothRemoteGATTCharacteristicMe
         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))
+                return Err(Error::from(error))
             },
         };
         *self.value.borrow_mut() = Some(value.clone());
         Ok(value)
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue
     fn WriteValue(&self, value: Vec<u8>) -> ErrorResult {
@@ -203,13 +203,13 @@ impl BluetoothRemoteGATTCharacteristicMe
         }
         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 {
             Ok(_) => Ok(()),
             Err(error) => {
-                Err(Type(error))
+                Err(Error::from(error))
             },
         }
     }
 }
--- a/servo/components/script/dom/bluetoothremotegattdescriptor.rs
+++ b/servo/components/script/dom/bluetoothremotegattdescriptor.rs
@@ -6,17 +6,17 @@ use bluetooth_blacklist::{Blacklist, uui
 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::{InvalidModification, Network, Security, Type};
+use dom::bindings::error::Error::{self, InvalidModification, Network, Security};
 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};
 use dom::bindings::str::{ByteString, DOMString};
 use dom::bluetoothremotegattcharacteristic::{BluetoothRemoteGATTCharacteristic, MAXIMUM_ATTRIBUTE_LENGTH};
 use ipc_channel::ipc::{self, IpcSender};
 use net_traits::bluetooth_thread::BluetoothMethodMsg;
@@ -96,17 +96,17 @@ impl BluetoothRemoteGATTDescriptorMethod
         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))
+                return Err(Error::from(error))
             },
         };
         *self.value.borrow_mut() = Some(value.clone());
         Ok(value)
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue
     fn WriteValue(&self, value: Vec<u8>) -> ErrorResult {
@@ -121,13 +121,13 @@ impl BluetoothRemoteGATTDescriptorMethod
         }
         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 {
             Ok(_) => Ok(()),
             Err(error) => {
-                Err(Type(error))
+                Err(Error::from(error))
             },
         }
     }
 }
--- a/servo/components/script/dom/bluetoothremotegattserver.rs
+++ b/servo/components/script/dom/bluetoothremotegattserver.rs
@@ -1,17 +1,17 @@
 /* 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_blacklist::{Blacklist, uuid_is_blacklisted};
 use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
 use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding;
 use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods;
-use dom::bindings::error::Error::{Security, Type};
+use dom::bindings::error::Error::{self, Security};
 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};
 use dom::bindings::str::DOMString;
 use dom::bluetoothdevice::BluetoothDevice;
 use dom::bluetoothremotegattservice::BluetoothRemoteGATTService;
 use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID};
@@ -67,34 +67,34 @@ impl BluetoothRemoteGATTServerMethods fo
             BluetoothMethodMsg::GATTServerConnect(String::from(self.Device().Id()), sender)).unwrap();
         let server = receiver.recv().unwrap();
         match server {
             Ok(connected) => {
                 self.connected.set(connected);
                 Ok(Root::from_ref(self))
             },
             Err(error) => {
-                Err(Type(error))
+                Err(Error::from(error))
             },
         }
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-disconnect
     fn Disconnect(&self) -> ErrorResult {
         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 {
             Ok(connected) => {
                 self.connected.set(connected);
                 Ok(())
             },
             Err(error) => {
-                Err(Type(error))
+                Err(Error::from(error))
             },
         }
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice
     fn GetPrimaryService(&self, service: BluetoothServiceUUID) -> Fallible<Root<BluetoothRemoteGATTService>> {
         let uuid = try!(BluetoothUUID::GetService(self.global().r(), service)).to_string();
         if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
@@ -108,17 +108,17 @@ impl BluetoothRemoteGATTServerMethods fo
             Ok(service) => {
                 Ok(BluetoothRemoteGATTService::new(self.global().r(),
                                                    &self.device.get(),
                                                    DOMString::from(service.uuid),
                                                    service.is_primary,
                                                    service.instance_id))
             },
             Err(error) => {
-                Err(Type(error))
+                Err(Error::from(error))
             },
         }
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices
     fn GetPrimaryServices(&self,
                           service: Option<BluetoothServiceUUID>)
                           -> Fallible<Vec<Root<BluetoothRemoteGATTService>>> {
@@ -141,13 +141,13 @@ impl BluetoothRemoteGATTServerMethods fo
                               .map(|service| BluetoothRemoteGATTService::new(self.global().r(),
                                                                              &self.device.get(),
                                                                              DOMString::from(service.uuid),
                                                                              service.is_primary,
                                                                              service.instance_id))
                               .collect())
             },
             Err(error) => {
-                Err(Type(error))
+                Err(Error::from(error))
             },
         }
     }
 }
--- a/servo/components/script/dom/bluetoothremotegattservice.rs
+++ b/servo/components/script/dom/bluetoothremotegattservice.rs
@@ -1,16 +1,16 @@
 /* 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_blacklist::{Blacklist, uuid_is_blacklisted};
 use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding;
 use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods;
-use dom::bindings::error::Error::{Security, Type};
+use dom::bindings::error::Error::{self, Security};
 use dom::bindings::error::Fallible;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::{JS, MutHeap, Root};
 use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object};
 use dom::bindings::str::DOMString;
 use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties;
 use dom::bluetoothdevice::BluetoothDevice;
 use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic;
@@ -110,17 +110,17 @@ impl BluetoothRemoteGATTServiceMethods f
                                                                         characteristic.writable_auxiliaries);
                 Ok(BluetoothRemoteGATTCharacteristic::new(self.global().r(),
                                                           self,
                                                           DOMString::from(characteristic.uuid),
                                                           &properties,
                                                           characteristic.instance_id))
             },
             Err(error) => {
-                Err(Type(error))
+                Err(Error::from(error))
             },
         }
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics
     fn GetCharacteristics(&self,
                           characteristic: Option<BluetoothCharacteristicUUID>)
                           -> Fallible<Vec<Root<BluetoothRemoteGATTCharacteristic>>> {
@@ -155,17 +155,17 @@ impl BluetoothRemoteGATTServiceMethods f
                                                                                 self,
                                                                                 DOMString::from(characteristic.uuid),
                                                                                 &properties,
                                                                                 characteristic.instance_id));
                 }
                 Ok(characteristics)
             },
             Err(error) => {
-                Err(Type(error))
+                Err(Error::from(error))
             },
         }
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservice
     fn GetIncludedService(&self,
                           service: BluetoothServiceUUID)
                           -> Fallible<Root<BluetoothRemoteGATTService>> {
@@ -183,17 +183,17 @@ impl BluetoothRemoteGATTServiceMethods f
             Ok(service) => {
                 Ok(BluetoothRemoteGATTService::new(self.global().r(),
                                                    &self.device.get(),
                                                    DOMString::from(service.uuid),
                                                    service.is_primary,
                                                    service.instance_id))
             },
             Err(error) => {
-                Err(Type(error))
+                Err(Error::from(error))
             },
         }
     }
 
     // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices
     fn GetIncludedServices(&self,
                           service: Option<BluetoothServiceUUID>)
                           -> Fallible<Vec<Root<BluetoothRemoteGATTService>>> {
@@ -218,13 +218,13 @@ impl BluetoothRemoteGATTServiceMethods f
                               .map(|service| BluetoothRemoteGATTService::new(self.global().r(),
                                                                              &self.device.get(),
                                                                              DOMString::from(service.uuid),
                                                                              service.is_primary,
                                                                              service.instance_id))
                               .collect())
             },
             Err(error) => {
-                Err(Type(error))
+                Err(Error::from(error))
             },
         }
     }
 }