diff --git a/index.bs b/index.bs index 4454abf..fe77041 100644 --- a/index.bs +++ b/index.bs @@ -94,25 +94,31 @@ host is the traditional guardian of access to the capabilities a device provides. In the development of this specification two possibilities were considered. First, the UA could notify the device of the origin from which a request originated. This would be similar to the Referrer header -included in HTTP request. The difficulty of this approach is that it places +included in HTTP request. The difficulty of this approach is that it places the burden of access control on the device. Devices often have very limited processing and storage capabilities and so an effort was made to limit the -amount of work necessary on the part of the device. The approach chosen by this -specification is to instead require that the UA control access. This is done -though a mechanism similiar to [[CORS]]. This specification defines a way for -the device to provide the UA with a set of static data structures defining a -set of origins that are allowed to connect to it. For devices manufactured -before this specification is adopted information about allowed origins can also -be provided out of band through a public device registry. - -A downside of this approach is that it provides no mechanism for third-party -developers to use this API with a device. We encourage device manufacturers to -enable software ecosystems to develop around their devices by providing a -high-level API on top of the trusted code running on their own origin. Such an -API could be accessed by embedding the manufacturer's trusted origin as an -iframe within the developer's own site. The trusted origin retains control over -the device through its ability to restrict the commands the third-party site -can send through it. +amount of work necessary on the part of the device. + +The approach initially chosen during drafting of this specification was to +instead require that the UA control access though a mechanism similiar to +[[CORS]]. The device could provide the UA with a set of static data structures +defining a set of origins that are allowed to connect to it. To support a +transition period for existing devices it was proposed that information about +allowed origins could also be provided out of band through some kind of public +registry. + +A downside of this approach was two-fold. First, it required vendors to build +new devices with WebUSB in mind or rely on a public registry system that proved +difficult to specify. Product development cycles are long and as only an +Editor's Draft this specification does not have the clout necessary to influence +product planning. Second, it provided no mechanism for third-party developers to +use this API with a device. This limited innovation and the number of developers +who could take advantage of this new capability. + +After considering these options the authors have decided that the permission +prompt encouraged by the {{USB/requestDevice()}} method and the integration with +[[#feature-policy]] provide adequate protection against unwanted access to a +device. ## Attacking the Host ## {#attacking-the-host} @@ -221,7 +227,7 @@ specified in the wIndex field. Value - GET_ALLOWED_ORIGINS + (Reserved) 1 @@ -230,52 +236,6 @@ specified in the wIndex field. -

Get Allowed Origins

- -This request gets the set of origins allowed to access the device. -It is analogous to the Access-Control-Allow-Origin -header defined by [[CORS]]. - -The device MUST respond with data beginning with a Allowed -Origins Header or stall the transfer. - -A URL descriptor referenced by the response MUST be -interpreted as an origin (as defined by [[RFC6454]]) and so content -beyond the scheme/host/port triple MUST be ignored. - -If the UA chooses to enforce this policy then an origin is -allowed to access a device if it matches one of the origins in -the top-level Allowed Origins Header or any descriptors -following it. An origin -is allowed to -access a configuration if it matches one of the origins in -the corresponding Configuration Subset Header or in the -top-level Allowed Origins Header. An origin -is allowed to access -an interface if it matches one of the origins in the -corresponding Function Subset Header, the Configuration -Subset Header containing it or the top-level Allowed Origins -Header. - - - - - - - - - - - - - - - - - -
bmRequestType - bRequestwValuewIndexwLengthData
11000000BbVendorCodeZeroGET_ALLOWED_ORIGINSDescriptor LengthDescriptor
-

Get URL

This request fetches the URL descriptor with the given index. @@ -314,16 +274,8 @@ specification. Value - WEBUSB_DESCRIPTOR_SET_HEADER - 0 - - - WEBUSB_CONFIGURATION_SUBSET_HEADER - 1 - - - WEBUSB_FUNCTION_SUBSET_HEADER - 2 + (Reserved) + 0-2 WEBUSB_URL @@ -331,177 +283,6 @@ specification. -

Allowed Origins Header

- -This header lists the set of origins allowed to access the entire -USB device. It MUST be followed by bNumConfigurations -configuration subset headers that control permission to -access particular configurations. - -This descriptor MUST be the beginning of the response to the Get -Allowed Origins request. wTotalLength MUST be the -total length of the response. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OffsetFieldSizeValueDescription
0bLength1NumberSize of this descriptor. Must be set to N + 5.
1bDescriptorType1ConstantWEBUSB_DESCRIPTOR_SET_HEADER.
2wTotalLength2NumberTotal size of this and all following descriptors.
4bNumConfigurations1Number - Number of configuration subset headers following this descriptor. -
5iOrigin[|N|]|N| × 1NumberSet of bLength - 5 URL descriptor indicies.
- -

Configuration Subset Header

- -This header lists the set of origins allowed to access the USB -device configuration described by the configuration -descriptor with the given bConfigurationValue. It -MUST be followed by bNumFunctions function subset -headers that control permission to access functions within this -configuration. - -This descriptor MUST follow a Allowed Origins Header. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OffsetFieldSizeValueDescription
0bLength1Number - Size of this descriptor. Must be set to N + 4. -
1bDescriptorType1ConstantWEBUSB_CONFIGURATION_SUBSET_HEADER.
2bConfigurationValue1NumberConfiguration to which this section applies.
3bNumFunctions1Number - Number of function subset headers following this - descriptor. -
4iOrigin[|N|]|N| × 1NumberSet of bLength - 4 URL descriptor indicies.
- -

Function Subset Header

- -This header lists the set of origins allowed to access the USB -device interface described by the interface descriptor with a -bInterfaceNumber equal to -bFirstInterfaceNumber or the set of interfaces defined -as a function by an interface association descriptor with an -equal bFirstInterfaceNumber. - -This descriptor MUST follow a Configuration Subset Header. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
WebUSB Function Subset Header
OffsetFieldSizeValueDescription
0bLength1Number - Size of this descriptor. Must be set to N + 3. -
1bDescriptorType1ConstantWEBUSB_FUNCTION_SUBSET_HEADER.
2bFirstInterfaceNumber1NumberFirst interface of the function to which this section applies.
3iOrigin[|N|]|N| × 1NumberSet of bLength - 3 URL descriptor indicies.
-

URL Descriptor

This descriptor contains a single URL and is returned by the Get URL @@ -563,13 +344,6 @@ The bScheme field MUST be one of these values: -

Public Device Registry

- -The WebUSB Platform Capability Descriptor and descriptors -returned by the requests defined above can be elided by publishing -this information in a public registry of supported USB devices. This -will allow device manufacturers to support WebUSB on existing devices. - # Device Enumeration # {#enumeration}
@@ -723,27 +497,20 @@ steps in parallel:
      |enumerationResult|.
   5. Remove devices from |enumerationResult| if they do not match a
      filter in |options|.{{USBPermissionDescriptor/filters}}.
-
-     The UA MAY apply additional origin-based filtering of available devices by
-     consulting an authoritative list of device-origin mappings or referring to
-     the origin list returned by the Get Allowed Origins request.
-
-     The UA MAY provide additional mechanisms for blacklisting or whitelisting
-     specific devices for arbitrary origins.
-  7. Display a prompt to the user requesting they select a device from
+  6. Display a prompt to the user requesting they select a device from
      |enumerationResult|. The UA SHOULD show a human-readable name for each
      device.
-  8. Wait for the user to have selected a |device| or cancelled the
+  7. Wait for the user to have selected a |device| or cancelled the
      prompt.
-  9. If the user cancels the prompt, set
+  8. If the user cancels the prompt, set
      |status|.{{USBPermissionResult/devices}} to an empty
      {{FrozenArray}}, resolve |promise| with undefined,
      and abort these steps.
-  10. Add |device| to |storage|.
-  11. Let |deviceObj| be the {{USBDevice}} object representing |device|.
-  12. Set |status|.{{USBPermissionResult/devices}} to a new
+  9. Add |device| to |storage|.
+  10. Let |deviceObj| be the {{USBDevice}} object representing |device|.
+  11. Set |status|.{{USBPermissionResult/devices}} to a new
       {{FrozenArray}} containing |deviceObj| as its only element.
-  13. Resolve |promise| with undefined.
+  12. Resolve |promise| with undefined.
 
 To add an allowed USB device
 |device| to {{USBPermissionStorage}} |storage|, the UA MUST run the following
@@ -828,83 +595,6 @@ host it MUST perform the following steps for each script execution environment:
   7. Fire an event named disconnect on {{Navigator/usb}}, using
      |event| as the event object.
 
-## Permission API Integration ## {#permission-api}
-
-The [[permissions]] API provides a uniform way for websites to request
-permissions from users and query which permissions they have.
-
-The "usb" powerful feature is
-defined as follows:
-
-
-
permission descriptor type
-
-
-      dictionary USBPermissionDescriptor : PermissionDescriptor {
-        sequence<USBDeviceFilter> filters;
-      };
-    
-
-
extra permission data type
-
- {{USBPermissionStorage}}, defined as: -
-      dictionary AllowedUSBDevice {
-        required octet vendorId;
-        required octet productId;
-        DOMString serialNumber;
-      };
-
-      dictionary USBPermissionStorage {
-        required sequence<AllowedUSBDevice> allowedDevices = [];
-      };
-    
- - {{AllowedUSBDevice}} instances have an internal slot - \[[devices]] that holds an - array of USB devices. -
-
permission result type
-
-
-      interface USBPermissionResult : PermissionStatus {
-        attribute FrozenArray<USBDevice> devices;
-      };
-    
-
-
permission query algorithm
-
- To query the "usb" permission with a {{USBPermissionDescriptor}} - |desc|, a {{USBPermissionStorage}} |storage|, and a {{USBPermissionResult}} - |status|, the UA must: - - 1. If |desc|.{{USBPermissionDescriptor/filters}} is set then, - for each |filter| in - |desc|.{{USBPermissionDescriptor/filters}} if |filter| - is not a valid filter then raise a {{TypeError}} and abort these - steps. - 2. Set |status|.{{PermissionStatus/state}} to - {{"prompt"}}. - 3. Let |matchingDevices| be a new {{Array}}. - 4. For each |allowedDevice| in - |storage|.{{USBPermissionStorage/allowedDevices}} and - for each |device| in |allowedDevice|@{{[[devices]]}}, run - the following substeps: - - 1. If |desc|.{{USBPermissionDescriptor/filters}} is set - and |device| does not match a filter in - |desc|.{{USBPermissionDescriptor/filters}}, continue - to the next |device|. - 2. Get the {{USBDevice}} representing |device| and add it to - |matchingDevices|. - - 5. Set |status|.{{USBPermissionResult/devices}} to a new - {{FrozenArray}} whose contents are |matchingDevices|. -
-
permission request algorithm
-
Request the "usb" permission.
-
- # Device Usage # {#device-usage}
@@ -1034,17 +724,14 @@ parallel:
   4. If |device|.{{USBDevice/opened}} is not equal to
      true reject |promise| with an {{InvalidStateError}} and
      abort these steps.
-  5. The UA MAY check that the caller is allowed to access
-     |configuration|, and if not reject |promise| with a
-     {{SecurityError}} and abort these steps.
-  6. Abort all transfers currently scheduled on endpoints other than the
+  5. Abort all transfers currently scheduled on endpoints other than the
      default control pipe and reject their associated promises
      with a {{AbortError}}.
-  7. Issue a SET_CONFIGURATION control transfer to the device to
+  6. Issue a SET_CONFIGURATION control transfer to the device to
      set |configurationValue| as its active configuration.  If this step
      fails reject |promise| with a {{NetworkError}} and abort these
      steps.
-  8. Set |device|.{{USBDevice/configuration}} to |configuration|
+  7. Set |device|.{{USBDevice/configuration}} to |configuration|
      and resolve |promise|.
 
 The {{USBDevice/claimInterface(interfaceNumber)}} method, when invoked, MUST
@@ -1060,13 +747,10 @@ return a new {{Promise}} and run the following steps in parallel:
      |interface|.{{USBInterface/claimed}} is not false,
      reject |promise| with an {{InvalidStateError}} and abort these
      steps.
-  4. The UA MAY check that the caller is allowed to access |interface|,
-     and if not reject |promise| with a {{SecurityError}} and abort these
-     steps.
-  5. Perform the necessary platform-specific steps to request exclusive control
+  4. Perform the necessary platform-specific steps to request exclusive control
      over |interface|. If this fails, reject |promise| with a
      {{NetworkError}} and abort these steps.
-  6. Set |interface|.{{USBInterface/claimed}} to true
+  5. Set |interface|.{{USBInterface/claimed}} to true
      and resolve |promise|.
 
 The {{USBDevice/releaseInterface(interfaceNumber)}} method, when invoked, MUST
@@ -1471,10 +1155,6 @@ perform the following steps:
   3. Let |configuration| be the active configuration. If the device is
      not configured abort these steps.
   4. If |setup|.{{USBControlTransferParameters/recipient}} is
-     {{"device"}} or {{"other"}} the UA MAY check that the caller is allowed
-     to access |configuration|, and if not reject |promise| with a
-     {{SecurityError}} and abort these steps.
-  5. If |setup|.{{USBControlTransferParameters/recipient}} is
      {{"interface"}}, perform the following steps:
        1. Let |interfaceNumber| be the lower 8 bits of
           |setup|.{{USBControlTransferParameters/index}}.
@@ -1485,10 +1165,7 @@ perform the following steps:
        3. If |interface|.{{USBInterface/claimed}} is not equal to
           true, reject |promise| with an
           {{InvalidStateError}} and abort these steps.
-       4. The UA MAY check that the caller is allowed to access
-          |interface|, and if not reject |promise| with a
-          {{SecurityError}}.
-  6. If |setup|.{{USBControlTransferParameters/recipient}} is
+  5. If |setup|.{{USBControlTransferParameters/recipient}} is
      {{"endpoint"}}, run the following steps:
        1. Let |endpointNumber| be defined as the lower 4 bits of
           |setup|.{{USBControlTransferParameters/index}}.
@@ -1503,9 +1180,6 @@ perform the following steps:
           |interface|.{{USBInterface/claimed}} is not equal to
           true, reject |promise| with an
           {{InvalidStateError}}.
-       5. The UA MAY check that the caller is allowed to access
-          |interface|, and if not reject |promise| with a
-          {{SecurityError}}.
 
 ## Configurations ## {#configurations}
 
@@ -1660,6 +1334,94 @@ multiple transactions per microframe. In a SuperSpeed device this value will
 include the multiplication factor provided by the bMaxBurst field
 of the SuperSpeed Endpoint Companion descriptor.
 
+# Integrations # {#integrations}
+
+## Feature Policy ## {#feature-policy}
+
+This specification defines a feature that controls whether the
+{{Navigator/usb}} attribute is exposed on the {{Navigator}} object.
+
+The feature name for this feature is "usb".
+
+The default allowlist for this feature is ["self"].
+
+## Permission API ## {#permission-api}
+
+The [[permissions]] API provides a uniform way for websites to request
+permissions from users and query which permissions they have.
+
+The "usb" powerful feature is
+defined as follows:
+
+
+
permission descriptor type
+
+
+      dictionary USBPermissionDescriptor : PermissionDescriptor {
+        sequence<USBDeviceFilter> filters;
+      };
+    
+
+
extra permission data type
+
+ {{USBPermissionStorage}}, defined as: +
+      dictionary AllowedUSBDevice {
+        required octet vendorId;
+        required octet productId;
+        DOMString serialNumber;
+      };
+
+      dictionary USBPermissionStorage {
+        required sequence<AllowedUSBDevice> allowedDevices = [];
+      };
+    
+ + {{AllowedUSBDevice}} instances have an internal slot + \[[devices]] that holds an + array of USB devices. +
+
permission result type
+
+
+      interface USBPermissionResult : PermissionStatus {
+        attribute FrozenArray<USBDevice> devices;
+      };
+    
+
+
permission query algorithm
+
+ To query the "usb" permission with a {{USBPermissionDescriptor}} + |desc|, a {{USBPermissionStorage}} |storage|, and a {{USBPermissionResult}} + |status|, the UA must: + + 1. If |desc|.{{USBPermissionDescriptor/filters}} is set then, + for each |filter| in + |desc|.{{USBPermissionDescriptor/filters}} if |filter| + is not a valid filter then raise a {{TypeError}} and abort these + steps. + 2. Set |status|.{{PermissionStatus/state}} to + {{"prompt"}}. + 3. Let |matchingDevices| be a new {{Array}}. + 4. For each |allowedDevice| in + |storage|.{{USBPermissionStorage/allowedDevices}} and + for each |device| in |allowedDevice|@{{[[devices]]}}, run + the following substeps: + + 1. If |desc|.{{USBPermissionDescriptor/filters}} is set + and |device| does not match a filter in + |desc|.{{USBPermissionDescriptor/filters}}, continue + to the next |device|. + 2. Get the {{USBDevice}} representing |device| and add it to + |matchingDevices|. + + 5. Set |status|.{{USBPermissionResult/devices}} to a new + {{FrozenArray}} whose contents are |matchingDevices|. +
+
permission request algorithm
+
Request the "usb" permission.
+
+ # Terminology # {#terminology} This specification uses several terms taken from [[USB31]]. While @@ -1725,6 +1487,11 @@ spec: ECMAScript; urlPrefix: https://tc39.github.io/ecma262/# text: Array; url: sec-array-objects text: Promise; url:sec-promise-objects text: TypeError; url: sec-native-error-types-used-in-this-standard-typeerror +spec: Feature Policy; urlPrefix: https://wicg.github.io/feature-policy/# + type: dfn + text: default allowlist + text: feature + text: feature name