diff options
24 files changed, 649 insertions, 33 deletions
diff --git a/components/atoms/static_atoms.txt b/components/atoms/static_atoms.txt index 1ddf07db553..e59c9cad809 100644 --- a/components/atoms/static_atoms.txt +++ b/components/atoms/static_atoms.txt @@ -65,3 +65,4 @@ fetch characteristicvaluechanged fullscreenchange fullscreenerror +gattserverdisconnected diff --git a/components/bluetooth/lib.rs b/components/bluetooth/lib.rs index 2d542868e02..8af1fab71da 100644 --- a/components/bluetooth/lib.rs +++ b/components/bluetooth/lib.rs @@ -247,6 +247,12 @@ impl BluetoothManager { BluetoothRequest::Test(data_set_name, sender) => { let _ = sender.send(self.test(data_set_name)); } + BluetoothRequest::SetRepresentedToNull(service_ids, characteristic_ids, descriptor_ids) => { + self.remove_ids_from_caches(service_ids, characteristic_ids, descriptor_ids) + } + BluetoothRequest::IsRepresentedDeviceNull(id, sender) => { + let _ = sender.send(!self.device_is_cached(&id)); + } BluetoothRequest::Exit => { break }, @@ -273,6 +279,26 @@ impl BluetoothManager { } } + fn remove_ids_from_caches(&mut self, + service_ids: Vec<String>, + characteristic_ids: Vec<String>, + descriptor_ids: Vec<String>) { + for id in service_ids { + self.cached_services.remove(&id); + self.service_to_device.remove(&id); + } + + for id in characteristic_ids { + self.cached_characteristics.remove(&id); + self.characteristic_to_service.remove(&id); + } + + for id in descriptor_ids { + self.cached_descriptors.remove(&id); + self.descriptor_to_characteristic.remove(&id); + } + } + // Adapter pub fn get_or_create_adapter(&mut self) -> Option<BluetoothAdapter> { @@ -613,20 +639,19 @@ impl BluetoothManager { } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-disconnect - fn gatt_server_disconnect(&mut self, device_id: String) -> BluetoothResult<bool> { + fn gatt_server_disconnect(&mut self, device_id: String) -> BluetoothResult<()> { let mut adapter = try!(self.get_adapter()); - match self.get_device(&mut adapter, &device_id) { Some(d) => { // Step 2. if !d.is_connected().unwrap_or(true) { - return Ok(false); + return Ok(()); } 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 Ok(false), + false => return Ok(()), } } return Err(BluetoothError::Network); diff --git a/components/bluetooth/test.rs b/components/bluetooth/test.rs index e2c6e639e82..b8f8a53750f 100644 --- a/components/bluetooth/test.rs +++ b/components/bluetooth/test.rs @@ -222,21 +222,23 @@ fn create_heart_rate_service(device: &BluetoothDevice, try!(create_characteristic_with_value(&heart_rate_service, HEART_RATE_MEASUREMENT_CHARACTERISTIC_UUID.to_owned(), vec![0])); - try!(heart_rate_measurement_characteristic.set_flags(vec![NOTIFY_FLAG.to_string()])); + try!(heart_rate_measurement_characteristic.set_flags(vec![NOTIFY_FLAG.to_string(), + READ_FLAG.to_string(), + WRITE_FLAG.to_string()])); // Body Sensor Location Characteristic 1 let body_sensor_location_characteristic_1 = try!(create_characteristic_with_value(&heart_rate_service, BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(), vec![49])); - try!(body_sensor_location_characteristic_1.set_flags(vec![READ_FLAG.to_string()])); + try!(body_sensor_location_characteristic_1.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])); // Body Sensor Location Characteristic 2 let body_sensor_location_characteristic_2 = try!(create_characteristic_with_value(&heart_rate_service, BODY_SENSOR_LOCATION_CHARACTERISTIC_UUID.to_owned(), vec![50])); - try!(body_sensor_location_characteristic_2.set_flags(vec![READ_FLAG.to_string()])); + try!(body_sensor_location_characteristic_2.set_flags(vec![READ_FLAG.to_string(), WRITE_FLAG.to_string()])); Ok(heart_rate_service) } diff --git a/components/bluetooth_traits/lib.rs b/components/bluetooth_traits/lib.rs index ede1c8ecdba..345425cc1d5 100644 --- a/components/bluetooth_traits/lib.rs +++ b/components/bluetooth_traits/lib.rs @@ -85,12 +85,14 @@ pub type BluetoothResponseResult = Result<BluetoothResponse, BluetoothError>; pub enum BluetoothRequest { RequestDevice(RequestDeviceoptions, IpcSender<BluetoothResponseResult>), GATTServerConnect(String, IpcSender<BluetoothResponseResult>), - GATTServerDisconnect(String, IpcSender<BluetoothResult<bool>>), + GATTServerDisconnect(String, IpcSender<BluetoothResult<()>>), GetGATTChildren(String, Option<String>, bool, GATTType, IpcSender<BluetoothResponseResult>), ReadValue(String, IpcSender<BluetoothResponseResult>), WriteValue(String, Vec<u8>, IpcSender<BluetoothResponseResult>), EnableNotification(String, bool, IpcSender<BluetoothResponseResult>), WatchAdvertisements(String, IpcSender<BluetoothResponseResult>), + SetRepresentedToNull(Vec<String>, Vec<String>, Vec<String>), + IsRepresentedDeviceNull(String, IpcSender<bool>), Test(String, IpcSender<BluetoothResult<()>>), Exit, } diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs index d2b3ced25fe..fdc248c360f 100644 --- a/components/script/dom/bluetooth.rs +++ b/components/script/dom/bluetooth.rs @@ -106,6 +106,10 @@ impl Bluetooth { self.global().as_window().bluetooth_thread() } + pub fn get_device_map(&self) -> &DOMRefCell<HashMap<String, MutJS<BluetoothDevice>>> { + &self.device_instance_map + } + // https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices fn request_bluetooth_devices(&self, p: &Rc<Promise>, diff --git a/components/script/dom/bluetoothdevice.rs b/components/script/dom/bluetoothdevice.rs index d3d66b66440..d56970c0d98 100644 --- a/components/script/dom/bluetoothdevice.rs +++ b/components/script/dom/bluetoothdevice.rs @@ -10,6 +10,8 @@ use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMet use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::error::Error; +use dom::bindings::error::ErrorResult; +use dom::bindings::inheritance::Castable; use dom::bindings::js::{MutJS, MutNullableJS, Root}; use dom::bindings::reflector::{DomObject, reflect_dom_object}; use dom::bindings::str::DOMString; @@ -22,7 +24,7 @@ use dom::bluetoothremotegattservice::BluetoothRemoteGATTService; use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; use dom::promise::Promise; -use ipc_channel::ipc::IpcSender; +use ipc_channel::ipc::{self, IpcSender}; use js::jsapi::JSContext; use std::cell::Cell; use std::collections::HashMap; @@ -72,6 +74,10 @@ impl BluetoothDevice { BluetoothDeviceBinding::Wrap) } + fn get_context(&self) -> Root<Bluetooth> { + self.context.get() + } + pub fn get_or_create_service(&self, service: &BluetoothServiceMsg, server: &BluetoothRemoteGATTServer) @@ -119,6 +125,13 @@ impl BluetoothDevice { return bt_characteristic; } + pub fn is_represented_device_null(&self) -> bool { + let (sender, receiver) = ipc::channel().unwrap(); + self.get_bluetooth_thread().send( + BluetoothRequest::IsRepresentedDeviceNull(self.Id().to_string(), sender)).unwrap(); + receiver.recv().unwrap() + } + pub fn get_or_create_descriptor(&self, descriptor: &BluetoothDescriptorMsg, characteristic: &BluetoothRemoteGATTCharacteristic) @@ -139,6 +152,60 @@ impl BluetoothDevice { fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> { self.global().as_window().bluetooth_thread() } + + // https://webbluetoothcg.github.io/web-bluetooth/#clean-up-the-disconnected-device + #[allow(unrooted_must_root)] + pub fn clean_up_disconnected_device(&self) { + // Step 1. + self.Gatt().set_connected(false); + + // TODO: Step 2: Implement activeAlgorithms internal slot for BluetoothRemoteGATTServer. + + // Step 3: We don't need `context`, we get the attributeInstanceMap from the device. + // https://github.com/WebBluetoothCG/web-bluetooth/issues/330 + + // Step 4. + let mut service_map = self.attribute_instance_map.0.borrow_mut(); + let service_ids = service_map.drain().map(|(id, _)| id).collect(); + + let mut characteristic_map = self.attribute_instance_map.1.borrow_mut(); + let characteristic_ids = characteristic_map.drain().map(|(id, _)| id).collect(); + + let mut descriptor_map = self.attribute_instance_map.2.borrow_mut(); + let descriptor_ids = descriptor_map.drain().map(|(id, _)| id).collect(); + + // Step 5, 6.4, 7. + // TODO: Step 6: Implement `active notification context set` for BluetoothRemoteGATTCharacteristic. + let _ = self.get_bluetooth_thread().send( + BluetoothRequest::SetRepresentedToNull(service_ids, characteristic_ids, descriptor_ids)); + + // Step 8. + self.upcast::<EventTarget>().fire_bubbling_event(atom!("gattserverdisconnected")); + } + + // https://webbluetoothcg.github.io/web-bluetooth/#garbage-collect-the-connection + #[allow(unrooted_must_root)] + pub fn garbage_collect_the_connection(&self) -> ErrorResult { + // Step 1: TODO: Check if other systems using this device. + + // Step 2. + let context = self.get_context(); + for (id, device) in context.get_device_map().borrow().iter() { + // Step 2.1 - 2.2. + if id == &self.Id().to_string() { + if device.get().Gatt().Connected() { + return Ok(()); + } + // TODO: Step 2.3: Implement activeAlgorithms internal slot for BluetoothRemoteGATTServer. + } + } + + // Step 3. + let (sender, receiver) = ipc::channel().unwrap(); + self.get_bluetooth_thread().send( + BluetoothRequest::GATTServerDisconnect(String::from(self.Id()), sender)).unwrap(); + receiver.recv().unwrap().map_err(Error::from) + } } impl BluetoothDeviceMethods for BluetoothDevice { diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs index ad7833af908..e81aae08abe 100644 --- a/components/script/dom/bluetoothremotegattserver.rs +++ b/components/script/dom/bluetoothremotegattserver.rs @@ -15,7 +15,7 @@ use dom::bluetoothdevice::BluetoothDevice; use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID}; use dom::globalscope::GlobalScope; use dom::promise::Promise; -use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::ipc::IpcSender; use js::jsapi::JSContext; use std::cell::Cell; use std::rc::Rc; @@ -46,6 +46,10 @@ impl BluetoothRemoteGATTServer { fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> { self.global().as_window().bluetooth_thread() } + + pub fn set_connected(&self, connected: bool) { + self.connected.set(connected); + } } impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { @@ -86,27 +90,14 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { // Step 2. if !self.Connected() { - return Ok(()); + return Ok(()) } - let (sender, receiver) = ipc::channel().unwrap(); - self.get_bluetooth_thread().send( - BluetoothRequest::GATTServerDisconnect(String::from(self.Device().Id()), sender)).unwrap(); - let server = receiver.recv().unwrap(); - // TODO: Step 3: Implement the `clean up the disconnected device` algorithm. + // Step 3. + self.Device().clean_up_disconnected_device(); - // TODO: Step 4: Implement representedDevice internal slot for BluetoothDevice. - - // TODO: Step 5: Implement the `garbage-collect the connection` algorithm. - match server { - Ok(connected) => { - self.connected.set(connected); - Ok(()) - }, - Err(error) => { - Err(Error::from(error)) - }, - } + // Step 4 - 5: + self.Device().garbage_collect_the_connection() } #[allow(unrooted_must_root)] @@ -134,6 +125,14 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTServer { match response { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect BluetoothResponse::GATTServerConnect(connected) => { + // Step 5.2.3 + if self.Device().is_represented_device_null() { + if let Err(e) = self.Device().garbage_collect_the_connection() { + return promise.reject_error(promise_cx, Error::from(e)); + } + return promise.reject_error(promise_cx, Error::Network); + } + // Step 5.2.4. self.connected.set(connected); diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index ca2f3db7589..25e032f876a 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -6794,6 +6794,12 @@ "url": "/_mozilla/mozilla/bluetooth/disconnect/disconnect-twice-in-a-row.html" } ], + "mozilla/bluetooth/disconnect/event-is-fired.html": [ + { + "path": "mozilla/bluetooth/disconnect/event-is-fired.html", + "url": "/_mozilla/mozilla/bluetooth/disconnect/event-is-fired.html" + } + ], "mozilla/bluetooth/getCharacteristic/blocklisted-characteristic.html": [ { "path": "mozilla/bluetooth/getCharacteristic/blocklisted-characteristic.html", @@ -6830,6 +6836,18 @@ "url": "/_mozilla/mozilla/bluetooth/getCharacteristic/disconnect-called-during.html" } ], + "mozilla/bluetooth/getCharacteristic/disconnect-invalidates-object.html": [ + { + "path": "mozilla/bluetooth/getCharacteristic/disconnect-invalidates-object.html", + "url": "/_mozilla/mozilla/bluetooth/getCharacteristic/disconnect-invalidates-object.html" + } + ], + "mozilla/bluetooth/getCharacteristic/get-different-characteristic-after-reconnection.html": [ + { + "path": "mozilla/bluetooth/getCharacteristic/get-different-characteristic-after-reconnection.html", + "url": "/_mozilla/mozilla/bluetooth/getCharacteristic/get-different-characteristic-after-reconnection.html" + } + ], "mozilla/bluetooth/getCharacteristic/get-same-characteristic.html": [ { "path": "mozilla/bluetooth/getCharacteristic/get-same-characteristic.html", @@ -6926,6 +6944,18 @@ "url": "/_mozilla/mozilla/bluetooth/getCharacteristics/disconnect-called-during.html" } ], + "mozilla/bluetooth/getCharacteristics/disconnect-invalidates-objects.html": [ + { + "path": "mozilla/bluetooth/getCharacteristics/disconnect-invalidates-objects.html", + "url": "/_mozilla/mozilla/bluetooth/getCharacteristics/disconnect-invalidates-objects.html" + } + ], + "mozilla/bluetooth/getCharacteristics/get-different-characteristics-after-reconnection.html": [ + { + "path": "mozilla/bluetooth/getCharacteristics/get-different-characteristics-after-reconnection.html", + "url": "/_mozilla/mozilla/bluetooth/getCharacteristics/get-different-characteristics-after-reconnection.html" + } + ], "mozilla/bluetooth/getCharacteristics/get-same-characteristics.html": [ { "path": "mozilla/bluetooth/getCharacteristics/get-same-characteristics.html", @@ -6992,6 +7022,18 @@ "url": "/_mozilla/mozilla/bluetooth/getDescriptor/disconnect-called-during.html" } ], + "mozilla/bluetooth/getDescriptor/disconnect-invalidates-object.html": [ + { + "path": "mozilla/bluetooth/getDescriptor/disconnect-invalidates-object.html", + "url": "/_mozilla/mozilla/bluetooth/getDescriptor/disconnect-invalidates-object.html" + } + ], + "mozilla/bluetooth/getDescriptor/get-different-descriptor-after-reconnection.html": [ + { + "path": "mozilla/bluetooth/getDescriptor/get-different-descriptor-after-reconnection.html", + "url": "/_mozilla/mozilla/bluetooth/getDescriptor/get-different-descriptor-after-reconnection.html" + } + ], "mozilla/bluetooth/getDescriptor/get-same-descriptor.html": [ { "path": "mozilla/bluetooth/getDescriptor/get-same-descriptor.html", @@ -7094,6 +7136,18 @@ "url": "/_mozilla/mozilla/bluetooth/getDescriptors/disconnect-called-during.html" } ], + "mozilla/bluetooth/getDescriptors/disconnect-invalidates-objects.html": [ + { + "path": "mozilla/bluetooth/getDescriptors/disconnect-invalidates-objects.html", + "url": "/_mozilla/mozilla/bluetooth/getDescriptors/disconnect-invalidates-objects.html" + } + ], + "mozilla/bluetooth/getDescriptors/get-different-descriptors-after-reconnection.html": [ + { + "path": "mozilla/bluetooth/getDescriptors/get-different-descriptors-after-reconnection.html", + "url": "/_mozilla/mozilla/bluetooth/getDescriptors/get-different-descriptors-after-reconnection.html" + } + ], "mozilla/bluetooth/getDescriptors/get-same-descriptors.html": [ { "path": "mozilla/bluetooth/getDescriptors/get-same-descriptors.html", @@ -7124,12 +7178,24 @@ "url": "/_mozilla/mozilla/bluetooth/getPrimaryService/disconnect-called-during.html" } ], + "mozilla/bluetooth/getPrimaryService/disconnect-invalidates-object.html": [ + { + "path": "mozilla/bluetooth/getPrimaryService/disconnect-invalidates-object.html", + "url": "/_mozilla/mozilla/bluetooth/getPrimaryService/disconnect-invalidates-object.html" + } + ], "mozilla/bluetooth/getPrimaryService/disconnected-device.html": [ { "path": "mozilla/bluetooth/getPrimaryService/disconnected-device.html", "url": "/_mozilla/mozilla/bluetooth/getPrimaryService/disconnected-device.html" } ], + "mozilla/bluetooth/getPrimaryService/get-different-service-after-reconnection.html": [ + { + "path": "mozilla/bluetooth/getPrimaryService/get-different-service-after-reconnection.html", + "url": "/_mozilla/mozilla/bluetooth/getPrimaryService/get-different-service-after-reconnection.html" + } + ], "mozilla/bluetooth/getPrimaryService/get-same-service.html": [ { "path": "mozilla/bluetooth/getPrimaryService/get-same-service.html", @@ -7220,6 +7286,12 @@ "url": "/_mozilla/mozilla/bluetooth/getPrimaryServices/disconnect-called-during.html" } ], + "mozilla/bluetooth/getPrimaryServices/disconnect-invalidates-objects.html": [ + { + "path": "mozilla/bluetooth/getPrimaryServices/disconnect-invalidates-objects.html", + "url": "/_mozilla/mozilla/bluetooth/getPrimaryServices/disconnect-invalidates-objects.html" + } + ], "mozilla/bluetooth/getPrimaryServices/disconnected-device-with-uuid.html": [ { "path": "mozilla/bluetooth/getPrimaryServices/disconnected-device-with-uuid.html", @@ -7232,6 +7304,12 @@ "url": "/_mozilla/mozilla/bluetooth/getPrimaryServices/disconnected-device.html" } ], + "mozilla/bluetooth/getPrimaryServices/get-different-services-after-reconnection.html": [ + { + "path": "mozilla/bluetooth/getPrimaryServices/get-different-services-after-reconnection.html", + "url": "/_mozilla/mozilla/bluetooth/getPrimaryServices/get-different-services-after-reconnection.html" + } + ], "mozilla/bluetooth/getPrimaryServices/get-same-service.html": [ { "path": "mozilla/bluetooth/getPrimaryServices/get-same-service.html", diff --git a/tests/wpt/mozilla/meta/mozilla/bluetooth/getCharacteristic/disconnect-invalidates-object.html.ini b/tests/wpt/mozilla/meta/mozilla/bluetooth/getCharacteristic/disconnect-invalidates-object.html.ini new file mode 100644 index 00000000000..5e864acb72f --- /dev/null +++ b/tests/wpt/mozilla/meta/mozilla/bluetooth/getCharacteristic/disconnect-invalidates-object.html.ini @@ -0,0 +1,5 @@ +[disconnect-invalidates-object.html] + type: testharness + [Calls on a characteristic after we disconnect and connect again. Should reject with InvalidStateError.] + expected: FAIL + diff --git a/tests/wpt/mozilla/meta/mozilla/bluetooth/getCharacteristics/disconnect-invalidates-objects.html.ini b/tests/wpt/mozilla/meta/mozilla/bluetooth/getCharacteristics/disconnect-invalidates-objects.html.ini new file mode 100644 index 00000000000..03863760106 --- /dev/null +++ b/tests/wpt/mozilla/meta/mozilla/bluetooth/getCharacteristics/disconnect-invalidates-objects.html.ini @@ -0,0 +1,5 @@ +[disconnect-invalidates-objects.html] + type: testharness + [Calls on characteristics after we disconnect and connect again. Should reject with InvalidStateError.] + expected: FAIL + diff --git a/tests/wpt/mozilla/meta/mozilla/bluetooth/stopNotifications/disconnect-called-before.html.ini b/tests/wpt/mozilla/meta/mozilla/bluetooth/stopNotifications/disconnect-called-before.html.ini deleted file mode 100644 index af249ef0167..00000000000 --- a/tests/wpt/mozilla/meta/mozilla/bluetooth/stopNotifications/disconnect-called-before.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[disconnect-called-before.html] - type: testharness - [disconnect() called before stopNotifications. Reject with InvalidStateError.] - expected: FAIL - diff --git a/tests/wpt/mozilla/tests/mozilla/bluetooth/disconnect/event-is-fired.html b/tests/wpt/mozilla/tests/mozilla/bluetooth/disconnect/event-is-fired.html new file mode 100644 index 00000000000..67e146fc956 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/bluetooth/disconnect/event-is-fired.html @@ -0,0 +1,33 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/_mozilla/mozilla/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(() => { + window.testRunner.setBluetoothMockDataSet(adapter_type.heart_rate); + return window.navigator.bluetooth.requestDevice({ + filters: [{services: [heart_rate.name]}], + optionalServices: [generic_access.name] + }) + .then(device => { + return device.gatt.connect() + .then(gattServer => { + let event = 'gattserverdisconnected'; + let disconnected = new Promise((resolve, reject) => { + let event_listener = (e) => { + device.removeEventListener(event, event_listener); + resolve(e); + }; + device.addEventListener(event, event_listener); + }); + gattServer.disconnect(); + return disconnected + }) + .then(disconnected => { + assert_equals(disconnected.target.name, mock_device_name.heart_rate); + assert_true(disconnected.bubbles); + }); + }); +}, 'A device disconnecting while connected should fire the gattserverdisconnected event.'); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/bluetooth/getCharacteristic/disconnect-invalidates-object.html b/tests/wpt/mozilla/tests/mozilla/bluetooth/getCharacteristic/disconnect-invalidates-object.html new file mode 100644 index 00000000000..c1e6a864b0c --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/bluetooth/getCharacteristic/disconnect-invalidates-object.html @@ -0,0 +1,36 @@ +<!doctype html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/_mozilla/mozilla/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(t => { + window.testRunner.setBluetoothMockDataSet(adapter_type.two_heart_rate); + return window.navigator.bluetooth.requestDevice({ + filters: [{services: [generic_access.name]}] + }) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService(generic_access.name) + .then(service => service.getCharacteristic(device_name.name)) + .then(c => { + let characteristic = c; + gattServer.disconnect(); + return gattServer.connect() + .then(() => characteristic); + }); + }) + .then(characteristic => { + let promises = []; + promises.push(promise_rejects(t, 'InvalidStateError', characteristic.getDescriptor(number_of_digitals.name))); + promises.push(promise_rejects(t, 'InvalidStateError', characteristic.getDescriptors(number_of_digitals.name))); + promises.push(promise_rejects(t, 'InvalidStateError', characteristic.getDescriptors())); + promises.push(promise_rejects(t, 'InvalidStateError', characteristic.readValue())); + promises.push(promise_rejects(t, 'InvalidStateError', characteristic.writeValue(new Uint8Array(1)))); + promises.push(promise_rejects(t, 'InvalidStateError', characteristic.startNotifications())); + promises.push(promise_rejects(t, 'InvalidStateError', characteristic.stopNotifications())); + return Promise.all(promises); + }); +}, 'Calls on a characteristic after we disconnect and connect again. Should reject with InvalidStateError.'); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/bluetooth/getCharacteristic/get-different-characteristic-after-reconnection.html b/tests/wpt/mozilla/tests/mozilla/bluetooth/getCharacteristic/get-different-characteristic-after-reconnection.html new file mode 100644 index 00000000000..b65a9a27836 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/bluetooth/getCharacteristic/get-different-characteristic-after-reconnection.html @@ -0,0 +1,29 @@ +<!doctype html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/_mozilla/mozilla/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(t => { + window.testRunner.setBluetoothMockDataSet(adapter_type.two_heart_rate); + return window.navigator.bluetooth.requestDevice({ + filters: [{services: [generic_access.name]}] + }) + .then(device => device.gatt.connect()) + .then(gattServer => { + let characteristic1; + return gattServer.getPrimaryService(generic_access.name) + .then(service => service.getCharacteristic(device_name.name)) + .then(characteristic => characteristic1 = characteristic) + .then(() => gattServer.disconnect()) + .then(() => gattServer.connect()) + .then(() => gattServer.getPrimaryService(generic_access.name)) + .then(service => service.getCharacteristic(device_name.name)) + .then(characteristic2 => [characteristic1, characteristic2]) + }) + .then(characteristics_array => { + assert_not_equals(characteristics_array[0], characteristics_array[1]); + }); +}, 'Calls to getCharacteristic after a disconnection should return a different object.'); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/bluetooth/getCharacteristics/disconnect-invalidates-objects.html b/tests/wpt/mozilla/tests/mozilla/bluetooth/getCharacteristics/disconnect-invalidates-objects.html new file mode 100644 index 00000000000..adf607a0954 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/bluetooth/getCharacteristics/disconnect-invalidates-objects.html @@ -0,0 +1,39 @@ +<!doctype html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/_mozilla/mozilla/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(t => { + window.testRunner.setBluetoothMockDataSet(adapter_type.heart_rate); + return window.navigator.bluetooth.requestDevice({ + filters: [{services: [heart_rate.name]}] + }) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService(heart_rate.name) + .then(service => service.getCharacteristics()) + .then(c => { + let characteristics = c; + assert_greater_than(characteristics.length, 1); + gattServer.disconnect(); + return gattServer.connect() + .then(() => characteristics); + }); + }) + .then(characteristics => { + let promises = []; + for (let characteristic of characteristics) { + promises.push(promise_rejects(t, 'InvalidStateError', characteristic.getDescriptor(number_of_digitals.name))); + promises.push(promise_rejects(t, 'InvalidStateError', characteristic.getDescriptors(number_of_digitals.name))); + promises.push(promise_rejects(t, 'InvalidStateError', characteristic.getDescriptors())); + promises.push(promise_rejects(t, 'InvalidStateError', characteristic.readValue())); + promises.push(promise_rejects(t, 'InvalidStateError', characteristic.writeValue(new Uint8Array(1)))); + promises.push(promise_rejects(t, 'InvalidStateError', characteristic.startNotifications())); + promises.push(promise_rejects(t, 'InvalidStateError', characteristic.stopNotifications())); + } + return Promise.all(promises); + }); +}, 'Calls on characteristics after we disconnect and connect again. Should reject with InvalidStateError.'); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/bluetooth/getCharacteristics/get-different-characteristics-after-reconnection.html b/tests/wpt/mozilla/tests/mozilla/bluetooth/getCharacteristics/get-different-characteristics-after-reconnection.html new file mode 100644 index 00000000000..0e93083a1cb --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/bluetooth/getCharacteristics/get-different-characteristics-after-reconnection.html @@ -0,0 +1,35 @@ +<!doctype html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/_mozilla/mozilla/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(t => { + window.testRunner.setBluetoothMockDataSet(adapter_type.heart_rate); + return window.navigator.bluetooth.requestDevice({ + filters: [{services: [heart_rate.name]}], + }) + .then(device => device.gatt.connect()) + .then(gattServer => { + let characteristics1; + return gattServer.getPrimaryService(heart_rate.name) + .then(service => service.getCharacteristics()) + .then(characteristics => characteristics1 = characteristics) + .then(() => gattServer.disconnect()) + .then(() => gattServer.connect()) + .then(() => gattServer.getPrimaryService(heart_rate.name)) + .then(service => service.getCharacteristics()) + .then(characteristics2 => [characteristics1, characteristics2]) + }) + .then(characteristics_arrays => { + for (let i = 1; i < characteristics_arrays.length; i++) { + assert_equals(characteristics_arrays[0].length, characteristics_arrays[i].length); + } + let base_set = new Set(characteristics_arrays.shift()); + for (let characteristics of characteristics_arrays) { + characteristics.forEach(characteristic => assert_false(base_set.has(characteristic))); + } + }); +}, 'Calls to getCharacteristics after a disconnection should return different objects.'); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/bluetooth/getDescriptor/disconnect-invalidates-object.html b/tests/wpt/mozilla/tests/mozilla/bluetooth/getDescriptor/disconnect-invalidates-object.html new file mode 100644 index 00000000000..b99e877159b --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/bluetooth/getDescriptor/disconnect-invalidates-object.html @@ -0,0 +1,32 @@ +<!doctype html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/_mozilla/mozilla/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(t => { + window.testRunner.setBluetoothMockDataSet(adapter_type.heart_rate); + return window.navigator.bluetooth.requestDevice({ + filters: [{services: [generic_access.name]}] + }) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService(generic_access.name) + .then(service => service.getCharacteristic(device_name.name)) + .then(characteristic => characteristic.getDescriptor(number_of_digitals.name)) + .then(d => { + let descriptor = d; + gattServer.disconnect(); + return gattServer.connect() + .then(() => descriptor); + }); + }) + .then(descriptor => { + let promises = []; + promises.push(promise_rejects(t, 'InvalidStateError', descriptor.readValue())); + promises.push(promise_rejects(t, 'InvalidStateError', descriptor.writeValue(new Uint8Array(1)))); + return Promise.all(promises); + }); +}, 'Calls on a descriptor after we disconnect and connect again. Should reject with InvalidStateError.'); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/bluetooth/getDescriptor/get-different-descriptor-after-reconnection.html b/tests/wpt/mozilla/tests/mozilla/bluetooth/getDescriptor/get-different-descriptor-after-reconnection.html new file mode 100644 index 00000000000..ea7559415d4 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/bluetooth/getDescriptor/get-different-descriptor-after-reconnection.html @@ -0,0 +1,31 @@ +<!doctype html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/_mozilla/mozilla/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(t => { + window.testRunner.setBluetoothMockDataSet(adapter_type.two_heart_rate); + return window.navigator.bluetooth.requestDevice({ + filters: [{services: [generic_access.name]}] + }) + .then(device => device.gatt.connect()) + .then(gattServer => { + let descriptor1; + return gattServer.getPrimaryService(generic_access.name) + .then(service => service.getCharacteristic(device_name.name)) + .then(characteristic => characteristic.getDescriptor(number_of_digitals.name)) + .then(descriptor => descriptor1 = descriptor) + .then(() => gattServer.disconnect()) + .then(() => gattServer.connect()) + .then(() => gattServer.getPrimaryService(generic_access.name)) + .then(service => service.getCharacteristic(device_name.name)) + .then(characteristic => characteristic.getDescriptor(number_of_digitals.name)) + .then(descriptor2 => [descriptor1, descriptor2]) + }) + .then(descriptors_array => { + assert_not_equals(descriptors_array[0], descriptors_array[1]); + }); +}, 'Calls to getDescriptor after a disconnection should return a different object.'); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/bluetooth/getDescriptors/disconnect-invalidates-objects.html b/tests/wpt/mozilla/tests/mozilla/bluetooth/getDescriptors/disconnect-invalidates-objects.html new file mode 100644 index 00000000000..8f912b06755 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/bluetooth/getDescriptors/disconnect-invalidates-objects.html @@ -0,0 +1,35 @@ +<!doctype html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/_mozilla/mozilla/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(t => { + window.testRunner.setBluetoothMockDataSet(adapter_type.heart_rate); + return window.navigator.bluetooth.requestDevice({ + filters: [{services: [generic_access.name]}] + }) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService(generic_access.name) + .then(service => service.getCharacteristic(device_name.name)) + .then(characteristic => characteristic.getDescriptors()) + .then(d => { + let descriptors = d; + gattServer.disconnect(); + return gattServer.connect() + .then(() => descriptors); + }); + }) + .then(descriptors => { + let promises = []; + for (let descriptor of descriptors) { + promises.push(promise_rejects(t, 'InvalidStateError', descriptor.readValue())); + if (descriptor.uuid != client_characteristic_configuration.uuid) + promises.push(promise_rejects(t, 'InvalidStateError', descriptor.writeValue(new Uint8Array(1)))); + } + return Promise.all(promises); + }); +}, 'Calls on descriptors after we disconnect and connect again. Should reject with InvalidStateError.'); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/bluetooth/getDescriptors/get-different-descriptors-after-reconnection.html b/tests/wpt/mozilla/tests/mozilla/bluetooth/getDescriptors/get-different-descriptors-after-reconnection.html new file mode 100644 index 00000000000..4a5ea15f96c --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/bluetooth/getDescriptors/get-different-descriptors-after-reconnection.html @@ -0,0 +1,37 @@ +<!doctype html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/_mozilla/mozilla/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(t => { + window.testRunner.setBluetoothMockDataSet(adapter_type.two_heart_rate); + return window.navigator.bluetooth.requestDevice({ + filters: [{services: [generic_access.name]}] + }) + .then(device => device.gatt.connect()) + .then(gattServer => { + let descriptors1; + return gattServer.getPrimaryService(generic_access.name) + .then(service => service.getCharacteristic(device_name.name)) + .then(characteristic => characteristic.getDescriptors(number_of_digitals.name)) + .then(descriptors => descriptors1 = descriptors) + .then(() => gattServer.disconnect()) + .then(() => gattServer.connect()) + .then(() => gattServer.getPrimaryService(generic_access.name)) + .then(service => service.getCharacteristic(device_name.name)) + .then(characteristic => characteristic.getDescriptors(number_of_digitals.name)) + .then(descriptors2 => [descriptors1, descriptors2]) + }) + .then(descriptors_arrays => { + for (let i = 1; i < descriptors_arrays.length; i++) { + assert_equals(descriptors_arrays[0].length, descriptors_arrays[i].length); + } + let base_set = new Set(descriptors_arrays.shift()); + for (let descriptors of descriptors_arrays) { + descriptors.forEach(descriptor => assert_false(base_set.has(descriptor))); + } + }); +}, 'Calls to getDescriptors after a disconnection should return a different object.'); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/bluetooth/getPrimaryService/disconnect-invalidates-object.html b/tests/wpt/mozilla/tests/mozilla/bluetooth/getPrimaryService/disconnect-invalidates-object.html new file mode 100644 index 00000000000..a0254ee32ce --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/bluetooth/getPrimaryService/disconnect-invalidates-object.html @@ -0,0 +1,31 @@ +<!doctype html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/_mozilla/mozilla/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(t => { + window.testRunner.setBluetoothMockDataSet(adapter_type.two_heart_rate); + return window.navigator.bluetooth.requestDevice({ + filters: [{services: [heart_rate.name]}] + }) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryService(heart_rate.name) + .then(s => { + let service = s; + gattServer.disconnect(); + return gattServer.connect() + .then(() => service); + }); + }) + .then(service => { + let promises = []; + promises.push(promise_rejects(t, 'InvalidStateError', service.getCharacteristic(body_sensor_location.name))); + promises.push(promise_rejects(t, 'InvalidStateError', service.getCharacteristics(body_sensor_location.name))); + promises.push(promise_rejects(t, 'InvalidStateError', service.getCharacteristics())); + return Promise.all(promises); + }); +}, 'Calls on a service after we disconnect and connect again. Should reject with InvalidStateError.'); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/bluetooth/getPrimaryService/get-different-service-after-reconnection.html b/tests/wpt/mozilla/tests/mozilla/bluetooth/getPrimaryService/get-different-service-after-reconnection.html new file mode 100644 index 00000000000..4f6e2bbc92a --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/bluetooth/getPrimaryService/get-different-service-after-reconnection.html @@ -0,0 +1,27 @@ +<!doctype html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/_mozilla/mozilla/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(t => { + window.testRunner.setBluetoothMockDataSet(adapter_type.two_heart_rate); + return window.navigator.bluetooth.requestDevice({ + filters: [{services: [generic_access.name]}] + }) + .then(device => device.gatt.connect()) + .then(gattServer => { + let service1; + return gattServer.getPrimaryService(generic_access.name) + .then(service => service1 = service) + .then(() => gattServer.disconnect()) + .then(() => gattServer.connect()) + .then(() => gattServer.getPrimaryService(generic_access.name)) + .then(service2 => [service1, service2]) + }) + .then(services_array => { + assert_not_equals(services_array[0], services_array[1]); + }); +}, 'Calls to getPrimaryService after a disconnection should return a different object.'); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/bluetooth/getPrimaryServices/disconnect-invalidates-objects.html b/tests/wpt/mozilla/tests/mozilla/bluetooth/getPrimaryServices/disconnect-invalidates-objects.html new file mode 100644 index 00000000000..6f07ab81d99 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/bluetooth/getPrimaryServices/disconnect-invalidates-objects.html @@ -0,0 +1,34 @@ +<!doctype html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/_mozilla/mozilla/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(t => { + window.testRunner.setBluetoothMockDataSet(adapter_type.two_heart_rate); + return window.navigator.bluetooth.requestDevice({ + filters: [{services: [heart_rate.name]}] + }) + .then(device => device.gatt.connect()) + .then(gattServer => { + return gattServer.getPrimaryServices() + .then(s => { + let services = s; + assert_greater_than(services.length, 1); + gattServer.disconnect(); + return gattServer.connect() + .then(() => services); + }); + }) + .then(services => { + let promises = []; + for (let service of services) { + promises.push(promise_rejects(t, 'InvalidStateError', service.getCharacteristic(body_sensor_location.name))); + promises.push(promise_rejects(t, 'InvalidStateError', service.getCharacteristics(body_sensor_location.name))); + promises.push(promise_rejects(t, 'InvalidStateError', service.getCharacteristics())); + } + return Promise.all(promises); + }); +}, 'Calls on services after we disconnect and connect again. Should reject with InvalidStateError.'); +</script> diff --git a/tests/wpt/mozilla/tests/mozilla/bluetooth/getPrimaryServices/get-different-services-after-reconnection.html b/tests/wpt/mozilla/tests/mozilla/bluetooth/getPrimaryServices/get-different-services-after-reconnection.html new file mode 100644 index 00000000000..2ef3da7730d --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/bluetooth/getPrimaryServices/get-different-services-after-reconnection.html @@ -0,0 +1,34 @@ +<!doctype html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/_mozilla/mozilla/bluetooth/bluetooth-helpers.js"></script> +<script> +'use strict'; +promise_test(t => { + window.testRunner.setBluetoothMockDataSet(adapter_type.two_heart_rate); + return window.navigator.bluetooth.requestDevice({ + filters: [{services: [heart_rate.name]}], + optionalServices: [generic_access.name] + }) + .then(device => device.gatt.connect()) + .then(gattServer => { + let services1; + return gattServer.getPrimaryServices() + .then(services => services1 = services) + .then(() => gattServer.disconnect()) + .then(() => gattServer.connect()) + .then(() => gattServer.getPrimaryServices()) + .then(services2 => [services1, services2]) + }) + .then(services_arrays => { + for (let i = 1; i < services_arrays.length; i++) { + assert_equals(services_arrays[0].length, services_arrays[i].length); + } + let base_set = new Set(services_arrays.shift()); + for (let services of services_arrays) { + services.forEach(service => assert_false(base_set.has(service))); + } + }); +}, 'Calls to getPrimaryServices after a disconnection should return different objects.'); +</script> |