From 97fc5410ba24249c1785aab9ec6e848a17aef216 Mon Sep 17 00:00:00 2001 From: Jeffrey Yasskin Date: Thu, 21 Jul 2016 16:31:27 -0700 Subject: [PATCH] Add an explicit no-filters option. Before, filters: [{}] would have been a completely open filter, but that seems too subtle. --- scanning.bs | 49 +++++++++++++++++++++++++++++++++++-------- scanning.html | 57 +++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 91 insertions(+), 15 deletions(-) diff --git a/scanning.bs b/scanning.bs index 1bda59f..bce2c60 100644 --- a/scanning.bs +++ b/scanning.bs @@ -273,8 +273,9 @@ spec: html }; dictionary BluetoothLEScanOptions { - required sequence<BluetoothLEScanFilterInit> filters; + sequence<BluetoothLEScanFilterInit> filters; boolean keepRepeatedDevices = false; + boolean acceptAllAdvertisements = false; }; partial interface Bluetooth { @@ -311,6 +312,10 @@ spec: html doesn't guarantee you won't get redundant events; it just allows the UA to save power by omitting them.

+

+ In the rare case that you want to receive every advertisement without filtering them, + use the acceptAllAdvertisements field. +

@@ -320,6 +325,20 @@ spec: html and run the following steps in parallel:

    +
  1. + If |options|.acceptAllAdvertisements is `true`, + and |options|.filters is present, + reject |promise| with a {{TypeError}} and abort these steps. + + Note: There's no need to include filters if all advertisements are being accepted. +
  2. +
  3. + If |options|.acceptAllAdvertisements is `false`, + and |options|.filters is either absent or empty, + reject |promise| with a {{TypeError}} and abort these steps. + + Note: An empty set of filters wouldn't return any advertisements. +
  4. Let |filters| be |options|.filters.map(filter=>new @@ -334,12 +353,11 @@ spec: html name: "bluetooth-le-scan", filters: options.filters, keepRepeatedDevices: options.keepRepeatedDevices, + acceptAllAdvertisements: options.acceptAllAdvertisements, } -

    - This may require that this algorithm was triggered by user activation. -

    + Note: This may require that this algorithm was triggered by user activation.
  5. If the result is {{"denied"}}, @@ -355,6 +373,10 @@ spec: html {{BluetoothLEScan/keepRepeatedDevices}} |options|.keepRepeatedDevices + + {{BluetoothLEScan/acceptAllAdvertisements}} + |options|.acceptAllAdvertisements + {{BluetoothLEScan/active}}`true`
  6. @@ -405,6 +427,7 @@ spec: html interface BluetoothLEScan { readonly attribute FrozenArray<BluetoothLEScanFilter> filters; readonly attribute boolean keepRepeatedDevices; + readonly attribute boolean acceptAllAdvertisements; readonly attribute boolean active; @@ -429,6 +452,12 @@ spec: html
  7. Initialize all fields to `null`.
  8. +
  9. + If no member of |init| is present, throw a {{TypeError}}. + + Note: A filter can't implicitly allow all advertisements. + Use {{BluetoothLEScanOptions/acceptAllAdvertisements}} to explicitly do it. +
  10. For each present member in |init|, set `this`'s attribute with a matching identifier to the value of the member. @@ -475,7 +504,8 @@ spec: html dictionary BluetoothLEScanPermissionDescriptor : PermissionDescriptor { // These match BluetoothLEScanOptions. sequence<BluetoothLEScanFilterInit> filters; - boolean keepRepeatedDevices; + boolean keepRepeatedDevices = false; + boolean acceptAllAdvertisements = false; }; @@ -590,7 +620,7 @@ spec: html Let device be the Bluetooth device that sent the advertising event.
  11. - For each {{Bluetooth}} instance |bluetooth| in the UA, + For each {{Bluetooth}} instance |bluetooth| in the UA, queue a task on |bluetooth|'s relevant settings object's responsible event loop to do the following sub-steps: @@ -633,7 +663,8 @@ spec: html

    1. - If |event| doesn't match + |scan|.acceptAllAdvertisements is `false` and + |event| doesn't match any filter in |scan|.{{BluetoothLEScan/filters}}, return `no match`.
    2. @@ -644,7 +675,7 @@ spec: html and |device|.{{[[returnedFromScans]]}} includes |scan|, the UA MAY return `no match`. -
    3. Return `match`.
    4. +
    5. Return `match`.
@@ -751,7 +782,7 @@ spec: html as its callbackfn parameter, regardless of any modifications that have been made to window, Array, Array.prototype, Array.prototype.map, - Function, Function.prototype, + Function, Function.prototype, BluetoothLEScanFilter, or other objects.

diff --git a/scanning.html b/scanning.html index 90c13f7..8b21e18 100644 --- a/scanning.html +++ b/scanning.html @@ -1587,8 +1587,9 @@

4. }; dictionary BluetoothLEScanOptions { - required sequence<BluetoothLEScanFilterInit> filters; + sequence<BluetoothLEScanFilterInit> filters; boolean keepRepeatedDevices = false; + boolean acceptAllAdvertisements = false; }; partial interface Bluetooth { @@ -1614,11 +1615,21 @@

4. set keepRepeatedDevices to true. Note that setting keepRepeatedDevices to false doesn’t guarantee you won’t get redundant events; it just allows the UA to save power by omitting them.

+

In the rare case that you want to receive every advertisement without filtering them, + use the acceptAllAdvertisements field.

The requestLEScan(options) method, when invoked, MUST return a new promise promise and run the following steps in parallel:

    +
  1. + If options.acceptAllAdvertisements is true, + and options.filters is present, reject promise with a TypeError and abort these steps. +

    Note: There’s no need to include filters if all advertisements are being accepted.

    +
  2. + If options.acceptAllAdvertisements is false, + and options.filters is either absent or empty, reject promise with a TypeError and abort these steps. +

    Note: An empty set of filters wouldn’t return any advertisements.

  3. Let filters be options.filters.map(filter=>new BluetoothLEScanFilter(filter)). If this throws an exception, reject promise with that exception and abort these steps.
  4. @@ -1627,9 +1638,10 @@

    4. name: "bluetooth-le-scan", filters: options.filters, keepRepeatedDevices: options.keepRepeatedDevices, + acceptAllAdvertisements: options.acceptAllAdvertisements, } -

    This may require that this algorithm was triggered by user activation.

    +

    Note: This may require that this algorithm was triggered by user activation.

  5. If the result is "denied", reject promise with a NotAllowedError and abort these steps.
  6. @@ -1647,6 +1659,9 @@

    4. keepRepeatedDevices options.keepRepeatedDevices + + acceptAllAdvertisements + options.acceptAllAdvertisements active true @@ -1684,6 +1699,7 @@

    interface BluetoothLEScan { readonly attribute FrozenArray<BluetoothLEScanFilter> filters; readonly attribute boolean keepRepeatedDevices; + readonly attribute boolean acceptAllAdvertisements; readonly attribute boolean active; @@ -1699,6 +1715,10 @@

    BluetoothLEScanFilter(init) constructor, when invoked MUST perform the following steps:

    1. Initialize all fields to null. +
    2. + If no member of init is present, throw a TypeError. +

      Note: A filter can’t implicitly allow all advertisements. + Use acceptAllAdvertisements to explicitly do it.

    3. For each present member in init, set this's attribute with a matching identifier to the value of the member. If the member’s type is BluetoothServiceUUID, @@ -1730,7 +1750,8 @@

      dictionary BluetoothLEScanPermissionDescriptor : PermissionDescriptor { // These match BluetoothLEScanOptions. sequence<BluetoothLEScanFilterInit> filters; - boolean keepRepeatedDevices; + boolean keepRepeatedDevices = false; + boolean acceptAllAdvertisements = false; };
      permission result type @@ -1813,7 +1834,7 @@

      An advertising event event matches a BluetoothLEScan scan if the following steps return match:

        -
      1. If event doesn’t match any filter in scan.filters, +
      2. scan.acceptAllAdvertisements is false and event doesn’t match any filter in scan.filters, return no match.
      3. If scan.keepRepeatedDevices is false, there is a BluetoothDevice device that @@ -2135,6 +2156,13 @@

        Index

        Terms defined by this specification

        + +