diff --git a/index.bs b/index.bs
index 80bacb6..1f05354 100644
--- a/index.bs
+++ b/index.bs
@@ -621,6 +621,9 @@ The {{USB/ondisconnect}} attribute is an Event handler IDL attribute for the
The {{USB/getDevices()}} method, when invoked, MUST return a new {{Promise}} and
run the following steps in parallel:
+ 1. Let |document| be this's [=relevant global object=]'s
+ [=associated Document=], or null
if there is no associated
+ {{Document}}.
1. Let |storage| be:
1. The {{USBPermissionStorage}} object in the script execution environment
of the associated [=service worker client=], if [=this=]'s [=relevant
@@ -631,7 +634,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 |device| is [=blocklisted=] for |document|, [=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
@@ -658,10 +661,10 @@ The {{USB/requestDevice()}} method, when invoked, MUST run the following steps:
throw a {{NotFoundError}} and abort these steps.
2. Return |result|.{{USBPermissionResult/devices}}[0]
.
-To request the "usb" permission, given a {{USBPermissionStorage}}
-|storage|, a {{USBPermissionDescriptor}} |options| and a {{USBPermissionResult}}
-|status|, the UA MUST return a new {{Promise}} |promise| and run the following
-steps in parallel:
+To request the "usb" permission, given a {{Document}} |document|, a
+{{USBPermissionStorage}} |storage|, a {{USBPermissionDescriptor}} |options| and
+a {{USBPermissionResult}} |status|, the UA MUST return a new {{Promise}}
+|promise| and run the following steps in parallel:
1. For each |filter| in
|options|.{{USBPermissionDescriptor/filters}}
if |filter|
@@ -677,7 +680,8 @@ 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=].
+ 1. Remove devices from |enumerationResult| if they are [=blocklisted=] for
+ |document|.
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
@@ -1309,8 +1313,15 @@ All USB devices MUST have a default control pipe which is
with a {{NotFoundError}} and abort these steps.
1. If this.{{USBDevice/[[claimedInterface]]}}[|interfaceIndex|] is true
,
resolve |promise| and abort these steps.
- 1. If |interfaces|[|interfaceIndex|].{{USBInterface/[[isProtectedClass]]}} is true
,
- [=reject=] |promise| with a {{SecurityError}} and abort these steps.
+ 1. Let |unrestricted| be false
.
+ 1. Let |document| be this's [=relevant global object=]'s [=associated Document=], or
+ null
if there is no associated {{Document}}.
+ 1. If |document| is not null
and |document| is [=allowed to use=] the
+ [=policy-controlled feature=] named "usb-unrestricted"
, set |unrestricted| to
+ true
.
+ 1. If |interfaces|[|interfaceIndex|].{{USBInterface/[[isProtectedClass]]}} is true
+ and |unrestricted| is false
, [=reject=] |promise| with a {{SecurityError}} and
+ abort these steps.
1. Perform the necessary platform-specific steps to request exclusive control
over |interfaces|[|interfaceIndex|] for the current execution context. If this fails,
reject |promise| with a {{NetworkError}} and abort these steps.
@@ -2349,9 +2360,12 @@ The USB blocklist is the result of [=parsing the blocklist=] at
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":
+A {{USBDevice}} |device| is blocklisted for a {{Document}} |document|
+if the following steps return "blocked":
+ 1. If |document| is not null
and |document| is [=allowed to use=]
+ the [=policy-controlled feature=] named "usb-unrestricted"
,
+ return "not blocked".
1. [=list/For each=] |entry| of the [=USB blocklist=]:
1. If |device|.{{USBDevice/vendorId}} is not equal to
|entry|.{{USBBlocklistEntry/idVendor}}, [=iteration/continue=].
@@ -2374,6 +2388,18 @@ is exposed on the {{Navigator}} object.
The default allowlist for this feature is ["self"]
.
+This specification defines a second policy-controlled feature, identified
+by the token "usb-unrestricted"
, that controls whether blocklisted
+USB devices and device interfaces with protected classes can be accessed. This
+feature MUST only be enabled for Isolated Web Apps
+that declare the feature in the Web Application Manifest [[APPMANIFEST]].
+
+The default allowlist for this feature is ["self"]
.
+Typically this would imply that the feature is allowed in {{Document}}s in
+[=top-level traversables=] by default. However, due to the requirement that this
+feature is only enabled for Isolated Web Apps with the feature declared in the
+manifest, the effective default allowlist is ["none"]
.
+
## Permission API ## {#permission-api}
The [[permissions]] API provides a uniform way for websites to request