Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add WebDriver BiDi extension #622

Merged
merged 21 commits into from
Apr 23, 2024
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
234 changes: 234 additions & 0 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,17 @@ spec: html; urlPrefix: https://html.spec.whatwg.org/multipage/browsing-the-web.h
spec: PAGE-VISIBILITY; urlPrefix: https://www.w3.org/TR/page-visibility-2/#
type: dfn
text: document visibility state; url: dom-visibilitystate

spec: WEBDRIVER; urlPrefix: https://w3c.github.io/webdriver/
type: dfn
text: error; url: dfn-errors
text: local end; url: dfn-local-ends

<!-- WebDriver BiDi should be updated to export this definition. -->
<!-- https://github.com/speced/bikeshed/issues/2802 -->
spec: WEBDRIVER-BIDI; urlPrefix: https://w3c.github.io/webdriver-bidi/
type: dfn
text: set of sessions for which an event is enabled; url: set-of-sessions-for-which-an-event-is-enabled
</pre>
<pre class="link-defaults">
spec:dom
Expand Down Expand Up @@ -1476,6 +1487,9 @@ steps:
1. If |exclusionFilters| isn't `null`, remove devices from
<var>scanResult</var> if they <a>match a filter</a> in
<var>uuidExclusionFilters</var>.
1. Let |browsing context| be [=this=]'s [=relevant global object=]'s [=browsing context=].
OrKoN marked this conversation as resolved.
Show resolved Hide resolved
1. Let |prompt id| be a new unique opaque string.
1. [=Trigger a prompt open event=] given |browsing context|, |prompt id|, and |scanResult|.
1. <p id="requestDevice-prompt">Even if <var>scanResult</var> is empty,
<a>prompt the user to choose</a> one of the devices in |scanResult|,
associated with |descriptor|, and let |device| be the result.
Expand All @@ -1490,6 +1504,7 @@ steps:
to indicate interest and then perform a privacy-disabled scan to retrieve
the name.
</div>
1. [=Trigger a prompt close event=] given |browsing context| and |prompt id|.
1. The UA MAY <a>add |device| to |storage|</a>.

<div class="note">
Expand Down Expand Up @@ -4827,6 +4842,225 @@ attribute on the {{Navigator}} object may be used.

The <a>default allowlist</a> for this feature is <code>["self"]</code>.

# Automated testing # {#automated-testing}

For the purposes of user-agent automation and application testing, this document defines extensions to the [[WebDriver-BiDi]] specification.

## The bluetooth module ## {#bluetooth-module}

The bluetooth module contains commands for managing the remote end Bluetooth behavior.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrap "bluetooth" with <dfn>:

The <dfn>bluetooth</dfn> module contains commands

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have removed the definition because it conflicts with another definition with the same id. We also usually do not need the definition for the module, is there a place you want to reference it?


### Types ### {#bidi-types}

#### The bluetooth.RequestDevice Type #### {#bluetooth-requestdevice-type}

```cddl
OrKoN marked this conversation as resolved.
Show resolved Hide resolved
bluetooth.RequestDevice = text
```

The bluetooth.RequestDevice is an identifier for a single device in a request device prompt.
OrKoN marked this conversation as resolved.
Show resolved Hide resolved

A <dfn>device prompt</dfn> is a [=tuple=] consisting of a <dfn>device prompt id</dfn> (a string) and a <dfn>set of devices</dfn> (a [=/set=]). It represents a prompt which allows a user to [=prompt the user to choose|choose=] a [=Bluetooth device=].
OrKoN marked this conversation as resolved.
Show resolved Hide resolved

#### The bluetooth.RequestDeviceInfo Type #### {#bluetooth-requestdeviceinfo-type}

```cddl
bluetooth.RequestDeviceInfo = {
id: bluetooth.RequestDevice,
name: text,
}
```

The bluetooth.RequestDeviceInfo type represents a single device in a request device prompt.
OrKoN marked this conversation as resolved.
Show resolved Hide resolved

<div algorithm="serialize device">
To <dfn>serialize device</dfn> given [=Bluetooth device=] |device|:
OrKoN marked this conversation as resolved.
Show resolved Hide resolved

1. Let |id| be the id of |device|.
OrKoN marked this conversation as resolved.
Show resolved Hide resolved
1. Let |name| be the name of |device|.
1. Return a [=map=] matching the <code>bluetooth.RequestDeviceInfo</code> production, with the <code>id</code> field set to |id|, and the <code>name</code> field set to |name|.
OrKoN marked this conversation as resolved.
Show resolved Hide resolved

</div>

#### The bluetooth.RequestDevicePrompt Type #### {#bluetooth-requestdeviceprompt-type}

```cddl
bluetooth.RequestDevicePrompt = text
```

The bluetooth.RequestDevicePrompt is an identifier for a single prompt.
OrKoN marked this conversation as resolved.
Show resolved Hide resolved

A remote end has a <dfn>map of browsing context to device prompts</dfn> which is a [=/map=] whose keys are [=browsing context ids=] and values are [=device prompts=].
OrKoN marked this conversation as resolved.
Show resolved Hide resolved

<div algorithm="get a prompt">
To <dfn>get a prompt</dfn> given |browsing context id| and |prompt id|:

1. If [=map of browsing context to device prompts=][|browsing context id|] does not [=map/exist=]:
OrKoN marked this conversation as resolved.
Show resolved Hide resolved
1. Return [=error=] with [=error code=] [=no such prompt=].
1. Let |prompt| be [=map of browsing context to device prompts=][|browsing context id|].
1. If |prompt|'s [=device prompt id=] is not |prompt id|:
1. Return [=error=] with [=error code=] [=no such prompt=].
1. Return [=success=] with data |prompt|.

</div>

<div algorithm="match a device in prompt">
To <dfn>match a device in prompt</dfn> given [=device prompt=] |prompt| and |device id|:

1. For each |device| in |prompt|'s [=set of devices=]:
1. If |device| matches |device id|, return [=success=] with data |device|.
OrKoN marked this conversation as resolved.
Show resolved Hide resolved
1. Otherwise:
1. Return [=error=] with [=error code=] [=no such device=].

</div>

<div algorithm="serialize prompt devices">
To <dfn>serialize prompt devices</dfn> given [=device prompt=] |prompt|:

1. Let |devices| be an empty [=/list=].
1. For each |device| in |prompt|'s [=set of devices=].
1. Append the result of [=serialize device=] with |device|.
OrKoN marked this conversation as resolved.
Show resolved Hide resolved
1. Return |devices|.

</div>

### Errors ### {#bidi-errors}

This specification extends the set of [=error codes=] from
[[WEBDRIVER-BIDI|WebDriver BiDi]] with the following additional codes:

<dl>
<dt><dfn>no such device</dfn>
<dd>Tried to reference an unknown [=Bluetooth device=].
OrKoN marked this conversation as resolved.
Show resolved Hide resolved

<dt><dfn>no such prompt</dfn>
<dd>Tried to reference an unknown prompt.
OrKoN marked this conversation as resolved.
Show resolved Hide resolved
</dl>

### Commands ### {#bidi-commands}

#### The bluetooth.handleRequestDevicePrompt Command #### {#bluetooth-handlerequestdeviceprompt-command}

```cddl
bluetooth.HandleRequestDevicePrompt = (
method: "bluetooth.handleRequestDevicePrompt",
params: bluetooth.HandleRequestDevicePromptParameters,
)

bluetooth.HandleRequestDevicePromptParameters = {
context: browsingContext.BrowsingContext,
prompt: bluetooth.RequestDevicePrompt,
(
bluetooth.HandleRequestDevicePromptAcceptParameters //
bluetooth.HandleRequestDevicePromptCancelParameters
)
}

bluetooth.HandleRequestDevicePromptAcceptParameters = {
accept: true,
device: bluetooth.RequestDevice,
}

bluetooth.HandleRequestDevicePromptCancelParameters = {
accept: false,
}
```

<div algorithm="remote end steps for bluetooth.handleRequestDevicePrompt">
The [=remote end steps=] with |command parameters| are:
OrKoN marked this conversation as resolved.
Show resolved Hide resolved

1. Let |context id| be the value of the <code>context</code> field of |command parameters|.
1. Let |prompt id| be the value of the <code>prompt</code> field of |command parameters|.
1. Let |prompt| be the result of [=trying=] to [=get a prompt=] with |context id| and |prompt id|.
1. Let |accept| be the value of the <code>accept</code> field of |command parameters|.
1. If |accept| is true:
1. Let |device id| be the value of the <code>device</code> field of |command parameters|.
1. Let |device| be the result of [=trying=] to [=match a device in prompt=] given |prompt| and |device id|.
1. Acknowledge |prompt| with |device|.
1. Otherwise:
1. Dismiss |prompt|.
OrKoN marked this conversation as resolved.
Show resolved Hide resolved
1. Return [=success=] with data null.
OrKoN marked this conversation as resolved.
Show resolved Hide resolved

</div>

<div class="example">
A [=local end=] could dismiss a prompt by sending the following message:

<pre highlight="json">
{
"method": "bluetooth.handleRequestDevicePrompt",
"params": {
"context": "cxt-d03fdd81",
"prompt": "pmt-e0a234b",
"accept": true,
"device": "dvc-9b3b872"
}
}
</pre>
</div>

### Events ### {#bidi-events}

#### The bluetooth.requestDevicePromptOpened Event #### {#bluetooth-requestdevicepromptopened-event}

```cddl
bluetooth.RequestDevicePromptOpened = (
method: "bluetooth.requestDevicePromptOpened",
params: browsingContext.RequestDevicePromptOpenedParameters,
)

bluetooth.RequestDevicePromptOpenedParameters = {
context: browsingContext.BrowsingContext,
prompt: bluetooth.RequestDevicePrompt,
devices: [* bluetooth.RequestDeviceInfo],
}
```

OrKoN marked this conversation as resolved.
Show resolved Hide resolved
<div algorithm="remote end event trigger for bluetooth.requestDevicePromptOpened">
To <dfn>trigger a prompt open event</dfn> given a [=browsing context=] |context|, a string |prompt id|, and a [=/set=] of [=Bluetooth devices=] |devices|:

1. Let |context id| be |context|'s [=browsing context id=].
1. Let |prompt| be the [=device prompt=] (|prompt id|, |devices|).
1. Let |serialized devices| be the result of [=serialize prompt devices=] with |prompt|.
1. Set [=map of browsing context to device prompts=][|context id|] to |prompt|.
1. Let |params| be a [=map=] matching the <code>bluetooth.RequestDevicePromptOpenedParameters</code> production with the <code>context</code> field set to |context id|, the <code>prompt</code> field set to |prompt id|, and the <code>devices</code> field set to |serialized devices|.
1. Let |body| be a [=map=] matching the <code>bluetooth.RequestDevicePromptOpened</code> production, with the <code>params</code> field set to |params|.
1. Let |related browsing contexts| be a [=/set=] containing |context|.
1. For each |session| in the [=set of sessions for which an event is enabled=] given "<code>bluetooth.requestDevicePromptOpened</code>" and |related browsing contexts|:
1. [=Emit an event=] with |session| and |body|.

</div>

#### The bluetooth.requestDevicePromptClosed Event #### {#bluetooth-requestdevicepromptclosed-event}

```cddl
bluetooth.RequestDevicePromptClosed = (
method: "bluetooth.requestDevicePromptClosed",
params: browsingContext.RequestDevicePromptClosedParameters,
)

bluetooth.RequestDevicePromptClosedParameters = {
context: browsingContext.BrowsingContext,
prompt: bluetooth.RequestDevicePrompt,
}
```

<div algorithm="remote end event trigger for bluetooth.requestDevicePromptClosed">
To <dfn>trigger a prompt close event</dfn> given a [=browsing context=] |context| and a string |prompt id|:

1. Let |context id| be |context|'s [=browsing context id=].
1. Assert: [=map of browsing context to device prompts=][|context id|] [=map/exists=].
1. Let |prompt| be [=map of browsing context to device prompts=][|context id|].
1. If |prompt|'s [=device prompt id=] is |prompt id|:
1. [=map/Remove=] [=map of browsing context to device prompts=][|context id|].
1. Let |params| be a [=map=] matching the <code>bluetooth.RequestDevicePromptClosedParameters</code> production with the <code>context</code> field set to |context id|, and the <code>prompt</code> field set to |prompt id|.
1. Let |body| be a [=map=] matching the <code>bluetooth.RequestDevicePromptClosed</code> production, with the <code>params</code> field set to |params|.
1. Let |related browsing contexts| be a [=/set=] containing |context|.
1. For each |session| in the [=set of sessions for which an event is enabled=] given "<code>bluetooth.requestDevicePromptClosed</code>" and |related browsing contexts|:
1. [=Emit an event=] with |session| and |body|.

</div>

# Terminology and Conventions # {#terminology}

This specification uses a few conventions and several terms from other
Expand Down