Re: Should we expose all devices as if they were bonded?

I think we're going to want to treat things as-if-bonded with 1 queued
notification, in the long run, but so far the folks writing sample apps are
asking for as-if-non-bonded, and that's simpler for Chrome to implement, so
let's go with that for now, until we start getting complaints.

I've filed https://github.com/WebBluetoothCG/web-bluetooth/issues/226 so I
remember to spec this.

On Thu, Mar 31, 2016 at 7:47 AM, François Beaufort 🇫🇷 <
fbeaufort@google.com> wrote:

> What is the status on this?
>
> On Fri, Mar 18, 2016 at 8:18 PM Jeffrey Yasskin <jyasskin@google.com>
> wrote:
>
>> On Fri, Mar 18, 2016 at 7:57 AM, Von Dentz, Luiz
>> <luiz.von.dentz@intel.com> wrote:
>> > Hi Jeffrey,
>> >
>> > On Thu, Mar 17, 2016 at 11:00 PM, Jeffrey Yasskin <jyasskin@google.com>
>> wrote:
>> >> On Thu, Mar 17, 2016 at 10:12 AM, Rob Moran <Rob.Moran@arm.com> wrote:
>> >>>
>> >>> I agree that registering service changed events is the same in both
>> cases,
>> >>> but having to register for these across re-connects feels unintuitive
>> versus
>> >>> scanning after a re-connect.
>> >>> I am assuming that discovering services again would still return the
>> >>> cached ones, however.
>> >>
>> >>
>> >> If we treat devices as not-bonded, I think we get:
>> >>
>> >>   await device.gatt.connect();
>> >>   // Depends on
>> https://github.com/WebBluetoothCG/web-bluetooth/issues/53:
>> >>   device.addEventListener('servicechanged', change =>
>> console.log(change));
>> >>   let service = await device.gatt.getPrimaryService('uuid');
>> >>   let characteristic = await service.getCharacteristic('uuid2');
>> >>   device.gatt.disconnect();
>> >>   await device.gatt.connect();
>> >>   await service.getCharacteristic('uuid2') // Throws InvalidStateError:
>> >> service no longer exists?
>> >>   let service2 = await device.gatt.getPrimaryService('uuid'); // Waits
>> until
>> >> discovery process finishes.
>> >>   service ?== service2; // ???
>> >>   device.gatt.disconnect();
>> >>   // 'uuid' service removed, replaced with 'uuid3' service.
>> >>   await device.gatt.connect();
>> >>   await service.getCharacteristic('uuid2') // Throws InvalidStateError:
>> >> service no longer exists?
>> >>   let service3 = await device.gatt.getPrimaryService('uuid'); //
>> >> NotFoundError.
>> >>   let service4 = await device.gatt.getPrimaryService('uuid3');
>> >>   service4 !== service2;
>> >>
>> >> I think we wouldn't get any 'servicechanged' events in this scenario,
>> since
>> >> the changes happen when no services are known.
>> >
>> > Well if that would be the case 'servicechanged' cannot be used for
>> > detecting new services since it appears to ignore any change outside
>> > the known range.
>>
>> In the design I've got so far, to detect a service you expect to be
>> added, you'd getPrimaryService('the-service'), catch the rejection if
>> it's not there, and then watch for 'servicechanged' to tell you it's
>> been added. Skipping the getPrimaryService() call could indeed cause
>> the browser to skip the 'servicechanged' event because of the rules in
>>
>> https://webbluetoothcg.github.io/web-bluetooth/#only-notify-for-requested-services
>> .
>> Those are there so the browser doesn't have to do a full discovery on
>> connect().
>>
>> >> If we treat devices as bonded, I think we get the following flow
>> instead:
>> >>
>> >>   await device.gatt.connect();
>> >>   // Depends on
>> https://github.com/WebBluetoothCG/web-bluetooth/issues/53:
>> >>   device.addEventListener('servicechanged', change => console.log);
>> >>   let service = await device.gatt.getPrimaryService('uuid');
>> >>   let characteristic = await service.getCharacteristic('uuid2');
>> >>   let value = await characteristic.readValue();
>> >>   device.gatt.disconnect();
>> >>   await device.gatt.connect();
>> >>   characteristic === await service.getCharacteristic('uuid2');
>> >>   service === await device.gatt.getPrimaryService('uuid');
>> >>   await device.gatt.getPrimaryService('uuid3');  // NotFoundError
>> >>   device.gatt.disconnect();
>> >>   // 'uuid' service removed, replaced with 'uuid3' service.
>> >>   await device.gatt.connect();
>> >
>> > This seems to ignore that fact that the changes can happens while
>> > connected where the following events would be exactly the same.
>>
>> This example happens to show the change occurring while disconnected,
>> in order to highlight the difference from the as-if-non-bonded case.
>> If the change happens while the device is connected and after the
>> service has been retrieved during the current connection, I think the
>> bonded and non-bonded options act the same. Have I missed something?
>>
>> >>   // 'servicechanged' fired some time after this. Let's say it doesn't
>> >> arrive for a while.
>> >>   service === await device.gatt.getPrimaryService('uuid');  // Cached.
>> >>   characteristic === await service.getCharacteristic('uuid2');  //
>> Cached.
>> >>   let value = await characteristic.readValue(); // InvalidStateError?
>> What
>> >> GATT error does this cause?
>> >>   await device.gatt.getPrimaryService('uuid3');  // Cached
>> NotFoundError.
>> >>   // Say 'servicechanged' arrives now. Listener logs it to console.
>> >>   let service2 = await device.gatt.getPrimaryService('uuid3');  //
>> Succeeds.
>> >>   let service3 = await device.gatt.getPrimaryService('uuid'); //
>> >> NotFoundError.
>> >>
>> >>
>> >> Does that all make sense? Does it convince anyone to prefer
>> as-if-bonded or
>> >> as-if-not-bonded?
>> >
>> > The main concept difference appears to be persistent cache vs
>> > temporary cache, the miss chance is slightly bigger on the former but
>> > handling is almost the same either way.
>>
>> I don't really follow, sorry. IIUC, the persistent/as-if-bonded option
>> guarantees sites don't miss a single notification sent right after the
>> connection is established, and allows sites to write less code, but
>> requires more code from the browser. The temporary/as-if-non-bonded
>> option allows missed notifications, but allows a simpler browser
>> implementation.
>>
>> > Btw, the persistent cache can
>> > be used to check the services matches during the connection phase
>> > which further reduces the chance of cache miss.
>>
>> I still think the persistent-but-non-bonded cache can fail to notice
>> added and removed characteristics within an existing service whose
>> range doesn't change. We don't need that to change in Bluez to
>> implement Web Bluetooth, since we can just blame any resulting bugs on
>> the user's platform, but I don't want to bake it into the web API.
>>
>> Jeffrey
>>
>> >> Jeffrey
>> >>
>> >>>
>> >>> Rob
>> >>>
>> >>> Hi Rob,
>> >>>
>> >>> I really meant GATT notifications, even though advertise would
>> >>> probably make more sense but Im not sure it is supported in a lot of
>> >>> systems, certainly not Web Bluetooth. Anyway, I don't think suggesting
>> >>> to use advertise will make the problem go away as devices may already
>> >>> be in the market.
>> >>>
>> >>> Btw, the statement about having to register service changed events and
>> >>> possibly holding stale services is true in any case regardless if we
>> >>> persist the attributes or not because the device may change them while
>> >>> connected not only when it is offline.
>> >>>
>> >>> On Thu, Mar 17, 2016 at 1:47 PM, Rob Moran <Rob.Moran@arm.com> wrote:
>> >>> > Hi Luiz,
>> >>> >
>> >>> > I assume you are meaning devices such as eddystone beacons?
>> >>> > I'm not sure if the Web Bluetooth requestDevice() function is the
>> best
>> >>> > interface to observe these sorts of beacons, but is more geared
>> towards
>> >>> > connecting and interacting with devices.
>> >>> > For purely observing devices, I think another function alongside
>> >>> > requestDevice() (observeDevices()?) may be a better approach which
>> can
>> >>> > maintain the cache required for these sorts of devices, is
>> read-only and may
>> >>> > not need the security restrictions of requestDevice().
>> >>> >
>> >>> > Specific scanning apps (such as the physical web app) may also be
>> >>> > another option?
>> >>> >
>> >>> > ________________________________________
>> >>> > From: Von Dentz, Luiz <luiz.von.dentz@intel.com>
>> >>> > Sent: 17 March 2016 11:11
>> >>> > To: Rob Moran
>> >>> > Cc: Christiansen, Kenneth R; Jeffrey Yasskin; public-web-bluetooth
>> >>> > Subject: Re: Should we expose all devices as if they were bonded?
>> >>> >
>> >>> > Hi Rob,
>> >>> >
>> >>> > There are device that advertise, notify one value and disconnect,
>> >>> > which creates a race condition where the application/page may not be
>> >>> > quick enough to catch the value which is then lost as the device
>> >>> > disconnects immediately to save power.
>> >>> >
>> >>> > On Thu, Mar 17, 2016 at 1:06 PM, Rob Moran <Rob.Moran@arm.com>
>> wrote:
>> >>> >>
>> >>> >> IMO having the device appear unbonded and requiring a user to
>> >>> >> re-discover services and re-register for events, etc. after a
>> disconnect is
>> >>> >> a cleaner and more atomic approach.
>> >>> >> Requiring the user to register for service changed events and
>> possibly
>> >>> >> holding stale services (as they may not exist after a reconnect)
>> could
>> >>> >> create more edge cases and potential errors to cover.
>> >>> >>
>> >>> >> In this scenario, I think the item to persist between connections
>> is
>> >>> >> the security context, so that any further reconnections don't
>> require a user
>> >>> >> action to undertake, but still honour the original service / name
>> filters.
>> >>> >>
>> >>> >> Cheers,
>> >>> >>
>> >>> >> Rob
>> >>> >> ________________________________________
>> >>> >> From: Christiansen, Kenneth R <kenneth.r.christiansen@intel.com>
>> >>> >> Sent: 17 March 2016 10:39
>> >>> >> To: Jeffrey Yasskin; public-web-bluetooth
>> >>> >> Subject: RE: Should we expose all devices as if they were bonded?
>> >>> >>
>> >>> >> At least for development purposes it would be nice to have them
>> >>> >> unbounded (but I guess we could have a way to change the behavior
>> in
>> >>> >> devtools when it is open)
>> >>> >>
>> >>> >> I am not sure whether I want the notifications to be queued, at
>> least
>> >>> >> not by default. Think about something like temperature change and
>> heart rate
>> >>> >> measurements.
>> >>> >>
>> >>> >> Kenneth
>> >>> >>
>> >>> >>> -----Original Message-----
>> >>> >>> From: Jeffrey Yasskin [mailto:jyasskin@google.com]
>> >>> >>> Sent: Thursday, March 17, 2016 2:22 AM
>> >>> >>> To: public-web-bluetooth <public-web-bluetooth@w3.org>
>> >>> >>> Subject: Should we expose all devices as if they were bonded?
>> >>> >>>
>> >>> >>> Two issues came up recently where the Bluetooth spec defines
>> different
>> >>> >>> behavior depending on whether a device is bonded.
>> >>> >>>
>> >>> >>> In https://groups.google.com/a/chromium.org/d/topic/web-
>> >>> >>> bluetooth/PQpZAFNlvT4/discussion
>> >>> >>> and https://github.com/thegecko/web-bluetooth-dfu/issues/12,
>> Luiz is
>> >>> >>> suggesting that we have Web Bluetooth remember services,
>> >>> >>> characteristics,
>> >>> >>> and descriptors across disconnection, even when there's no
>> physical
>> >>> >>> bond.
>> >>> >>> That's similar to treating the web site as bonded to the
>> peripheral.
>> >>> >>> We'd in
>> >>> >>> the case of no bond, we'd re-discover the known services, etc.
>> after
>> >>> >>> re-
>> >>> >>> connecting, and send service-changed events for the ones that have
>> >>> >>> changed. We'd also allow users to hold onto Service, etc. objects
>> >>> >>> across
>> >>> >>> disconnect/connect pairs, and continue using the objects
>> afterward. On
>> >>> >>> the
>> >>> >>> other hand, if we treat pages as un-bonded, users would need to
>> >>> >>> re-fetch
>> >>> >>> services, etc. before using them after a disconnect/reconnect
>> pair.
>> >>> >>>
>> >>> >>> In https://github.com/WebBluetoothCG/web-bluetooth/issues/220 and
>> >>> >>> https://bugs.chromium.org/p/chromium/issues/detail?id=589796, we
>> have
>> >>> >>> to decide whether users need to re-subscribe to notifications
>> after a
>> >>> >>> disconnection. If we treat pages as bonded, the notification state
>> >>> >>> should
>> >>> >>> persist across disconnections. If we treat pages as non-bonded,
>> the
>> >>> >>> state
>> >>> >>> should reset to unsubscribed on disconnection. (3.G.3.3.3.3) If we
>> >>> >>> keep the
>> >>> >>> page subscribed across disconnection, users might expect us to
>> queue
>> >>> >>> notifications, or at least indications, and deliver them the next
>> time
>> >>> >>> the page
>> >>> >>> is connected. Should we do the same if the page is unloaded? That
>> kind
>> >>> >>> of
>> >>> >>> unbounded queueing seems problematic.
>> >>> >>>
>> >>> >>> And, of course, beyond always treating a page as bonded or
>> not-bonded,
>> >>> >>> we
>> >>> >>> could make the page's bonded-ness depend on the presence of a
>> physical
>> >>> >>> bond.
>> >>> >>>
>> >>> >>> Are there other areas where treating the page as having or
>> not-having
>> >>> >>> a
>> >>> >>> bond would cause divergent behavior?
>> >>> >>>
>> >>> >>> Which behavior do you folks think makes more sense for the web
>> API?
>> >>> >>>
>> >>> >>> Jeffrey
>> >>> >>
>> >>> >> IMPORTANT NOTICE: The contents of this email and any attachments
>> are
>> >>> >> confidential and may also be privileged. If you are not the
>> intended
>> >>> >> recipient, please notify the sender immediately and do not
>> disclose the
>> >>> >> contents to any other person, use it for any purpose, or store or
>> copy the
>> >>> >> information in any medium. Thank you.
>> >>> >>
>> >>> >>
>> >>> >
>> >>> > IMPORTANT NOTICE: The contents of this email and any attachments are
>> >>> > confidential and may also be privileged. If you are not the intended
>> >>> > recipient, please notify the sender immediately and do not disclose
>> the
>> >>> > contents to any other person, use it for any purpose, or store or
>> copy the
>> >>> > information in any medium. Thank you.
>> >>> >
>> >>>
>> >>> IMPORTANT NOTICE: The contents of this email and any attachments are
>> >>> confidential and may also be privileged. If you are not the intended
>> >>> recipient, please notify the sender immediately and do not disclose
>> the
>> >>> contents to any other person, use it for any purpose, or store or
>> copy the
>> >>> information in any medium. Thank you.
>> >>>
>> >>
>>
>>

Received on Thursday, 31 March 2016 23:42:12 UTC