diff --git a/index.bs b/index.bs
index 5659eef..d5c612b 100644
--- a/index.bs
+++ b/index.bs
@@ -631,6 +631,7 @@ run the following steps in parallel:
|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, check permissions for
|device| with |storage|.
2. Search for an element |allowedDevice| in
@@ -676,6 +677,7 @@ steps in parallel:
4. Set |status|.{{PermissionStatus/state}}
to "ask"
.
5. Enumerate all devices attached to the system. Let this result be
|enumerationResult|.
+ 1. Remove devices from |enumerationResult| if they are [=blocklisted=].
6. Remove devices from |enumerationResult| if they do not match a device
filter in |options|.{{USBPermissionDescriptor/filters}}
.
7. Remove devices from |enumerationResult| if they match a device filter
@@ -2300,6 +2302,85 @@ slots described in the following table:
1. Return wMaxPacketSize
of |endpointDescriptor|.
+# The USB Blocklist # {#blocklist}
+
+
null
, [=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
+ '\n'
.
+ 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 '#'
.
+ 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
+ ':'
.
+ 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 0xFFFF
.
+ * 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 USB blocklist is the value of the resolved promise returned by
+[=parsing the blocklist=] at https://raw.githubusercontent.com/WICG/webusb/main/blocklist.txt.
+The UA should re-fetch the blocklist periodically, but it’s unspecified how
+often.
+
+A {{USBDevice}} |device| is blocklisted 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}