Skip to content

Commit

Permalink
Add steps for parsing the blocklist and testing blocklistedness
Browse files Browse the repository at this point in the history
  • Loading branch information
nondebug committed Aug 4, 2023
1 parent 2af4f14 commit 7f28ba6
Showing 1 changed file with 84 additions and 0 deletions.
84 changes: 84 additions & 0 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,7 @@ run the following steps <a>in parallel</a>:
|enumerationResult|.
2. Let |devices| be a new empty {{Array}}.
3. For each |device| in |enumerationResult|:
1. If |device| is [=blocklisted=], [=iteration/continue=].
1. If this is the first call to this method, <a>check permissions for
|device|</a> with |storage|.
2. Search for an element |allowedDevice| in
Expand Down Expand Up @@ -676,6 +677,7 @@ steps <a>in parallel</a>:
4. Set <code>|status|.{{PermissionStatus/state}}</code> to <code>"ask"</code>.
5. <a>Enumerate all devices attached to the system</a>. Let this result be
|enumerationResult|.
1. Remove devices from |enumerationResult| if they are [=blocklisted=].
6. Remove devices from |enumerationResult| if they do not <a>match a device
filter</a> in <code>|options|.{{USBPermissionDescriptor/filters}}</code>.
7. Remove devices from |enumerationResult| if they <a>match a device filter</a>
Expand Down Expand Up @@ -2300,6 +2302,85 @@ slots</a> described in the following table:
1. Return <code>wMaxPacketSize</code> of |endpointDescriptor|.
</dl>

# The USB Blocklist # {#blocklist}

<xmp class="idl">
// USBBlocklistEntry is never exposed.
[Exposed=()]
dictionary USBBlocklistEntry {
required unsigned short idVendor;
required unsigned short idProduct;
required unsigned short bcdDevice;
};
</xmp>

This specification relies on a <a href="https://raw.githubusercontent.com/WICG/webusb/main/blocklist.txt">blocklist.txt</a>
file in this repository to restrict the set of devices a website can access.

The result of <dfn>parsing the blocklist</dfn> at a {{URL}} |url| is a
{{Promise}} that resolves to a [=list=] of {{USBBlocklistEntry}} objects,
produced by the following algorithm:

1. Let |promise| be a [=a new promise=].
1. Let |request| be a new [=request=] with associated [=request/URL=] |url|.
1. Let |processResponse| be an algorithm accepting a [=response=] |response|
with the following steps:
1. Let |body| be the associated [=response/body=] for |response|.
1. If |body| is <code>null</code>, [=resolve=] |promise| with an empty
[=list=] and abort these steps.
1. Let |contents| be the result of running [=utf-8 decode=] with |body|.
1. Let |lines| be the result of invoking
{{String/split(separator, limit)}} on |contents| with separator
<code>'\n'</code>.
1. Let |blocklist| be an empty [=list=].
1. [=list/For each=] |line| of |lines|:
1. Let |commentBegin| be the result of invoking
|line|.{{String/indexOf()}} with <code>'#'</code>.
1. If |commentBegin| is not -1, set |line| to the result of invoking
|line|.{{String/substring()}} with 0 and |commentBegin|.
1. Set |line| to the result of |line|.{{String/trimEnd()}}.
1. Let |components| be the result of invoking
{{String/split(separator, limit)}} on |line| with separator
<code>':'</code>.
1. If the [=list/size=] of |components| is not 2 or 3,
[=iteration/continue=].
1. Let |idVendor| be the result of invoking
{{Number/parseInt(string, radix)}} with |components|[0] and 16, or
[=iteration/continue=] if a {{TypeError}} is thrown.
1. Let |idProduct| be the result of invoking
{{Number/parseInt(string, radix)}} with |components|[1] and 16, or
[=iteration/continue=] if a {{TypeError}} is thrown.
1. If the [=list/size=] of |components| is:
* 2: Let |bcdDevice| be <code>0xFFFF</code>.
* 3: Let |bcdDevice| be the result of invoking
{{Number/parseInt(string, radix)}} with |components|[2] and 16,
or [=iteration/continue=] if a {{TypeError}} is thrown.
1. [=list/Append=] a new {{USBBlocklistEntry}} with |idVendor|,
|idProduct|, and |bcdDevice| to |blocklist|.
1. [=Resolve=] |promise| with |blocklist|.
1. [=Fetch=] with |request| and |processResponse|.
1. Return |promise|.

The <dfn>USB blocklist</dfn> is the value of the resolved promise returned by
[=parsing the blocklist=] at <a href="https://raw.githubusercontent.com/WICG/webusb/main/blocklist.txt">https://raw.githubusercontent.com/WICG/webusb/main/blocklist.txt</a>.
The UA should re-fetch the blocklist periodically, but it’s unspecified how
often.

A {{USBDevice}} |device| is <dfn>blocklisted</dfn> if the following steps return
"blocked":

1. [=list/For each=] |entry| of the [=USB blocklist=]:
1. If |device|.{{USBDevice/vendorId}} is not equal to
|entry|.{{USBBlocklistEntry/idVendor}}, [=iteration/continue=].
1. If |device|.{{USBDevice/productId}} is not equal to
|entry|.{{USBBlocklistEntry/idProduct}}, [=iteration/continue=].
1. Let |bcdDevice| be |device|.{{USBDevice/deviceVersionMajor}} << 8 +
|device|.{{USBDevice/deviceVersionMinor}} << 4 +
|device|.{{USBDevice/deviceVersionSubminor}}.
1. If |bcdDevice| is less than or equal to
|entry|.{{USBBlocklistEntry/bcdDevice}}, return "blocked".
1. Return "not blocked".

# Integrations # {#integrations}

<h3 id="permissions-policy" oldids="feature-policy">Permissions Policy</h3>
Expand Down Expand Up @@ -2561,4 +2642,7 @@ spec:infra; type:dfn; for:list; text:for each
spec:infra; type:dfn; for:list; text:append
spec:infra; type:dfn; for:list; text:empty
spec:infra; type:dfn; for:list; text:size
spec:fetch; type:dfn; for:/; text:request
spec:fetch; type:dfn; for:/; text:response
spec:url; type:interface; text:URL
</pre>

0 comments on commit 7f28ba6

Please sign in to comment.