[web-bluetooth] Generate 'characteristicvaluechanged' events without waiting for a CCCD update (#514)

reillyeon has just created a new issue for https://github.com/WebBluetoothCG/web-bluetooth:

== Generate 'characteristicvaluechanged' events without waiting for a CCCD update ==
In [this StackOverflow question](https://stackoverflow.com/questions/63757642/webbluetooth-gatt-characteric-notification-setup-too-slow-how-to-improve-setup) a developer explains that they are trying to use Web Bluetooth to communicate with a device that appears to generate a number of [Characteristic Value Notifications](https://webbluetoothcg.github.io/web-bluetooth/#characteristic-value-notification) immediately after the GATT connection has been established. If they perform the following sequence of calls there is a high probability that some of the notifications will be lost.

```js
const device = await navigator.bluetooth.requestDevice({ filters: [{ services: [serviceUuid] }] });
const server = await device.gatt.connect();
const service = await server.getPrimaryService(serviceUuid);
const characteristic = await service.getCharacteristic(characteristicUuid);
characteristic.addEventListener('characteristicvaluechanged', () => { ... });
await characteristic.startNotifications();
```

The issue is that each of these is an asynchronous operation which takes some time to complete and the [`startNotifications()`](https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-startnotifications) call in particular depends on being able to update the [Client Characteristic Configuration descriptor](https://webbluetoothcg.github.io/web-bluetooth/#client-characteristic-configuration) in order to enable notifications. While the device is not complying with the Bluetooth specification by sending notifications before requested the reality is that other Bluetooth APIs pass on these unsolicited notifications.

Properly fixing this seems to require two changes. First, the [active notification context set](https://webbluetoothcg.github.io/web-bluetooth/#active-notification-context-set) must be removed and the [steps for responding to notifications and indications](https://webbluetoothcg.github.io/web-bluetooth/#notification-events) updated to deliver events to all active [Bluetooth](https://webbluetoothcg.github.io/web-bluetooth/#bluetooth) globals regardless of whether `startNotifications()` or `stopNotifications()` have been called. Second, the bubbling of events through [the Bluetooth tree](https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-tree-bluetooth-tree) needs to be stabilized so that the code above can be rewritten to the following.

```js
const device = await navigator.bluetooth.requestDevice({ filters: [{ services: [serviceUuid] }] });
characteristic.addEventListener('characteristicvaluechanged', () => { ... });
const server = await device.gatt.connect();
const service = await server.getPrimaryService(serviceUuid);
const characteristic = await service.getCharacteristic(characteristicUuid);
await characteristic.startNotifications();
```

In this example an attempt to update the CCCD is made by calling `startNotifications()` but an event listener is added to the [BluetoothDevice](https://webbluetoothcg.github.io/web-bluetooth/#bluetoothdevice) object to catch all characteristic value change notifications that are delivered before that process is complete.

Please view or discuss this issue at https://github.com/WebBluetoothCG/web-bluetooth/issues/514 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Wednesday, 9 September 2020 01:27:32 UTC