From 1bc865a2874693817f74b26678e76c8ba57ead73 Mon Sep 17 00:00:00 2001 From: Daniel Vogelheim Date: Wed, 8 Apr 2026 15:31:10 +0200 Subject: [PATCH] Add reference to usermedia delta spec. --- README.md | 9 + usermedia-element-delta.html | 378 +++++++++++++++++++++++++++++++++++ 2 files changed, 387 insertions(+) create mode 100644 usermedia-element-delta.html diff --git a/README.md b/README.md index f4b5d07..649b39f 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,15 @@ An HTML permission element for the * [Explainer](geolocation_explainer.md) * [Geolocation Element Specification Draft](https://wicg.github.io/PEPC/geolocation-element.html) +# Usermedia Elements + +A set of HTML elements to mediate access to a [MediaStream](https://www.w3.org/TR/mediacapture-streams/#dom-mediastream): + +* [Explainer](usermedia_element.md) +* [Usermedia Element Specification Draft](usermedia-element-delta.html), meant + for inclusion in + [Media Capture and Streams Extensions](https://w3c.github.io/mediacapture-extensions/) + # Page Embedded Permission Control (PEPC) The originally proposed permission element, for any diff --git a/usermedia-element-delta.html b/usermedia-element-delta.html new file mode 100644 index 0000000..a125ec7 --- /dev/null +++ b/usermedia-element-delta.html @@ -0,0 +1,378 @@ + + + + Proposed <usermedia>, <camera>, and <microphone> + media capture HTML elements, + as a delta specification to Media Capture and Streams Extensions + + + + + +
+

This document proposes a set of HTML elements, <usermedia>, + <camera>, and <microphone>, + that mean to provide user-friendly and secure access + to a {{MediaStream}}, handling the required premissions in the process.

+

This is a delta specification, meant to eventually be included in + [[mediacapture-streams]] or [[mediacapture-extensions]].

+
+
+

This is a delta specification, meant to eventually be included in [[mediacapture-streams]] or [[mediacapture-extensions]]. It currently contains only the differences from this spec.

+
+
+

The <usermedia>, <camera>, and + <microphone> media capture HTML elements

+ +

The <usermedia>, + <camera>, and <microphone> + HTML elements are [[HTML]] elements that can mediate access to a + {{MediaStream}}, including handling the required [=permission/prompts=] + for [=powerful features=].

+ +

These three elements cover three different use cases and allow for use + case specific user interfaces in the [=user agent=]. Their + content attributes + and IDL are mostly the same.

+ +

The <usermedia> element uses the following + DOM interface:

+ +
+      [Exposed=Window]
+      interface HTMLUserMediaElement : HTMLElement {
+        [HTMLConstructor] constructor();
+
+        readonly attribute MediaStream? stream;
+        undefined setConstraints(MediaStreamConstraints constraints);
+        readonly attribute DOMException? error;
+      };
+      HTMLUserMediaElement includes ActivationBlockersMixin;
+    
+ +

The <camera> and <microphone> + DOM interfaces are almost the same. + The <camera> element uses the following + DOM interface:

+ +
+      [Exposed=Window]
+      interface HTMLCameraElement : HTMLElement {
+        [HTMLConstructor] constructor();
+
+        readonly attribute MediaStream? stream;
+        undefined setConstraints(MediaStreamConstraints constraints);
+        readonly attribute DOMException? error;
+      };
+      HTMLCameraElement includes ActivationBlockersMixin;
+    
+ +

The <microphone> element uses the following + DOM interface:

+ +
+      [Exposed=Window]
+      interface HTMLMicrophoneElement : HTMLElement {
+        [HTMLConstructor] constructor();
+
+        readonly attribute MediaStream? stream;
+        undefined setConstraints(MediaStreamConstraints constraints);
+        readonly attribute DOMException? error;
+      };
+      HTMLMicrophoneElement includes ActivationBlockersMixin;
+    
+ + +

The <usermedia>, + <camera>, and <microphone> + elements all use the following internal slot:

+ + +

The <usermedia>, + <camera>, and <microphone> + elements belong to the [=flow content=], + [=phrasing content=], [=interactive content=], and [=palpable content=] + categories. + They can be used in contexts where [=phrasing content=] is expected. + Their content, if any, are their + fallback content. + They use the {{ActivationBlockersMixin}} from [[geolocation-element]], to + provide protection against programmatic activation.

+ +

The <usermedia>, + <camera>, and <microphone> + elements all support the following + content attributes:

+ +
+
global attributes
+
— all global content attributes.
+
isValid
+
invalidReason
+
onvalidationstatuschange
+
— content attributes from {{ActivationBlockersMixin}}
+
+ + +
+

Algorithms

+ +

The {{HTMLUserMediaElement}}, {{HTMLCameraElement}}, and + {{HTMLMicrophoneElement}} all use the same constructor steps. Their + {{HTMLUserMediaElement/constructor()}} steps are:

+
    +
  1. Run {{ActivationBlockersMixin}}'s + [=ActivationBlockersMixin/initialization steps=].
  2. +
  3. Initialize {{HTMLUserMediaElement/[[stream]]}} to null.
  4. +
  5. Initialize {{HTMLUserMediaElement/[[error]]}} to null.
  6. +
  7. Initialize {{HTMLUserMediaElement/[[constraints]]}} to [=this=]'s + [=HTMLUserMediaElement/default constraints=].
  8. +
+ +

The <usermedia> element's [=insertion steps=] are:

+
    +
  1. Run {{ActivationBlockersMixin}}'s + [=ActivationBlockersMixin/insertion steps=].
  2. +
+ +

The <usermedia> element's [=removing steps=] are:

+
    +
  1. Run {{ActivationBlockersMixin}}'s + [=ActivationBlockersMixin/removing steps=].
  2. +
+ +

The {{HTMLUserMediaElement/stream}} getter steps are:

+
    +
  1. Return {{HTMLUserMediaElement/[[stream]]}}.
  2. +
+ +

The {{HTMLUserMediaElement/setConstraints()}} steps for an |element| and + a parameter |constraints| steps:

+
    +
  1. Set {{HTMLUserMediaElement/[[constraints]]}} to the result of + [=HTMLUserMediaElement/constraint filter=] for |element| + and |constraints|.
  2. +
+ +

The {{HTMLUserMediaElement/error}} getter steps are:

+
    +
  1. Return {{HTMLUserMediaElement/[[error]]}}. +
+ +

The <usermedia>, <camera>, and + <microphone> + permission name are:

+ + + + + + + + + + + + + + + + + + + + + +
Element typeValue
<usermedia>The [=string/concatenate|concatentation=] of + « [=/"camera"=], " ", [=/"microphone"=] ».
<camera>[=/"camera"=]
<microphone>[=/"microphone"=]
+ +

The <usermedia>, <camera>, and + <microphone> + default constraints are:

+ + + + + + + + + + + + + + + + + + + + + +
Element typeValue
<usermedia>«[ + {{MediaStreamConstraints/video}} → true, + {{MediaStreamConstraints/audio}} → true + ]»
<camera>«[ + {{MediaStreamConstraints/video}} → true, + {{MediaStreamConstraints/audio}} → false + ]»
<microphone>«[ + {{MediaStreamConstraints/video}} → false, + {{MediaStreamConstraints/audio}} → true + ]»
+

The <usermedia> |element|'s + [=EventTarget/activation behavior=] is:

+
    +
  1. If |element|.{{ActivationBlockersMixin/isValid}} is false, + then return.
  2. +
  3. If {{HTMLUserMediaElement/[[stream]]}} is null, run + [=HTMLUserMediaElement/activation initial=] steps.
  4. +
  5. Otherwise, run [=HTMLUserMediaElement/activation second=] steps.
  6. +
+ +

The activation initial steps + are:

+
    +
  1. [=Assert=]: |element|.{{ActivationBlockersMixin/isValid}}.
  2. +
  3. [=Assert=]: {{HTMLUserMediaElement/[[stream]]}} is null.
  4. +
  5. Let |permissionName| be |element|'s [=permission name=].
  6. +
  7. Let |descriptor| be a new {{PermissionDescriptor}} with value + «[ {{PermissionDescriptor/name}} → |permissionName| + ]».
  8. +
  9. Let |permissionState| be the result of + [=request permission to use=] the [=powerful features=] + described by |descriptor| with allowMultiple set to false.
  10. +
  11. If |permissionState| is not {{PermissionState/"granted"}}:
  12. +
      +
    1. Set {{HTMLUserMediaElement/[[stream]]}} to null.
    2. +
    3. Set {{HTMLUserMediaElement/[[error]]}} to null.
    4. +
    5. Return.
    6. +
    +
  13. Let |contraints| be {{HTMLUserMediaElement/[[constraints]]}}.
  14. +
  15. Let |mediaPromise| be the result of calling + {{MediaDevices/getUserMedia()}} with |constraints| as its first + argument.
  16. +
  17. [=promise/React=] to |mediaPromise|: +
      +
    1. If |mediaPromise| was fulfilled with value |v|:
    2. +
        +
      1. [=Assert=]: |v| is a {{MediaStream}}.
      2. +
      3. Set {{HTMLUserMediaElement/[[stream]]}} to |v|.
      4. +
      5. Set {{HTMLUserMediaElement/[[error]]}} to null.
      6. +
      +
    3. else: +
        +
      1. [=Assert=]: |mediaPromise| was rejected with reason |r|.
      2. +
      3. [=Assert=]: |r| is a |DOMException|.
      4. +
      5. Set {{HTMLUserMediaElement/[[stream]]}} to null.
      6. +
      7. Set {{HTMLUserMediaElement/[[error]]}} to |r|.
      8. +
      +
    4. +
    +
  18. +
+ +

The activation second steps + are:

+
    +
  1. [=Assert=]: |element|.{{ActivationBlockersMixin/isValid}}.
  2. +
  3. [=Assert=]: {{HTMLUserMediaElement/[[stream]]}} is a + {{MediaStream}}.
  4. +
  5. TODO: We ought to do something here, too. +
+ +

The constraint filter steps + for an |element| and {{MediaStreamConstraints}} |constraints| are:

+
    +
  1. Let |result| be a new [=dictionary=]. +
  2. If |element| is a {{HTMLUserMediaElement}}, + set |result| to «[ + {{MediaStreamConstraints/audio}} → |constraints|[{{MediaStreamConstraints/audio}}], + {{MediaStreamConstraints/video}} → |constraints|[{{MediaStreamConstraints/video}}] + ]».
  3. +
  4. Otherwise, if |element| is a {{HTMLMicrophoneElement}}, + set |result| to «[ + {{MediaStreamConstraints/audio}} → |constraints|[{{MediaStreamConstraints/audio}}], + {{MediaStreamConstraints/video}} → false + ]».
  5. +
  6. Otherwise, if |element| is a {{HTMLCameraElement}}, + set |result| to «[ + {{MediaStreamConstraints/audio}} → false, + {{MediaStreamConstraints/video}} → |constraints|[{{MediaStreamConstraints/video}}] + ]».
  7. +
  8. TODO: |results| should have additional filtering to support a + reasonable, easy-to-use subset of all the constraints allowed for + the getUserMedia call.
  9. +
  10. Return |result|. +
+ +
+
+

<usermedia> legacy support.

+ +

To ease transition from the current <usermedia> element in + Chrome, we support a limited form of the {{HTMLUserMediaElementLegacyMixin/type}} + attribute, with values for `audio`, `video`, or both. If this attribute is + set, it modifies the behaviour of the <usermedia> element to + match the behaviour of any of the elements discussed here. This is a + hold-over from the original <permission> element design. It is expected + that this mixin will not be included in the final standard.

+ +
+      interface mixin HTMLUserMediaElementLegacyMixin {
+        attribute DOMString type;
+        boolean isTypeSupported(DOMString type);
+      };
+      HTMLUserMediaElement includes HTMLUserMediaElementLegacyMixin;
+      
+ +

The {{HTMLUserMediaElementLegacyMixin/type}} IDL attribute reflects + the `type` content attribute. + Depending on {{HTMLUserMediaElementLegacyMixin/type}}, the + <usermedia> element changes behaviour:

+
+
`"audio video"`
+
`"video audio"`
+
— behaves like a regular <usermedia> element.
+
`"audio"`
+
— behaves like an <microphone> element.
+
`"video"`
+
— behaves like a <camera> element.
+
all other values
+
— behaves like an {{HTMLUnknownElement}}.
+
+ +

The {{HTMLUserMediaElementLegacyMixin/isTypeSupported()}} method can + be used to query whether a given type is supported by this element. + It will return true if the input string is one of `"audio video"`, + `"video audio"`, `"audio"`, or `"video"`, and false in all other cases. +

+
+
+ +