mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Auto merge of #11335 - szeged:blacklist, r=jdm
Add WebBluetooth GATTBlacklist support 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 --faster` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). Either: - [ ] There are tests for these changes OR - [X] These changes do not require tests because there are no webbluetooth tests yet. Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11335) <!-- Reviewable:end -->
This commit is contained in:
commit
6b1088234b
8 changed files with 237 additions and 10 deletions
124
components/script/bluetooth_blacklist.rs
Normal file
124
components/script/bluetooth_blacklist.rs
Normal file
|
@ -0,0 +1,124 @@
|
|||
/* 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 regex::Regex;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::io::BufRead;
|
||||
use std::string::String;
|
||||
use util::resource_files::read_resource_file;
|
||||
|
||||
const BLACKLIST_FILE: &'static str = "gatt_blacklist.txt";
|
||||
const BLACKLIST_FILE_NOT_FOUND: &'static str = "Could not find gatt_blacklist.txt file";
|
||||
const EXCLUDE_READS: &'static str = "exclude-reads";
|
||||
const EXCLUDE_WRITES: &'static str = "exclude-writes";
|
||||
const VALID_UUID_REGEX: &'static str = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
|
||||
|
||||
thread_local!(pub static BLUETOOTH_BLACKLIST: RefCell<BluetoothBlacklist> =
|
||||
RefCell::new(BluetoothBlacklist(parse_blacklist())));
|
||||
|
||||
pub fn uuid_is_blacklisted(uuid: &str, exclude_type: Blacklist) -> bool {
|
||||
BLUETOOTH_BLACKLIST.with(|blist| {
|
||||
match exclude_type {
|
||||
Blacklist::All => {
|
||||
blist.borrow().is_blacklisted(uuid)
|
||||
},
|
||||
Blacklist::Reads => {
|
||||
blist.borrow().is_blacklisted_for_reads(uuid)
|
||||
}
|
||||
Blacklist::Writes => {
|
||||
blist.borrow().is_blacklisted_for_writes(uuid)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub struct BluetoothBlacklist(Option<HashMap<String, Blacklist>>);
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub enum Blacklist {
|
||||
All, // Read and Write
|
||||
Reads,
|
||||
Writes,
|
||||
}
|
||||
|
||||
impl BluetoothBlacklist {
|
||||
// https://webbluetoothcg.github.io/web-bluetooth/#blacklisted
|
||||
pub fn is_blacklisted(&self, uuid: &str) -> bool {
|
||||
match self.0 {
|
||||
Some(ref map) => map.get(uuid).map_or(false, |et| et.eq(&Blacklist::All)),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
// https://webbluetoothcg.github.io/web-bluetooth/#blacklisted-for-reads
|
||||
pub fn is_blacklisted_for_reads(&self, uuid: &str) -> bool {
|
||||
match self.0 {
|
||||
Some(ref map) => map.get(uuid).map_or(false, |et| et.eq(&Blacklist::All) ||
|
||||
et.eq(&Blacklist::Reads)),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
// https://webbluetoothcg.github.io/web-bluetooth/#blacklisted-for-writes
|
||||
pub fn is_blacklisted_for_writes(&self, uuid: &str) -> bool {
|
||||
match self.0 {
|
||||
Some(ref map) => map.get(uuid).map_or(false, |et| et.eq(&Blacklist::All) ||
|
||||
et.eq(&Blacklist::Writes)),
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://webbluetoothcg.github.io/web-bluetooth/#parsing-the-blacklist
|
||||
fn parse_blacklist() -> Option<HashMap<String, Blacklist>> {
|
||||
// Step 1 missing, currently we parse ./resources/gatt_blacklist.txt.
|
||||
let valid_uuid_regex = Regex::new(VALID_UUID_REGEX).unwrap();
|
||||
let content = read_resource_file(BLACKLIST_FILE).expect(BLACKLIST_FILE_NOT_FOUND);
|
||||
// Step 3
|
||||
let mut result = HashMap::new();
|
||||
// Step 2 and 4
|
||||
for line in content.lines() {
|
||||
let line = match line {
|
||||
Ok(l) => l,
|
||||
Err(_) => return None,
|
||||
};
|
||||
// Step 4.1
|
||||
if line.is_empty() || line.starts_with('#') {
|
||||
continue;
|
||||
}
|
||||
let mut exclude_type = Blacklist::All;
|
||||
let mut words = line.split_whitespace();
|
||||
let uuid = match words.next() {
|
||||
Some(uuid) => uuid,
|
||||
None => continue,
|
||||
};
|
||||
if !valid_uuid_regex.is_match(uuid) {
|
||||
return None;
|
||||
}
|
||||
match words.next() {
|
||||
// Step 4.2 We already have an initialized exclude_type variable with Blacklist::All.
|
||||
None => {},
|
||||
// Step 4.3
|
||||
Some(EXCLUDE_READS) => {
|
||||
exclude_type = Blacklist::Reads;
|
||||
},
|
||||
Some(EXCLUDE_WRITES) => {
|
||||
exclude_type = Blacklist::Writes;
|
||||
},
|
||||
// Step 4.4
|
||||
_ => {
|
||||
return None;
|
||||
},
|
||||
}
|
||||
// Step 4.5
|
||||
if result.contains_key(uuid) {
|
||||
return None;
|
||||
}
|
||||
// Step 4.6
|
||||
result.insert(uuid.to_string(), exclude_type);
|
||||
}
|
||||
// Step 5
|
||||
return Some(result);
|
||||
}
|
|
@ -2,11 +2,12 @@
|
|||
* 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::Type;
|
||||
use dom::bindings::error::Error::{Security, Type};
|
||||
use dom::bindings::error::Fallible;
|
||||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::Root;
|
||||
|
@ -71,7 +72,11 @@ fn canonicalize_filter(filter: &BluetoothScanFilter, global: GlobalRef) -> Falli
|
|||
return Err(Type(SERVICE_ERROR.to_owned()));
|
||||
}
|
||||
for service in services {
|
||||
services_vec.push(try!(BluetoothUUID::GetService(global, service.clone())).to_string());
|
||||
let uuid = try!(BluetoothUUID::GetService(global, service.clone())).to_string();
|
||||
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
|
||||
return Err(Security)
|
||||
}
|
||||
services_vec.push(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,7 +124,11 @@ fn convert_request_device_options(options: &RequestDeviceOptions,
|
|||
let mut optional_services = vec!();
|
||||
if let Some(ref opt_services) = options.optionalServices {
|
||||
for opt_service in opt_services {
|
||||
optional_services.push(try!(BluetoothUUID::GetService(global, opt_service.clone())).to_string());
|
||||
let uuid = try!(BluetoothUUID::GetService(global, opt_service.clone())).to_string();
|
||||
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
|
||||
return Err(Security)
|
||||
}
|
||||
optional_services.push(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* 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::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
|
||||
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding;
|
||||
|
@ -9,7 +10,7 @@ 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, Type};
|
||||
use dom::bindings::error::Error::{Network, Security, Type};
|
||||
use dom::bindings::error::{Fallible, ErrorResult};
|
||||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::{JS, MutHeap, Root};
|
||||
|
@ -93,6 +94,9 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
|
|||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor
|
||||
fn GetDescriptor(&self, descriptor: BluetoothDescriptorUUID) -> Fallible<Root<BluetoothRemoteGATTDescriptor>> {
|
||||
let uuid = try!(BluetoothUUID::GetDescriptor(self.global().r(), descriptor)).to_string();
|
||||
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
|
||||
return Err(Security)
|
||||
}
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
self.get_bluetooth_thread().send(
|
||||
BluetoothMethodMsg::GetDescriptor(self.get_instance_id(), uuid, sender)).unwrap();
|
||||
|
@ -116,7 +120,12 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
|
|||
-> Fallible<Vec<Root<BluetoothRemoteGATTDescriptor>>> {
|
||||
let mut uuid: Option<String> = None;
|
||||
if let Some(d) = descriptor {
|
||||
uuid = Some(try!(BluetoothUUID::GetDescriptor(self.global().r(), d)).to_string())
|
||||
uuid = Some(try!(BluetoothUUID::GetDescriptor(self.global().r(), d)).to_string());
|
||||
if let Some(ref uuid) = uuid {
|
||||
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
|
||||
return Err(Security)
|
||||
}
|
||||
}
|
||||
};
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
self.get_bluetooth_thread().send(
|
||||
|
@ -144,6 +153,9 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
|
|||
|
||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-readvalue
|
||||
fn ReadValue(&self) -> Fallible<ByteString> {
|
||||
if uuid_is_blacklisted(self.uuid.as_ref(), Blacklist::Reads) {
|
||||
return Err(Security)
|
||||
}
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
if !self.Service().Device().Gatt().Connected() {
|
||||
return Err(Network)
|
||||
|
@ -165,6 +177,9 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris
|
|||
|
||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue
|
||||
fn WriteValue(&self, value: Vec<u8>) -> ErrorResult {
|
||||
if uuid_is_blacklisted(self.uuid.as_ref(), Blacklist::Writes) {
|
||||
return Err(Security)
|
||||
}
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
self.get_bluetooth_thread().send(
|
||||
BluetoothMethodMsg::WriteValue(self.get_instance_id(), value, sender)).unwrap();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* 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::cell::DOMRefCell;
|
||||
use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods;
|
||||
use dom::bindings::codegen::Bindings::BluetoothRemoteGATTCharacteristicBinding::
|
||||
|
@ -10,7 +11,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::{Type, Network};
|
||||
use dom::bindings::error::Error::{Network, Security, Type};
|
||||
use dom::bindings::error::{Fallible, ErrorResult};
|
||||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::{JS, MutHeap, Root};
|
||||
|
@ -85,6 +86,9 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
|
|||
|
||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-readvalue
|
||||
fn ReadValue(&self) -> Fallible<ByteString> {
|
||||
if uuid_is_blacklisted(self.uuid.as_ref(), Blacklist::Reads) {
|
||||
return Err(Security)
|
||||
}
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
if !self.Characteristic().Service().Device().Gatt().Connected() {
|
||||
return Err(Network)
|
||||
|
@ -106,6 +110,9 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor {
|
|||
|
||||
// https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattdescriptor-writevalue
|
||||
fn WriteValue(&self, value: Vec<u8>) -> ErrorResult {
|
||||
if uuid_is_blacklisted(self.uuid.as_ref(), Blacklist::Writes) {
|
||||
return Err(Security)
|
||||
}
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
self.get_bluetooth_thread().send(
|
||||
BluetoothMethodMsg::WriteValue(self.get_instance_id(), value, sender)).unwrap();
|
||||
|
|
|
@ -2,10 +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 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::Type;
|
||||
use dom::bindings::error::Error::{Security, Type};
|
||||
use dom::bindings::error::{Fallible, ErrorResult};
|
||||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::{JS, MutHeap, Root};
|
||||
|
@ -96,6 +97,9 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
|
|||
// 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) {
|
||||
return Err(Security)
|
||||
}
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
self.get_bluetooth_thread().send(
|
||||
BluetoothMethodMsg::GetPrimaryService(String::from(self.Device().Id()), uuid, sender)).unwrap();
|
||||
|
@ -120,7 +124,12 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer {
|
|||
-> Fallible<Vec<Root<BluetoothRemoteGATTService>>> {
|
||||
let mut uuid: Option<String> = None;
|
||||
if let Some(s) = service {
|
||||
uuid = Some(try!(BluetoothUUID::GetService(self.global().r(), s)).to_string())
|
||||
uuid = Some(try!(BluetoothUUID::GetService(self.global().r(), s)).to_string());
|
||||
if let Some(ref uuid) = uuid {
|
||||
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
|
||||
return Err(Security)
|
||||
}
|
||||
}
|
||||
};
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
self.get_bluetooth_thread().send(
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
* 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::Type;
|
||||
use dom::bindings::error::Error::{Security, Type};
|
||||
use dom::bindings::error::Fallible;
|
||||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::{JS, MutHeap, Root};
|
||||
|
@ -88,6 +89,9 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
|
|||
characteristic: BluetoothCharacteristicUUID)
|
||||
-> Fallible<Root<BluetoothRemoteGATTCharacteristic>> {
|
||||
let uuid = try!(BluetoothUUID::GetCharacteristic(self.global().r(), characteristic)).to_string();
|
||||
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
|
||||
return Err(Security)
|
||||
}
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
self.get_bluetooth_thread().send(
|
||||
BluetoothMethodMsg::GetCharacteristic(self.get_instance_id(), uuid, sender)).unwrap();
|
||||
|
@ -122,7 +126,12 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService {
|
|||
-> Fallible<Vec<Root<BluetoothRemoteGATTCharacteristic>>> {
|
||||
let mut uuid: Option<String> = None;
|
||||
if let Some(c) = characteristic {
|
||||
uuid = Some(try!(BluetoothUUID::GetCharacteristic(self.global().r(), c)).to_string())
|
||||
uuid = Some(try!(BluetoothUUID::GetCharacteristic(self.global().r(), c)).to_string());
|
||||
if let Some(ref uuid) = uuid {
|
||||
if uuid_is_blacklisted(uuid.as_ref(), Blacklist::All) {
|
||||
return Err(Security)
|
||||
}
|
||||
}
|
||||
};
|
||||
let mut characteristics = vec!();
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
|
|
|
@ -87,6 +87,7 @@ extern crate webrender_traits;
|
|||
extern crate websocket;
|
||||
extern crate xml5ever;
|
||||
|
||||
pub mod bluetooth_blacklist;
|
||||
pub mod clipboard_provider;
|
||||
pub mod cors;
|
||||
mod devtools;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue