@@ -110,6 +110,7 @@ spec: WEBDRIVER; urlPrefix: https://w3c.github.io/webdriver/
110110 type: dfn
111111 text: error; url: dfn-error
112112 text: local end; url: dfn-local-ends
113+ text: invalid element state; url: dfn-invalid-element-state
113114
114115</pre>
115116<pre class="link-defaults">
@@ -3111,6 +3112,13 @@ slots</a> described in the following table:
31113112 tell whether its <a>realm</a> was ever disconnected while it was running.
31123113 </td>
31133114 </tr>
3115+ <tr>
3116+ <td> <dfn>\[[automatedGATTConnectionResponse]]</dfn> </td>
3117+ <td><code> "not-expected"</code></td>
3118+ <td>
3119+ The simulated GATT connection response code for a GATT connection attempt.
3120+ </td>
3121+ </tr>
31143122</table>
31153123
31163124<div algorithm="BluetoothRemoteGATTServer connect">
@@ -3128,45 +3136,65 @@ method, when invoked, MUST perform the following steps:
31283136 but for now sites need to serialize their use of this API
31293137 and/or give the user a way to retry failed operations.
313031381. Let |promise| be [=a new promise=] .
3139+ 1. If [=this=] .{{BluetoothRemoteGATTServer/connected}} is `true`,
3140+ [=resolve=] |promise| with [=this=] and return |promise|.
313131411. Add |promise| to [=this=] .{{[[activeAlgorithms]]}} .
313231421. Run the following steps [=in parallel=] :
3133- 1. If [=this=] .{{BluetoothRemoteGATTServer/device}} .{{[[representedDevice]]}}
3134- has no [=ATT Bearer=] , do the following sub-steps:
3135- 1. <p id="create-an-att-bearer"> Attempt to create an <a>ATT Bearer</a>
3136- using the procedures described in "Connection Establishment" under
3137- <a>GAP Interoperability Requirements</a> . Abort this attempt if
3138- |promise| is removed from
3139- [=this=] .{{[[activeAlgorithms]]}} .</p>
3140-
3141- <div class="note">
3142- Note: These procedures can wait forever
3143- if a connectable advertisement isn't received.
3144- The website should call {{disconnect()}}
3145- if it no longer wants to connect.
3146- </div>
3147- 1. If this attempt was aborted because |promise| was removed from
3148- [=this=] .{{[[activeAlgorithms]]}} , [=queue a global task=] on
3149- the [=Bluetooth task source=] given |global| to [=reject=]
3150- |promise| with an "{{AbortError}} " {{DOMException}} and abort these
3151- steps.
3152- 1. If this attempt failed for another reason, [=queue a global task=]
3153- on the [=Bluetooth task source=] given |global| to [=reject=]
3154- |promise| with a "{{NetworkError}} " {{DOMException}} and abort
3155- these steps.
3156- 1. Use the [=Exchange MTU=] procedure to negotiate the largest
3157- supported MTU. Ignore any errors from this step.
3158- 1. The UA MAY attempt to bond with the remote device using the <a>BR/EDR
3159- Bonding Procedure</a> or the [=LE Bonding Procedure=] .
3160-
3161- Note: We would normally prefer to give the website control over
3162- whether and when bonding happens, but the [Core
3163- Bluetooth](https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/AboutCoreBluetooth/Introduction.html)
3164- platform API doesn't provide a way for UAs to implement such a knob.
3165- Having a bond is more secure than not having one, so this
3166- specification allows the UA to opportunistically create one on
3167- platforms where that's possible. This may cause a user-visible
3168- pairing dialog to appear when a connection is created, instead of
3169- when a restricted characteristic is accessed.
3143+ 1. If |global|'s [=Window/navigable=]' s
3144+ [=navigable/top-level traversable=] 's <a>simulated Bluetooth adapter</a>
3145+ is not empty, run the following steps:
3146+ 1. [=Trigger a gatt connection attempted event=] given |global|'s
3147+ [=Window/navigable=] and [=this=] .{{BluetoothRemoteGATTServer/device}} .
3148+ 1. If [=this=] .{{[[automatedGATTConnectionResponse]]}} is `"not-expected"`,
3149+ set it to `"expected"`.
3150+ 1. If [=this=] .{{[[automatedGATTConnectionResponse]]}} is `"expected"`,
3151+ wait for it to change.
3152+ 1. Let |response| be [=this=] .{{[[automatedGATTConnectionResponse]]}} .
3153+ 1. Set [=this=] .{{[[automatedGATTConnectionResponse]]}} to `"not-expected"`.
3154+ 1. If |response| is not `0`, do the
3155+ following sub-steps:
3156+ 1. Remove |promise| from [=this=] .{{[[activeAlgorithms]]}} .
3157+ 1. [=Queue a global task=] on the [=Bluetooth task source=] given
3158+ |global| to [=reject=] |promise| with a "{{NetworkError}} "
3159+ {{DOMException}} and abort these steps.
3160+ 1. Otherwise, run the following steps:
3161+ 1. If [=this=] .{{BluetoothRemoteGATTServer/device}} .{{[[representedDevice]]}}
3162+ has no [=ATT Bearer=] , do the following sub-steps:
3163+ 1. <p id="create-an-att-bearer"> Attempt to create an <a>ATT Bearer</a>
3164+ using the procedures described in "Connection Establishment" under
3165+ <a>GAP Interoperability Requirements</a> . Abort this attempt if
3166+ |promise| is removed from
3167+ [=this=] .{{[[activeAlgorithms]]}} .</p>
3168+
3169+ <div class="note">
3170+ Note: These procedures can wait forever
3171+ if a connectable advertisement isn't received.
3172+ The website should call {{disconnect()}}
3173+ if it no longer wants to connect.
3174+ </div>
3175+ 1. If this attempt was aborted because |promise| was removed from
3176+ [=this=] .{{[[activeAlgorithms]]}} , [=queue a global task=] on
3177+ the [=Bluetooth task source=] given |global| to [=reject=]
3178+ |promise| with an "{{AbortError}} " {{DOMException}} and abort these
3179+ steps.
3180+ 1. If this attempt failed for another reason, [=queue a global task=]
3181+ on the [=Bluetooth task source=] given |global| to [=reject=]
3182+ |promise| with a "{{NetworkError}} " {{DOMException}} and abort
3183+ these steps.
3184+ 1. Use the [=Exchange MTU=] procedure to negotiate the largest
3185+ supported MTU. Ignore any errors from this step.
3186+ 1. The UA MAY attempt to bond with the remote device using the <a>BR/EDR
3187+ Bonding Procedure</a> or the [=LE Bonding Procedure=] .
3188+
3189+ Note: We would normally prefer to give the website control over
3190+ whether and when bonding happens, but the [Core
3191+ Bluetooth](https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/AboutCoreBluetooth/Introduction.html)
3192+ platform API doesn't provide a way for UAs to implement such a knob.
3193+ Having a bond is more secure than not having one, so this
3194+ specification allows the UA to opportunistically create one on
3195+ platforms where that's possible. This may cause a user-visible
3196+ pairing dialog to appear when a connection is created, instead of
3197+ when a restricted characteristic is accessed.
31703198 1. [=Queue a global task=] on the [=Bluetooth task source=] given |global|
31713199 to perform the following sub-steps:
31723200 1. If |promise| is not in [=this=] .{{[[activeAlgorithms]]}} , [=reject=]
@@ -5134,6 +5162,7 @@ BluetoothCommand = (
51345162 bluetooth.DisableSimulation //
51355163 bluetooth.SimulatePreconnectedPeripheral //
51365164 bluetooth.SimulateAdvertisement //
5165+ bluetooth.SimulateGattConnectionResponse //
51375166)
51385167</pre>
51395168
@@ -5215,7 +5244,7 @@ bluetooth.SimulateAdapterParameters = {
52155244<div algorithm="remote end steps for bluetooth.simulateAdapter">
52165245The [=remote end steps=] with command parameters |params| are:
52175246
5218- 1. Let |contextId| be |params|["context"] .
5247+ 1. Let |contextId| be |params|[` "context"` ] .
521952481. Let |navigable| be the result of [=trying=] to [=get a navigable=] with |contextId|.
522052491. If |navigable| is not a [=navigable/top-level traversable=] , return [=error=] with [=error code=] [=invalid argument=] .
522152501. Let |simulatedBluetoothAdapter| be |navigable|'s <a>simulated Bluetooth adapter</a> .
@@ -5278,7 +5307,7 @@ bluetooth.DisableSimulationParameters = {
52785307<div algorithm="remote end steps for bluetooth.disableSimulation">
52795308The [=remote end steps=] with command parameters |params| are:
52805309
5281- 1. Let |contextId| be |params|["context"] .
5310+ 1. Let |contextId| be |params|[` "context"` ] .
528253111. Let |navigable| be the result of [=trying=] to [=get a navigable=] with |contextId|.
528353121. If |navigable| is not a [=navigable/top-level traversable=] , return [=error=] with [=error code=] [=invalid argument=] .
528453131. Set |navigable|'s <a>simulated Bluetooth adapter</a> to empty.
@@ -5380,7 +5409,7 @@ bluetooth.SimulateAdvertisementScanEntryParameters = {
53805409<div algorithm="remote end steps for bluetooth.simulateAdvertisement">
53815410The [=remote end steps=] with command parameters |params| are:
53825411
5383- 1. Let |contextId| be params[ "context"] .
5412+ 1. Let |contextId| be | params| [` "context"` ] .
538454131. Let |topLevelNavigable| be the result of [=trying=] to [=get a navigable=] with |contextId|.
538554141. If |topLevelNavigable| is not a [=navigable/top-level traversable=] , return [=error=] with [=error code=] [=invalid argument=] .
538654151. Let |scanEntry| be |params|[`"scanEntry"`] .
@@ -5429,6 +5458,58 @@ A [=local end=] could simulate a device advertisement by sending the following m
54295458</pre>
54305459</div>
54315460
5461+ #### The bluetooth.simulateGattConnectionResponse Command #### {#bluetooth-simulategattconnectionresponse-command}
5462+
5463+ <pre highlight="cddl" class="cddl remote-cddl local-cddl">
5464+ bluetooth.SimulateGattConnectionResponse = (
5465+ method: "bluetooth.simulateGattConnectionResponse",
5466+ params: bluetooth.SimulateGattConnectionResponseParameters,
5467+ )
5468+
5469+ bluetooth.SimulateGattConnectionResponseParameters = {
5470+ context: text,
5471+ address: text,
5472+ code: uint
5473+ }
5474+
5475+ </pre>
5476+
5477+ <div algorithm="remote end steps for bluetooth.simulateGattConnectionResponse">
5478+ The [=remote end steps=] with command parameters |params| are:
5479+
5480+ 1. Let |contextId| be |params|[`"context"`] .
5481+ 1. Let |navigable| be the result of [=trying=] to [=get a navigable=] with |contextId|.
5482+ 1. Let |deviceAddress| be |params|[`"address"`] .
5483+ 1. Let |simulatedBluetoothAdapter| be |navigable|'s <a>simulated Bluetooth adapter</a> .
5484+ 1. If |simulatedBluetoothAdapter| is empty, return [=error=] with [=error code=] [=invalid argument=] .
5485+ 1. Let |deviceMapping| be |simulatedBluetoothAdapter|'s <a>simulated Bluetooth device mapping</a> .
5486+ 1. If |deviceMapping|[|deviceAddress|] [=map/exists=] , let |simulatedDevice| be |deviceMapping|[|deviceAddress|] .
5487+ Otherwise, return [=error=] with [=error code=] [=invalid argument=] .
5488+ 1. Let |simulatedDeviceInstance| be the result of <a>get the <code>BluetoothDevice</code> representing</a>
5489+ |simulatedDevice| inside |navigable|'s <a>active window</a>' s <a spec=HTML>associated <code>Navigator</code></a> 's
5490+ [=associated Bluetooth=] .
5491+ 1. If |simulatedDeviceInstance|.{{[[gatt]]}} .{{[[automatedGATTConnectionResponse]]}} is `"expected"`,
5492+ set |simulatedDeviceInstance|.{{[[gatt]]}} .{{[[automatedGATTConnectionResponse]]}} to |params|[`"code"`] .
5493+ 1. Otherwise, return [=error=] with [=error code=] [=invalid element state=] .
5494+
5495+ </div>
5496+
5497+ <div class="example">
5498+ A [=local end=] could simulate a device gatt connection response of success
5499+ (error code `0x00` according to <a>List of Error Codes</a> ) by sending the following message:
5500+
5501+ <pre highlight="json">
5502+ {
5503+ "method": "bluetooth.simulateGattConnectionResponse",
5504+ "params": {
5505+ "context": "cxt-d03fdd81",
5506+ "address": "09:09:09:09:09:09",
5507+ "code": 0
5508+ }
5509+ }
5510+ </pre>
5511+ </div>
5512+
54325513### Events ### {#bidi-events}
54335514
54345515#### The bluetooth.requestDevicePromptUpdated Event #### {#bluetooth-requestdevicepromptupdated-event}
@@ -5453,10 +5534,39 @@ To <dfn>trigger a prompt updated event</dfn> given a [=navigable=] |navigable|,
545355341. Let |prompt| be the [=device prompt=] (|promptId|, |devices|).
545455351. Let |serialized devices| be the result of [=serialize prompt devices=] with |prompt|.
545555361. Set [=map of navigables to device prompts=] [|navigableId|] to |prompt|.
5456- 1. Let |params| be a [=map=] matching the <code> bluetooth.RequestDevicePromptUpdatedParameters</code> production with the <code> context</code> field set to |navigableId|, the <code> prompt</code> field set to |promptId|, and the <code> devices</code> field set to |serialized devices|.
5537+ 1. Let |params| be a [=map=] matching the <code> bluetooth.RequestDevicePromptUpdatedParameters</code> production with the <code> context</code> field set to |navigableId|, the <code> prompt</code> field set to |promptId|, and the <code> devices</code> field set to |serialized devices|.
545755381. Let |body| be a [=map=] matching the <code> bluetooth.RequestDevicePromptUpdated</code> production, with the <code> params</code> field set to |params|.
5458- 1. Let |related navigables| be a [=/set=] containing |navigable|.
5459- 1. For each |session| in the [=set of sessions for which an event is enabled=] given "<code> bluetooth.requestDevicePromptUpdated</code> " and |related navigables|:
5539+ 1. Let |relatedNavigables| be a [=/set=] containing |navigable|.
5540+ 1. For each |session| in the [=set of sessions for which an event is enabled=] given "<code> bluetooth.requestDevicePromptUpdated</code> " and |relatedNavigables|:
5541+ 1. [=Emit an event=] with |session| and |body|.
5542+
5543+ </div>
5544+
5545+ #### The bluetooth.gattConnectionAttempted Event #### {#bluetooth-gattConnectionAttempted-event}
5546+
5547+ <pre highlight="cddl" class="cddl local-cddl">
5548+ bluetooth.GattConnectionAttempted = (
5549+ method: "bluetooth.gattConnectionAttempted",
5550+ params: bluetooth.GattConnectionAttemptedParameters
5551+ )
5552+
5553+ bluetooth.GattConnectionAttemptedParameters = {
5554+ context: text,
5555+ address: text
5556+ }
5557+ </pre>
5558+
5559+ <div algorithm="remote end event trigger for bluetooth.GattConnectionAttempted">
5560+ To <dfn>trigger a gatt connection attempted event</dfn> given a [=navigable=] |navigable| and a {{BluetoothDevice}} |device|:
5561+
5562+ 1. Let |navigableId| be |navigable|'s [=navigable id=] .
5563+ 1. Let |params| be a [=map=] matching the <code> bluetooth.GattConnectionAttemptedParameters</code> production with the
5564+ <code> context</code> field set to |navigableId| and the <code> address</code> field set to |device|.{{[[representedDevice]]}} 's address.
5565+ 1. Let |body| be a [=map=] matching the <code> bluetooth.GattConnectionAttempted</code> production, with the
5566+ <code> params</code> field set to |params|.
5567+ 1. Let |relatedNavigables| be a [=/set=] containing |navigable|.
5568+ 1. For each |session| in the [=set of sessions for which an event is enabled=] given
5569+ "<code> bluetooth.gattEventGenerated</code> " and |relatedNavigables|:
54605570 1. [=Emit an event=] with |session| and |body|.
54615571
54625572</div>
@@ -5526,6 +5636,15 @@ This specification uses a read-only type that is similar to WebIDL's
55265636 </li>
55275637 <li value="2"> Core System Package [BR/EDR Controller volume]
55285638 <ol type="A">
5639+ <li value="4"> Error Codes
5640+ <ol>
5641+ <li value="1"> Overview of Error Codes
5642+ <ol>
5643+ <li value="3"> <dfn>List of Error Codes</dfn> </li>
5644+ </ol>
5645+ </li>
5646+ </ol>
5647+ </li>
55295648 <li value="5"> Host Controller Interface Functional Specification
55305649 <ol>
55315650 <li value="7"> HCI Commands and Events
0 commit comments