Copyright © 2025World Wide Web Consortium.W3C®liability,trademark andpermissive document license rules apply.
This specification extendsHTMLMediaElement
[HTML] providing APIs to control playback of encrypted content.
The API supports use cases ranging from simple clear key decryption to high value video (given an appropriate user agent implementation). License/key exchange is controlled by the application, facilitating the development of robust playback applications supporting a range of content decryption and protection technologies.
This specification does not define a content protection or Digital Rights Management system. Rather, it defines a common API that may be used to discover, select and interact with such systems as well as with simpler content encryption systems. Implementation of Digital Rights Management is not required for compliance with this specification: only theClear Key system is required to be implemented as a common baseline.
The common API supports a simple set of content encryption capabilities, leaving application functions such as authentication and authorization to page authors. This is achieved by requiring content protection system-specific messaging to be mediated by the page rather than assuming out-of-band communication between the encryption system and a license or other server.
This section describes the status of this document at the time of its publication. A list of currentW3C publications and the latest revision of this technical report can be found in theW3C standards and drafts index at https://www.w3.org/TR/.
Two new features were added since publication as aW3C Recommendation inSeptember 2017:
encryptionScheme
attribute.getStatusForPolicy
()
method.Inclusion of other features is out of scope for the Media Working Group. On top of editorial updates, other substantive changes made to this specification address maintenance issues against this specification:
encrypted-media
identifier.usable-in-future
" toMediaKeyStatus
for keys that are not yet usable for decryption.QuotaExceededError
when steps fail due to a lack of resources.MediaKeySessionClosedReason
to describe possible reasons for a session closure, and adjust algorithms accordingly.For a full list of changes made since the previous version, see thecommits.
This document was published by theMedia Working Group as a Working Draft using theRecommendation track.
Publication as a Working Draft does not imply endorsement byW3C and its Members.
This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under theW3C Patent Policy.W3C maintains apublic list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes containsEssential Claim(s) must disclose the information in accordance withsection 6 of theW3C Patent Policy.
This document is governed by the03 November 2023W3C Process Document.
This section is non-normative.
This specification enables script to select content protection mechanisms, control license/key exchange, and execute custom license management algorithms. It supports a wide range of use cases without requiring client-side modifications in each user agent for each use case. This enables content providers to develop a single application solution for all devices.
Supported content is encrypted per container-specific "common encryption" specifications, enabling use across key systems. Supported content has an unencrypted container, enabling metadata to be provided to the application and maintaining compatibility with otherHTMLMediaElement
features.
Implementers should pay attention to the mitigations for the security and privacy threats and concerns described in this specification. In particular, the specification requirements for security and privacy cannot be met without knowledge of the security and privacy properties of theKey System and its implementation(s).8. Implementation Requirements contains security and privacy provisions related to the integration and use of underlyingKey System implementations.10. Security focuses on external threats, such as input data or network attacks.11. Privacy focuses on the handling of user-specific information and providing users with adequate control over their own privacy.
While this specification is independent of the source of the media data, authors should be aware that many implementations only support decrypting media data provided via Media Source Extensions [MEDIA-SOURCE].
A generic stack implemented using the API is shown below. This diagram shows an example flow; other combinations of API calls and events are possible.
Content Decryption Module (CDM) is the client component that provides the functionality, including decryption, for one or moreKey Systems.
Implementations may or may not separate the implementations of CDMs or treat them as separate from the user agent. This is transparent to the API and application.
A Key System is a generic term for a decryption mechanism and/or content protection provider. Key System strings provide unique identification of a Key System. They are used by the user agent to select aCDM and identify the source of a key-related event. User agentsMUST support theCommon Key Systems. User agentsMAY also provide additionalCDMs with corresponding Key System strings.
A Key System string is always a reverse domain name. Key System strings are compared using case-sensitive matching. It isRECOMMENDED thatCDMs use simple lower-case ASCII key system strings.
For example, "com.example.somesystem".
Within a given system ("somesystem" in the example), subsystems may be defined as determined by the key system provider. For example, "com.example.somesystem.1" and "com.example.somesystem.1_5". Key System providers should keep in mind that these will be used for comparison and discovery, so they should be easy to compare and the structure should remain reasonably simple.
A Key Session, or simply Session, provides a context for message exchange with theCDM as a result of which key(s) are made available to theCDM. Sessions are embodied asMediaKeySession
objects. Each Key session is associated with a single instance ofInitialization Data provided in thegenerateRequest
()
call.
Each Key Session is associated with a singleMediaKeys
object, and only media element(s) associated with thatMediaKeys
object may access key(s) associated with the session. OtherMediaKeys
objects,CDM instances, and media elementsMUST NOT access the key session or use its key(s). Key sessions and the keys they contain are no longerusable for decryption once the session has been closed, including when theMediaKeySession
object is destroyed.
All license(s) and key(s) associated with a Key Session which have not been explicitly storedMUST be destroyed when the Key Session is closed.
Key IDsMUST be unique within a session.
A Session ID is a unique string identifier generated by theCDM that can be used by the application to identifyMediaKeySession
objects.
A new Session ID is generated each time the user agent andCDM successfully create a new session.
Each Session IDSHALL be unique within the browsing context in which it was created. For session types for which theIs persistent session type? algorithm returnstrue
, Session IDsMUST be unique within theorigin over time, including across browsing sessions.
The underlying content protection protocol does not necessarily need to support Session IDs.
Unless otherwise stated, key refers to a decryption key that can be used to decrypt blocks withinmedia data. Each such key is uniquely identified by akey ID. A key is associated with thesession used to provide it to theCDM. (The same key may be present in multiple sessions.) Such keysMUST only be provided to theCDM via anupdate
()
call. (They may later be loaded byload
()
as part of the stored session data.)
AuthorsSHOULD encrypt each set of stream(s) that requires enforcement of a meaningfully different policy with a distinct key (and key ID). For example, if policies may differ between two video resolutions, stream(s) containing one resolution should not be encrypted with the key used to encrypt stream(s) containing the other resolution. When encrypted, audio streamsSHOULD NOT use the same key as any video stream. This is the only way to ensure enforcement and compatibility across clients.
A key is considered usable for decryption if theCDM is certain the key is currently usable to decrypt one or more blocks ofmedia data.
For example, a key is not usable for decryption if its license has expired. Even if its license has not expired, a key is not usable for decryption if other conditions (e.g., output protection) for its use are not currently satisfied.
Akey is associated with a key ID that is a sequence of octets and which uniquely identifies the key. The container specifies the ID of the key that can decrypt a block or set of blocks within themedia data.Initialization DataMAY contain key ID(s) to identify the keys that are needed to decrypt the media data. However, there is no requirement that Initialization Data contain any or all key IDs used in themedia data ormedia resource.Licenses provided to theCDM associate each key with a key ID so theCDM can select the appropriate key when decrypting an encrypted block of media data.
A key is considered to be known to a session if theCDM's implementation of the session contains any information - specifically thekey ID - about it, regardless of whether the actualkey is usable or its value is known. Known keys are exposed via thekeyStatuses
attribute.
Keys are considered known even after they become unusable, such as due toexpiration or if they are removed but arecord of license destruction is available. Keys only become unknown when they are explicitly removed from a session and any license release message is acknowledged.
For example, a key could become unknown if anupdate
()
call provides a new license that does not include the key and includes instructions to replace the license(s) that previously contained the key.
A license is key system-specific state information that includes one or morekey(s) - each associated with akey ID - and potentially other information about key usage.
Key Systems usually require a block of initialization data containing information about the stream to be decrypted before they can construct a license request message. This block could be a simple key or content ID or a more complex structure containing such information. ItSHOULD always allow unique identification of thekey(s) needed to decrypt the content. This initialization informationMAY be obtained in some application-specific way or provided with themedia data.
Initialization Data is a generic term for container-specific data that is used by aCDM to generate a license request.
The format of the initialization data depends upon the type of container, and containersMAY support more than one format of initialization data. TheInitialization Data Type is a string that indicates the format of the accompanying Initialization Data. Initialization Data Type strings are always matched case-sensitively. It isRECOMMENDED that Initialization Data Type strings are lower-case ASCII strings.
TheEncrypted Media Extensions Initialization Data Format Registry [EME-INITDATA-REGISTRY] provides the mapping fromInitialization Data Type string to the specification for each format.
When the user agent encounters Initialization Data in themedia data, it provides that Initialization Data to the application in theinitData
attribute of the
event. The user agentMUST NOT store the Initialization Data or use itscontent at the time it is encountered. The application providesInitialization Data to theCDM viaencrypted
generateRequest
()
. The user agentMUST NOT provideInitialization Data to theCDM by other means.
Initialization DataMUST be a fixed value for a given set of stream(s) ormedia data. ItMUST only contain information related to the keys required to play a given set of stream(s) ormedia data. ItMUST NOT contain application data, client-specific data, user-specific data, or executable code.
Initialization DataSHOULD NOT contain Key System-specific data or values. ImplementationsMUST support the common formats defined in [EME-INITDATA-REGISTRY] for eachInitialization Data Type they support.
Use of proprietary formats/contents is discouraged, and supporting or usingonly proprietary formats is strongly discouraged. Proprietary formats should only be used with pre-existing content or on pre-existing client devices that do not support the common formats.
Two or more identifiers or other values are said to be associable if they are identicalor it is possible - with a reasonable amount of time and effort - to correlate or associate them. Otherwise, the values arenon-associable.
For example, values created in the following ways areassociable:
Using a trivially-reversible hash function.
Sharing a prefix or other subset
Replacing random value N with N+10
XORing the origin with a fixed value (because it is trivially reversible)
In contrast, two values that are completely unrelated or cryptographically distinct, such as via a cryptographically strong non-reversible hash function, arenon-associable
Two or more identifiers or other values are said to beassociable by an entity if it is possible - with a reasonable amount of time and effort - for the referenced entity or set of entities to correlate or associate them without participation of additional entity(ies). Otherwise, the values arenon-associable by an entity.
Two or more identifiers or other values are said to benon-associable by the application if they arenon-associable by an entity where the entity is the set that includes the application, all other applications, and other entities such as servers that they use or with which they communicate. Otherwise, the values would be consideredassociable by the application, which is forbidden.
A Distinctive Value is a value, piece of data, implication of the possession of a piece of data, or an observable behavior or timing that isnot shared across a large population of users or client devices. A Distinctive Value may be in memory or persisted.
Examples of Distinctive Values include but are not limited to:
Other identifiers
Other session data
While a Distinctive Value is typically unique to a user or client device, a value does not need to be strictly unique to be distinctive. For example, a value shared among a small number of users could still be distinctive.
A Permanent Identifier is a value, piece of data, implication of the possession of a piece of data, or an observable behavior or timing that is indelible in some way or otherwise non-trivial for the user to remove, reset, or change. This includes but is not limited to:
A hardware or hardware-based identifier
A value provisioned in the hardware device in the factory
A value associated with or derived from the operating system installation instance
A value associated with or derived from the user agent installation instance
A value associated with or derived from theCDM or other software component
A value in a configuration file or similar semi-permanent data, even if generated on the client
Client or other user account values
ADistinctive Permanent Identifier is aPermanent Identifier that isdistinctive.
When exposed outside the client, Distinctive Permanent Identifiers and values derived from or otherwise related to themMUST beencrypted. Distinctive Permanent IdentifiersMUST NOT ever be exposed to the application, even in encrypted form.
While a Distinctive Permanent Identifier is typically unique to a user or client device, a Distinctive Permanent Identifier does not need to be strictly unique to be distinctive. For example, a Distinctive Permanent Identifier shared among a small number of users could still be distinctive.
A Distinctive Permanent Identifier isnot aDistinctive Identifier because it is not derived or generated (within the scope of this specification).
distinctiveIdentifier
controls whether Distinctive Permanent Identifiers may be used. Specifically, Distinctive Permanent Identifiers may only be used when the value of thedistinctiveIdentifier
member of theMediaKeySystemAccess
used to create theMediaKeys
object is "required
".
A Distinctive Identifier is a value, including in opaque or encrypted form, for which it is possible for any entity external to the client to correlate or associate values beyond what a user may expect on the web platform (e.g., cookies and other site data). For example, values that areassociable by an entity other than the application across a)origins, b)browsing profiles, or c) browsing sessions even after the user has attempted to protect his or her privacy by clearing browsing data or values for which it is not easy for a user to break such association. In particular, a value is a Distinctive Identifier if it is possible for acentral server, such as an individualization server, to associate values across origins, such as because theindividualization requests contained a common value, or because values provided in individualization requests areassociable by such a server even after attempts to clear browsing data. Possible causes of this include use ofDistinctive Permanent Identifier(s) in the individualization process.
Distinctive Identifiers exposed to the application, even in encrypted form,MUST adhere to theidentifier requirements, including beingencrypted,unique per origin and profile, andclearable.
While the instantiation or use of a Distinctive Identifier is triggered by the application's use of the APIs defined in this specification, the identifier need not be provided to the application to trigger conditions related to Distinctive Identifiers. (TheDistinctive Permanent Identifier(s)MUST NOT ever be provided to the application, even in opaque or encrypted form.)
distinctiveIdentifier
controls whether Distinctive Identifiers may be used. Specifically, Distinctive Identifiers may only be used when the value of thedistinctiveIdentifier
member of theMediaKeySystemAccess
used to create theMediaKeys
object is "required
".
A Distinctive Identifier is a value, piece of data, implication of the possession of a piece of data, or an observable behavior or timing for which all of the following criteria hold:
It isdistinctive.
While a Distinctive Identifier is typically unique to a user or client device, an identifier does not need to be strictly unique to be distinctive. For example, an identifier shared among a small number of users could still be distinctive.
It, information about it, or values derived from or otherwise related to it are exposed, even in encrypted form, outside the client. This includes but is not limited to providing it to the application and/or license,individualization, or other server.
It has one or more the following properties:
It is derived from one or moreDistinctive Permanent Identifier(s).
The generation,individualization, provisioning or other process that produced the value involved, used, provided, derived from, or similarly involved one or moreDistinctive Permanent Identifier(s) or another Distinctive Identifier.
It isclearable but notalong with cookies and other site data.
For example, via some mechanism external to the user agent, such as an OS-level mechanism.
Other properties of concern that are normatively prohibited for values exposed to the application include:
It is aDistinctive Permanent Identifier.
It isnotclearable.
Value(s) created afterclearing identifier(s) may beassociable by the application with previous value(s).
Values may not beunique per origin and profile.
Values for different origins may beassociable by the application.
Examples of such normatively prohibited values include but is not limited to:
A single hardware-based value used for all origins.
A single random based value used for all origins.
A single value obtained from anindividualization process that is used for all origins.
Values that include all or part of any of the above values.
A single value that is used for multiple but not all origins.
A single value that is used for all origins on a domain. (Identifiers must be per-origin.)
A pre-provisioned origin-specific value.
Values generated by trivially-reversible means, which are thusassociable by the application, regardless of whether generated on the client or involving anindividualization process. For example, XORing or otherwise integrating (part of) the origin with a fixed value.
While Distinctive Identifier are usuallyassociable by the entity that generated them theyMUST benon-associable by applications. In other words, such correlation or association is only possible by the entity, such as anindividualization server, that originally generated the Distinctive Identifier values. Entities with access to theDistinctive Permanent Identifier(s)MUST NOT expose this capability to applications, as this would make resulting Distinctive Identifiersassociable by the application, andSHOULD take care to avoid exposing such correlation to other entities or third parties.
Examples of Distinctive Identifiers include but are not limited to:
A series of bytes that is included in key requests, different from the series of bytes included by other client devices, and based on or was acquired directly or indirectly using aDistinctive Permanent Identifier.
A public key included in key requests that is different from the public keys included in the requests by other client devices and is based on or was acquired directly or indirectly using aDistinctive Permanent Identifier.
Demonstration of possession of a private key (e.g., by signing some data) that other client devices do not have and is based on or was acquired directly or indirectly using aDistinctive Permanent Identifier.
An identifier for such a key.
Such a value used to derive another value that is exposed even though the first value is not directly exposed.
A value derived from another Distinctive Identifier.
A random value that was reported to a (e.g.,individualization) server along with aDistinctive Permanent Identifier or provided by such a server after providing aDistinctive Permanent Identifier.
A value derived from a unique value provisioned in the hardware device in the factory.
A value derived from a unique hardware value (e.g., MAC address or serial number) or software value (e.g., operating system installation instance or operating system user account name) in the hardware device in the factory.
A value derived from a unique value embedded in theCDM binary or other file used by theCDM.
Examples of things that arenot Distinctive Identifiers:
A public key shared among all copies of a givenCDM version if the installed base is large.
A nonce or ephemeral key that is unique but used in only one session.
A value that is not exposed, even in derived or similar ways, outside the client, including viaindividualization or similar.
Device-unique keys used in attestations between, for example, the video pipeline and theCDM when theCDM does not let these attestations further flow to the application and instead makes a new attestation on its own using a key that does not constitute a Distinctive Identifier.
A value that is fully cleared/clearable along with browsing data, such as cookies, after which it will be replaced by a value that isnon-associable] (not justnon-associable by applications), even by a central server such as anindividualization server, AND one or more of the following:
NoDistinctive Permanent Identifier or Distinctive Identifier was involved in the generation of the value.
It is a random value generatedwithout inputs from the system.
It is a value provided by a server without the use of or knowledge of another Distinctive Identifier.
An implementation, configuration, instance, or objectuses Distinctive Identifier(s) if, at any time during its lifetime or the lifetime of related such entities, it exposes, even in encrypted form, one or moreDistinctive Identifier(s), information about them, or values derived from or otherwise related to them outside the client. This includes but is not limited to providing such a value to the application and/or license,individualization, or other server.
An implementation, configuration, instance, or objectuses Distinctive Permanent Identifier(s) if, at any time during its lifetime or the lifetime of related such entities, it exposes, even in encrypted form, one or moreDistinctive Permanent Identifier(s), information about them, or values derived from or otherwise related to them outside the client. This includes but is not limited to providing such a value to anindividualization server. Such valuesMUST NOT be provided to the application.
An implementation, configuration, instance, or object uses Distinctive Identifier(s) or Distinctive Permanent Identifier(s) if ituses Distinctive Identifier(s) and/oruses Distinctive Permanent Identifier(s).
distinctiveIdentifier
controls whetherDistinctive Identifiers andDistinctive Permanent Identifiers may be used. Specifically, such identifiers may only be used when the value of thedistinctiveIdentifier
member of theMediaKeySystemAccess
used to create theMediaKeys
object is "required
".
During playback, embedded media data is exposed to script in the embeddingorigin. In order for the API to provideInitialization Data in the
event,media dataMUST beCORS-same-origin with the embedding page. Ifmedia data is cross-origin with the embedding document, authorsSHOULD use theencrypted
crossOrigin
attribute on theHTMLMediaElement
and CORS headers on themedia data response to make itCORS-same-origin.
During playback, embedded media data is exposed to script in the embeddingorigin. In order for the API to provideInitialization Data in the
event,media dataMUST NOT beMixed Content [MIXED-CONTENT].encrypted
TimeMUST be equivalent to that represented inECMAScriptTime Values and Time Range [ECMA-262].
Time will equalNaN
if no such time exists or if the time is indeterminate. It should never have the valueInfinity
.
Time generally represents an instant in time with millisecond accuracy; however, that alone is not a sufficient definition. The defined Time Values and Time Range reference adds other important requirements.
Thetime after which key(s) will no longer beusable for decryption.
A User Agent on a given machine may support execution in a variety of different contexts or modes or temporary states that are expected to behave independently with respect to application-visible state and data. In particular, all stored data is expected to be independent. In this specification we refer to such independent contexts or modes as "Browsing Profiles".
Examples of such independent contexts include if the user agent is running in different operating system user accounts or if the user agent provides the capability to define multiple independent profiles for a single account.
This section defines the mechanism for obtaining access to aKey System. The inclusion of capabilities in the request also enables feature detection.
The steps of an algorithm are always aborted when rejecting a promise.
requestMediaKeySystemAccess
()
is apolicy-controlled feature identified by the stringencrypted-media
. Itsdefault allowlist is'self'
[PERMISSIONS-POLICY].
WebIDL[Exposed=Window]partial interfaceNavigator
{ [SecureContext]Promise<MediaKeySystemAccess
>requestMediaKeySystemAccess
(DOMStringkeySystem,sequence<MediaKeySystemConfiguration
>supportedConfigurations);};
requestMediaKeySystemAccess()
Calling this method may haveuser-visible effects, including requests for user consent. This method should only be called when the author intends to create and use aMediaKeys
object with the provided configuration.
Requests access to the specifiedKey System. The configuration specified by at least one of its elements must be supported. The resultingMediaKeySystemAccess
will correspond to the first such element.
Any permission checks or user interaction, such as a prompt for consent,MUST be performed before resolving the promise.
If thekeySystem
is not supported or not allowed (in at least one of thesupportedConfigurations
), the promise is rejected. Otherwise, it is resolved with a newMediaKeySystemAccess
object.
This method is only exposed tosecure contexts as indicated by the[SecureContext]
IDL attribute.
Requiring Secure Contexts isnot a replacement for other security- and privacy-related requirements and recommendations. ImplementationsMUST meet all related requirements andSHOULD follow related recommendations such that the risks on in an secure context would be similar.
When this method is invoked, the user agentMUST run the following steps:
Ifthis'srelevant global object'sassociated Document is notallowed to use the
feature, then throw a "encrypted-media
SecurityError
"DOMException
and abort these steps.
IfkeySystem is the empty string, return a promise rejected with a newly created
.TypeError
IfsupportedConfigurations is empty, return a promise rejected with a newly created
.TypeError
Letdocument be the calling context'sDocument.
Letorigin be theorigin ofdocument.
Letpromise be a new promise.
Run the following steps in parallel:
IfkeySystem is not one of theKey Systems supported by the user agent, rejectpromise with a
. String comparison is case-sensitive.NotSupportedError
Letimplementation be the implementation ofkeySystem.
For each value insupportedConfigurations
:
Letcandidate configuration be the value.
Letsupported configuration be the result of executing theGet Supported Configuration algorithm onimplementation,candidate configuration, andorigin.
Ifsupported configuration is notNotSupported
, run the following steps:
Letaccess be a newMediaKeySystemAccess
object, and initialize it as follows:
Set thekeySystem
attribute tokeySystem.
Let theconfiguration value besupported configuration.
Let thecdm implementation value beimplementation.
Resolvepromise withaccess and abort the parallel steps of this algorithm.
Rejectpromise with a
.NotSupportedError
keySystem
was not supported/allowed or none of the configurations insupportedConfigurations
were supported/allowed.
Returnpromise.
Given aKey Systems implementationimplementation,MediaKeySystemConfiguration
candidate configuration, andorigin, this algorithm returns a supported configuration orNotSupported
as appropriate.
Unrecognized dictionary members incandidate configuration are ignored per [WEBIDL] and will never reach this algorithm. Thus, they cannot be considered as part of the configuration.
For certain configurations, it may be required to obtain user consent or inform the user. User Agents have some flexibility to determine whether consent is required for a specific configuration and whether such consent may also apply to other configurations. For example, consent to one configuration may also imply consent for less powerful, more restricted configurations. Equally, a denial of consent for one configuration may imply denial of consent for more powerful, less restricted configurations.
Supported configurations, including supported audio and video codecs, may depend on availability of optional capabilities such asDistinctive Identifier(s) and persistent state. The following algorithm iteratively tries to find a configuration that is both supported and has user consent (or does not need consent).
User Agents should reuse earlier consent responses, when appropriate, at least for the duration of therequestMediaKeySystemAccess
()
algorithm in order to avoid repeated requests to the user for similar configurations.
The variablerestrictions in the steps below represents the configurations for which consent has been denied during the execution of this algorithm or based on persisted consent information for the origin. It is used to determine whether user consent for a candidate configuration or accumulated configuration has been denied. Consent is denied for an accumulated configuration if every derived configuration has already been denied. Internal representation ofrestrictions is implementation-specific.
Letsupported configuration beConsentDenied
.
Initializerestrictions to indicate that no configurations have had user consent denied.
Repeat the following step whilesupported configuration isConsentDenied
:
Letsupported configuration and, if provided,restrictions be the result of executing theGet Supported Configuration and Consent algorithm withimplementation,candidate configuration,restrictions andorigin.
Returnsupported configuration.
Given aKey Systems implementationimplementation,MediaKeySystemConfiguration
candidate configuration,restrictions andorigin, this algorithm returns a supported configuration,NotSupported
, orConsentDenied
as appropriate and, in theConsentDenied
case,restrictions.
Letaccumulated configuration be a newMediaKeySystemConfiguration
dictionary.
Set thelabel
member ofaccumulated configuration to equal thelabel
member ofcandidate configuration.
If theinitDataTypes
member ofcandidate configuration is non-empty, run the following steps:
Letsupported types be an empty sequence ofDOMString
s.
For each value incandidate configuration'sinitDataTypes
member:
LetinitDataType be the value.
If theimplementation supports generating requests based oninitDataType, addinitDataType tosupported types. String comparison is case-sensitive. The empty string is never supported.
TheinitDataTypeMUST be supported independent of content types in order to avoid unexpectedly rejecting the configuration in later steps. Support forinitDataType includes both license generation and, when appropriate, extraction from media data. SeeInitialization Data Type Support requirements.
Ifsupported types is empty, returnNotSupported
.
Set theinitDataTypes
member ofaccumulated configuration tosupported types.
Letdistinctive identifier requirement be the value ofcandidate configuration'sdistinctiveIdentifier
member.
Ifdistinctive identifier requirement is "optional
" andDistinctive Identifiers are not allowed according torestrictions, setdistinctive identifier requirement to "not-allowed
".
Follow the steps fordistinctive identifier requirement from the following list:
required
" If theimplementation does not supportuse of Distinctive Identifier(s) in combination withaccumulated configuration andrestrictions, returnNotSupported
.
optional
"Continue with the following steps.
not-allowed
" If theimplementation requiresuse of Distinctive Identifier(s) or Distinctive Permanent Identifier(s) in combination withaccumulated configuration andrestrictions, returnNotSupported
.
The combination ofaccumulated configuration andrestrictions means all the possible configurations that include everything inaccumulated configuration and that are not denied according torestrictions.
A feature is supported by an implementation with this combination if the implementation supports at least one of the configurations in the combination with the feature.
A feature is required by an implementtion with this combination if all configurations in the combination that are suported by the implementation include the feature.
Set thedistinctiveIdentifier
member ofaccumulated configuration to equaldistinctive identifier requirement.
Letpersistent state requirement be equal to the value ofcandidate configuration'spersistentState
member.
Ifpersistent state requirement is "optional
" and persisting state is not allowed according torestrictions, setpersistent state requirement to "not-allowed
".
Follow the steps forpersistent state requirement from the following list:
required
" If theimplementation does not support persisting state in combination withaccumulated configuration andrestrictions, returnNotSupported
.
optional
"Continue with the following steps.
not-allowed
" If theimplementation requires persisting state in combination withaccumulated configuration andrestrictions, returnNotSupported
.
Set thepersistentState
member ofaccumulated configuration to equal the value ofpersistent state requirement.
Follow the steps for the first matching condition from the following list:
sessionTypes
member ispresent [Infra] incandidate configuration Letsession types becandidate configuration'ssessionTypes
member.
Letsession types be[ "
.temporary
" ]
For each value insession types:
Letsession type be the value.
Ifaccumulated configuration'spersistentState
value is "not-allowed
" and theIs persistent session type? algorithm returnstrue
forsession type returnNotSupported
.
If theimplementation does not supportsession type in combination withaccumulated configuration andrestrictions for other reasons, returnNotSupported
.
Ifaccumulated configuration'spersistentState
value is "optional
" and the result of running theIs persistent session type? algorithm onsession type istrue
, changeaccumulated configuration'spersistentState
value to "required
".
Set thesessionTypes
member ofaccumulated configuration tosession types.
If thevideoCapabilities
andaudioCapabilities
members incandidate configuration are both empty, returnNotSupported
.
videoCapabilities
member incandidate configuration is non-empty: Letvideo capabilities be the result of executing theGet Supported Capabilities for Audio/Video Type algorithm on Video,candidate configuration'svideoCapabilities
member,accumulated configuration, andrestrictions.
Ifvideo capabilities isnull
, returnNotSupported
.
Set thevideoCapabilities
member ofaccumulated configuration tovideo capabilities.
Set thevideoCapabilities
member ofaccumulated configuration to an empty sequence.
audioCapabilities
member incandidate configuration is non-empty: Letaudio capabilities be the result of executing theGet Supported Capabilities for Audio/Video Type algorithm on Audio,candidate configuration'saudioCapabilities
member,accumulated configuration, andrestrictions.
Ifaudio capabilities isnull
, returnNotSupported
.
Set theaudioCapabilities
member ofaccumulated configuration toaudio capabilities.
Set theaudioCapabilities
member ofaccumulated configuration to an empty sequence.
Ifaccumulated configuration'sdistinctiveIdentifier
value is "optional
", follow the steps for the first matching condition from the following list:
Changeaccumulated configuration'sdistinctiveIdentifier
value to "required
".
Changeaccumulated configuration'sdistinctiveIdentifier
value to "not-allowed
".
Ifaccumulated configuration'spersistentState
value is "optional
", follow the steps for the first matching condition from the following list:
Changeaccumulated configuration'spersistentState
value to "required
".
Changeaccumulated configuration'spersistentState
value to "not-allowed
".
Ifimplementation in the configuration specified by the combination of the values inaccumulated configuration is not supported or not allowed in theorigin, returnNotSupported
.
In this step, "supported" includes the implementation being available for use when this algorithm returns, not just user agent support for such an implementation.
Ifaccumulated configuration'sdistinctiveIdentifier
value is "required
" and theDistinctive Identifier(s) associated withaccumulated configuration are notunique per origin and profile andclearable:
Updaterestrictions to reflect that all configurations described byaccumulated configuration do not have user consent.
ReturnConsentDenied
andrestrictions.
The "unique per origin and profile" and "clearable" conditions cannot be false in a compliant implementation because implementationsMUSTuse per-origin per-profile identifiers andallow the user to clear identifier.
Letconsent status andupdated restrictions be the result of running theGet Consent Status algorithm onaccumulated configuration,restrictions andorigin and follow the steps for the value ofconsent status from the following list:
ConsentDenied
: ReturnConsentDenied
andupdated restrictions.
InformUser
: Inform the user thataccumulated configuration is in use in theorigin including, specifically, the information thatDistinctive Identifier(s) and/orDistinctive Permanent Identifier(s) as appropriate will be used if thedistinctiveIdentifier
member ofaccumulated configuration is "required
". Continue to the next step.
Allowed
:Continue to the next step.
Returnaccumulated configuration.
Given anaudio/video type,MediaKeySystemMediaCapability
sequencerequested media capabilities,MediaKeySystemConfiguration
accumulated configuration, andrestrictions, this algorithm returns a sequence of supportedMediaKeySystemMediaCapability
values for this audio/video type ornull
as appropriate.
Letlocal accumulated configuration be a local copy ofaccumulated configuration.
Letsupported media capabilities be an empty sequence ofMediaKeySystemMediaCapability
dictionaries.
For eachrequested media capability inrequested media capabilities:
Letcontent type berequested media capability'scontentType
member.
Letencryption scheme berequested media capability’sencryptionScheme
member.
Letrobustness berequested media capability'srobustness
member.
Ifcontent type is the empty string, returnnull
.
LetmimeType be the result of runningparse a MIME type withcontent type.
IfmimeType isfailure
or is unrecognized, continue to the next iteration.
Letcontainer be the container type specified bymimeType.
If the user agent does not supportcontainer, continue to the next iteration. The case-sensitivity of string comparisons is determined by the appropriate RFC.
Per RFC 6838 [RFC6838], "Both top-level type and subtype names are case-insensitive."
Letparameters be the "codecs" and "profiles" RFC 6381 [RFC6381] parameters, if any, ofmimeType.
If the user agent does not recognize one or moreparameters, or if any parameters are not valid per the relevant specification, continue to the next iteration.
Letmedia types be the set of codecs and codec constraints specified byparameters. The case-sensitivity of string comparisons is determined by the appropriate RFC or other specification.
Case-sensitive string comparison isRECOMMENDED because RFC 6381 [RFC6381] says, "Values are case sensitive" for some formats.
Ifmedia types is empty:
Letparameters be that set.
Continue to the next iteration.
IfmimeType is not strictly anaudio/video type, continue to the next iteration.
For example, ifaudio/video type is Video andmimeType'stype is not "video" ormedia types contains non-video codecs.
Ifencryption scheme is non-null and is not recognized or not supported byimplementation, continue to the next iteration.
Ifrobustness is not the empty string and contains an unrecognized value or a value not supported byimplementation, continue to the next iteration. String comparison is case-sensitive.
If the user agent andimplementation definitely support playback of encryptedmedia data for the combination ofcontainer,media types,encryption scheme,robustness andlocal accumulated configuration in combination withrestrictions:
requested media capability (content type and robustness) must be supported when used together with all previously added requested media capabilities.
Addrequested media capability tosupported media capabilities.
This step ensures that the values of the members of entries insupported media capabilities are exactly the strings supplied inrequested media capability without modification by the User Agent.
Addrequested media capability to thevideoCapabilities
member oflocal accumulated configuration.
Addrequested media capability to theaudioCapabilities
member oflocal accumulated configuration.
This step ensures that configurations are always checked with configurations from previous iterations, including from previous calls to this algorithm. Otherwise, only configurations from previous calls to this algorithm would be checked in subsequent calls.
Ifsupported media capabilities is empty, returnnull
.
None of theMediaKeySystemMediaCapability
elements inrequested media capabilities is supported in combination withaccumulated configuration.
Returnsupported media capabilities.
Given anaccumulated configuration,restrictions andorigin, this algorithm returns the consent status foraccumulated configuration andorigin as one ofConsentDenied
,InformUser
orAllowed
, together with an updated value forrestrictions in theConsentDenied
case.
Consent status foraccumulated configuration depends at least on the value of thedistinctiveIdentifier
member ofaccumulated configuration.
Previous consent foraccumulated configuration withdistinctiveIdentifier
set to "not-allowed
" does not imply consent for the same configuration withdistinctiveIdentifier
set to "optional
" or "required
".
If there is persisted denial fororigin indicating thataccumulated configuration is not allowed, run the following steps:
Updaterestrictions to reflect the configurations for which consent has been denied.
ReturnConsentDenied
andrestrictions.
If there is persisted consent fororigin indicatingaccumulated configuration is allowed, returnAllowed
.
If any of the following are true:
ThedistinctiveIdentifier
member ofaccumulated configuration is not "not-allowed
" and the combination of the User Agent,implementation andaccumulated configuration does not follow all the recommendations ofAllow Persistent Data to Be Cleared with respect toDistinctive Identifier(s).
The user agent requires explicit user consent for theaccumulated configuration for other reasons.
Another reason for requiring explicit user consent may be due to the security properties of theCDM implementation.
then run the following steps:
Request user consent to useaccumulated configuration in theorigin and wait for the user response.
The consentMUST include consent to use aDistinctive Identifier(s) and/orDistinctive Permanent Identifier(s) as appropriate ifaccumulated configuration'sdistinctiveIdentifier
member is "required
".
User consent to useaccumulated configuration is specific to theorigin and may be limited to configurations sharing certain properties withaccumulated configuration.
If consent was denied, run the following steps:
Updaterestrictions to reflect the configurations for which consent was denied.
ReturnConsentDenied
andrestrictions.
If thedistinctiveIdentifier
member ofaccumulated configuration is not "not-allowed
", returnInformUser
.
If the user agent requires informing the user for theaccumulated configuration for other reasons, returnInformUser
.
ReturnAllowed
.
WebIDLenumMediaKeysRequirement
{"required
","optional
","not-allowed
"};
TheMediaKeysRequirement
enumeration is defined as follows:
Enumeration description | |
---|---|
required |
|
optional |
|
not-allowed |
|
WebIDLdictionaryMediaKeySystemConfiguration
{DOMStringlabel
= "";sequence<DOMString>initDataTypes
= [];sequence<MediaKeySystemMediaCapability
>audioCapabilities
= [];sequence<MediaKeySystemMediaCapability
>videoCapabilities
= [];MediaKeysRequirement
distinctiveIdentifier
= "optional";MediaKeysRequirement
persistentState
= "optional";sequence<DOMString>sessionTypes
;};
The dictionaryMediaKeySystemConfiguration
contains the following members:
label
of typeDOMString
, defaulting to""
MediaKeySystemConfiguration
returned from thegetConfiguration
()
method ofMediaKeySystemAccess
.initDataTypes
of typesequence<DOMString
>, defaulting to[]
audioCapabilities
of typesequence<MediaKeySystemMediaCapability
>, defaulting to[]
videoCapabilities
element must not be empty.videoCapabilities
of typesequence<MediaKeySystemMediaCapability
>, defaulting to[]
audioCapabilities
element must not be empty.distinctiveIdentifier
of typeMediaKeysRequirement
, defaulting to"optional"
When this member is "not-allowed
", the implementationMUST NOTuse Distinctive Identifier(s) or Distinctive Permanent Identifier(s) for any operations associated with any object created from this configuration.
persistentState
of typeMediaKeysRequirement
, defaulting to"optional"
TheCDMMUST NOT persist any state related to the application ororigin of this object'sDocument when this member is "not-allowed
".
For the purposes of this member, persistent state does not include persistent unique identifiers (Distinctive Identifiers) controlled by theKey System implementation.distinctiveIdentifier
independently reflects this requirement.
Only "temporary
" sessions may be created when persistent state is not supported.
For "temporary
" sessions, the need and ability to store state isKey System implementation-specific and may vary by feature used.
Applications intending to create non-"temporary
" sessions, should set this member to "required
" when callingrequestMediaKeySystemAccess
()
.
sessionTypes
of typesequence<DOMString
>MediaKeySessionType
s that must be supported. All values must be supported. If this member isnot present [Infra] when the dictionary is passed torequestMediaKeySystemAccess
()
, the dictionary will be treated as if this member is set to[ "
.temporary
" ]
ImplementationsSHOULD NOT add members to this dictionary. Should member(s) be added, theyMUST be of typeMediaKeysRequirement
, and it isRECOMMENDED that they have default values of "optional
" to support the widest range of application and client combinations.
Dictionary members not recognized by a user agent implementation are ignored per [WEBIDL] and will not be considered in therequestMediaKeySystemAccess
()
algorithm. Should an application use non-standard dictionary member(s), itMUST NOT rely on user agent implementations rejecting a configuration that includes such dictionary members.
This dictionaryMUST NOT be used to pass state or data to theCDM.
WebIDLdictionaryMediaKeySystemMediaCapability
{DOMStringcontentType
= "";DOMString?encryptionScheme
= null;DOMStringrobustness
= "";};
MediaKeySystemMediaCapability
MemberscontentType
of typeDOMString
, defaulting to""
TheMIME type of themedia resource.
ApplicationsSHOULD ensure that the MIME type explicitly specifies codecs and codec constraints (e.g., per [RFC6381]) unless these are normatively implied by the container.
encryptionScheme
of typeDOMString
, defaulting tonull
The encryption scheme associated with the content type. A value which is null or not present indicates to the user agent that no specific encryption scheme is required by the application, and therefore any encryption scheme is acceptable.
Applications that are aware of this fieldSHOULD specify the encryption schemes they require, since different encryption schemes are generally incompatible with one another. It is unrealistic for an application to be accepting of "any" encryption scheme, but the default of null and the interpretation of null as "any" provide backward compatibility for unaware applications and a path to a polyfill for older user agents.
The empty string is distinct from null or not present, and so would be treated as an unrecognized encryption scheme.
Well-known values for encryptionScheme are:
cenc
: The "cenc" mode, defined in [CENC], section 4.2a. AES-CTR mode full sample and video NAL subsample encryption.cbcs
: The "cbcs" mode, defined in [CENC], section 4.2d. AES-CBC mode partial video NAL pattern encryption. For video, the spec allows various encryption patterns.cbcs-1-9
: The same as"cbcs"
mode, but with a specific encrypt:skip pattern of 1:9 for video, as recommended in [CENC], section 10.4.2.robustness
of typeDOMString
, defaulting to""
The robustness level associated with the content type. The empty string indicates that any ability to decrypt and decode the content type is acceptable.
ImplementationsMUST configure theCDM to support at least the robustness levels specified in the configuration of theMediaKeySystemAccess
object used to create theMediaKeys
object. Exact configuration of theCDM is implementation-specific, and implementationsMAY configure theCDM to use the highest robustness level in the configuration even if a higher robustness level is available. If only the empty string is specified, implementationsMAY be configured to use the lowest robustness level the implementation supports.
ApplicationsSHOULD specify the robustness level(s) they require to avoid unexpected client incompatibilities.
In order for the capability represented by this object to be considered supported,contentType
MUST NOT be the empty string and its entire value, including all codecs,MUST be supported withrobustness
.
If any of a set of codecs is acceptable, use a separate instances of this dictionary for each codec.
TheMediaKeySystemAccess
object provides access to aKey System.
WebIDL[Exposed=Window,SecureContext] interfaceMediaKeySystemAccess
{ readonly attributeDOMStringkeySystem
;MediaKeySystemConfiguration
getConfiguration
();Promise<MediaKeys
>createMediaKeys
();};
keySystem
of typeDOMString
, readonlygetConfiguration()
Returns the supported combination of configuration options selected by therequestMediaKeySystemAccess
()
algorithm.
The returned object is a non-strict subset (plus any implied defaults) of the first satisfiableMediaKeySystemConfiguration
configuration passed to therequestMediaKeySystemAccess
()
call that returned the promise that was resolved with this object. It does not contain values for capabilities not specified in that single configuration (other than implied defaults) and thus may not reflect all capabilities of theKey System implementation. All values in the configuration may be used in any combination. Members of typeMediaKeysRequirement
reflect whether the capability is required for any combination. They will not have the value "optional
".
When this method is invoked, the user agentMUST run the following steps:
Return this object'sconfiguration value.
This results in a new object being created and initialized fromconfiguration each time this method is called.
IfencryptionScheme
was not given by the application, the accumulatedconfigurationMUST still contain anencryptionScheme
field with a value ofnull
, so that polyfills can detect the user agent's support for the field without specifying specific values.
createMediaKeys()
Creates a newMediaKeys
object forkeySystem.
When this method is invoked, the user agentMUST run the following steps:
Letpromise be a new promise.
Run the following steps in parallel:
Letconfiguration be the value of this object'sconfiguration value.
Letuse distinctive identifier betrue
if the value ofconfiguration'sdistinctiveIdentifier
member is "required
" andfalse
otherwise.
Letpersistent state allowed betrue
if the value ofconfiguration'spersistentState
member is "required
" andfalse
otherwise.
Load and initialize theKey System implementation represented by this object'scdm implementation value if necessary.
Letinstance be a new instance of theKey System implementation represented by this object'scdm implementation value.
Initializeinstance to enable, disable and/or selectKey System features usingconfiguration.
Ifuse distinctive identifier isfalse
, preventinstance fromusing Distinctive Identifier(s) and Distinctive Permanent Identifier(s).
Ifpersistent state allowed isfalse
, preventinstance from persisting any state related to the application ororigin of this object'sDocument.
If any of the preceding steps failed, rejectpromise with a newDOMException
whose name is the appropriateerror name.
Letmedia keys be a newMediaKeys
object, and initialize it as follows:
Let theuse distinctive identifier value beuse distinctive identifier.
Let thepersistent state allowed value bepersistent state allowed.
Let thesupported session types value be be the value ofconfiguration'ssessionTypes
member.
Let thecdm implementation value be this object'scdm implementation value.
Let thecdm instance value beinstance.
Resolvepromise withmedia keys.
Returnpromise.
TheMediaKeys
object represents a set of keys that an associatedHTMLMediaElement
can use for decryption ofmedia data during playback. It also represents aCDM instance.
AMediaKeys
object may be destroyed by the user agent when it is no longer accessible
For example, when there are no script references and no attached media element.
For methods that return a promise, all errors are reported asynchronously by rejecting the returned Promise. This includes [WEBIDL] type mapping errors.
The steps of an algorithm are always aborted when rejecting a promise.
WebIDLenumMediaKeySessionType
{"temporary
","persistent-license
"};
TheMediaKeySessionType
enumeration is defined as follows:
Enumeration description | |
---|---|
temporary | A session for which the license, key(s) and record of or data related to the session are not persisted. The application need not worry about managing such storage. Support for this session type isREQUIRED. |
persistent-license | A session for which the license (and potentially other data related to the session) will be persisted. Arecord of license destructionSHALL be persisted when the license and key(s) it contains are destroyed. Therecord of license destruction is aKey System-specific attestation that the license and key(s) it contains are no longer usable by the client. Support for this session type isOPTIONAL. Sessions of this type can only be created if the configuration associated with the The application is responsible for ensuring that data persisted for such sessions is removed when the application no longer needs it. SeeSession Storage and Persistence. |
WebIDL[Exposed=Window,SecureContext] interfaceMediaKeys
{MediaKeySession
createSession
(optionalMediaKeySessionType
sessionType = "temporary");Promise<MediaKeyStatus
>getStatusForPolicy
(optionalMediaKeysPolicy
policy = {});Promise<boolean>setServerCertificate
(BufferSourceserverCertificate);};
createSession()
Returns a newMediaKeySession
object.
ThesessionType parameter affects the behavior of the returned object.
When this method is invoked, the user agentMUST run the following steps:
If this object'ssupported session types value does not containsessionType,throw [WEBIDL] a
.NotSupportedError
sessionType values for which theIs persistent session type? algorithm returnstrue
will fail if this object'spersistent state allowed value isfalse
.
If the implementation does not supportMediaKeySession
operations in the current state,throw [WEBIDL] an
.InvalidStateError
Some implementations are unable to executeMediaKeySession
algorithms until thisMediaKeys
object is associated with a media element usingsetMediaKeys
()
. This step enables applications to detect this uncommon behavior before attempting to perform such operations.
Letsession be a newMediaKeySession
object, and initialize it as follows:
Let thesessionId
attribute be the empty string.
Let theexpiration
attribute beNaN
.
Let theclosed
attribute be a new promise.
Letkey status be a new emptyMediaKeyStatusMap
object, and initialize it as follows:
Let thesize
attribute be 0.
Let thesession type value besessionType.
Let theuninitialized value be true.
Let thecallable value be false.
Let theclosing or closed value be false.
Let theuse distinctive identifier value be this object'suse distinctive identifier value.
Let thecdm implementation value be this object'scdm implementation.
Let thecdm instance value be this object'scdm instance.
Returnsession.
getStatusForPolicy()
Returns theMediaKeyStatus
for a givenMediaKeysPolicy
.
WebIDLdictionaryMediaKeysPolicy
{DOMStringminHdcpVersion
;};
TheMediaKeysPolicy
dictionary is an object consisting of only optional properties. Each property represents a policy requirement. A policy is said to be fulfilled if theCDM would allow presentation of decrypted media data based on all of the requirements.
The HDCP Policy is represented byminHdcpVersion
. If the system can enable the HDCP version specified or higher, then the policy will result in aMediaKeyStatus
of "usable
". The [EME-HDCP-VERSION-REGISTRY] provides the mapping fromminHdcpVersion
values to HDCP specifications.
The determination of HDCP status should be done in the same way that theCDM would enforce such a restriction during playback. In this way, application developers can get a reasonable hint to allow them to optimize what content they fetch to start playback.
When this method is invoked, the user agentMUST run the following steps:
TypeError
.Letpromise be a new promise.
Queue a task to run the following steps:
For eachdictionary member ofpolicy, run the following steps:
If the key is not a validMediaKeysPolicy
member or the type of the value is incorrect, then rejectpromise with
and abort these steps.TypeError
For eachdictionary member ofpolicy, run the following steps:
If theCDM cannot determine theMediaKeyStatus
for thedictionary member, then rejectpromise with
and abort these steps.NotSupportedError
For eachdictionary member ofpolicy, run the following steps:
If theCDM would block presentation of decrypted media data for thedictionary member, then resolvepromise with "output-restricted
".
Resolvepromise with "usable
".
Returnpromise.
setServerCertificate()
Provides a server certificate to be used to encrypt messages to the license server.
Key Systems that use such certificatesMUST also support requesting the certificate from the server via theQueue a "message" Event algorithm.
This method allows an application to proactively provide a server certificate to implementations that support it to avoid the additional round trip should theCDM request it. It is intended as an optimization, and applications are not required to use it.
The server certificate contents areKey System-specific. ItMUST NOT contain executable code.
When this method is invoked, the user agentMUST run the following steps:
If theKey System implementation represented by this object'scdm implementation value does not support server certificates, return a promise resolved withfalse
.
IfserverCertificate is an empty array, return a promise rejected with a new a newly created
.TypeError
Letcertificate be a copy of the contents of theserverCertificate parameter.
Letpromise be a new promise.
Run the following steps in parallel:
Letsanitized certificate be a validated and/or sanitized version ofcertificate.
The user agent should thoroughly validate the certificate before passing it to theCDM. This may include verifying values are within reasonable limits, stripping irrelevant data or fields, pre-parsing it, sanitizing it, and/or generating a fully sanitized version. The user agent should check that the length and values of fields are reasonable. Unknown fields should be rejected or removed.
Use this object'scdm instance to processsanitized certificate.
If the preceding step failed, rejectpromise with a newDOMException
whose name is the appropriateerror name.
Resolvepromise withtrue
.
Returnpromise.
The Is persistent session type? algorithm is run to determine whether the specified session type supports persistence of any kind. Requests to run this algorithm include aMediaKeySessionType
value.
The following steps are run:
Let thesession type be the specifiedMediaKeySessionType
value.
Follow the steps for the value ofsession type from the following list:
temporary
"false
.persistent-license
"true
. The CDM unavailable algorithm is run to close allMediaKeySession
objects associated with aMediaKeys
object,media keys when theCDM instance becomes unavailable. Requests to run this algorithm include aMediaKeySessionClosedReason
value.
The following steps are run:
Let thereason be the specifiedMediaKeySessionClosedReason
value.
For eachMediaKeySession
created by themedia keys that is notclosed,queue a task to run theSession Closed algorithm on the session with the reasonreason.
This section describes general requirements related to storage and persistence.
If aMediaKeys
object'spersistent state allowed value isfalse
then the object'scdm instanceSHALL NOT persist state or access previously persisted state as a result of operations on this object or any sessions that it creates.
If aMediaKeys
object'spersistent state allowed value istrue
then the object'scdm instanceMAY persist state or access previously persisted state as a result of operations on this object or any sessions that it creates.
Persisted dataMUST always be stored such that only theorigin of this object'sDocument can access it. In addition, the dataMUST only be accessible by the currentbrowsing profile; other browsing profiles, user agents, and applicationsMUST NOT be able to access the stored data. SeeInformation Stored on User Devices.
See10. Security and11. Privacy for additional considerations when supporting persistent storage.
TheMediaKeySession
object represents akey session.
AMediaKeySession
object isclosed if and only if the object'sclosed
attribute has been resolved.
The User AgentSHALL execute theMonitor for CDM State Changes algorithm continuously for eachMediaKeySession
object that is notclosed. TheMonitor for CDM State Changes algorithmMUST be run in parallel to the main event loop but not in parallel to other procedures defined in this specification that are also defined to be run in parallel.
AMediaKeySession
objectSHALL NOT be destroyed andSHALL continue to receive events if it is notclosed and theMediaKeys
object that created it remains accessible. Otherwise, aMediaKeySession
object that is no longer accessibleSHALL NOT receive further events andMAY be destroyed.
The above rule implies that theCDM instance must not be destroyed until allMediaKeys
objects and allMediaKeySession
objects associated with theCDM instance are destroyed.
If aMediaKeySession
object is notclosed when it becomes inaccessible to the page, theCDMSHALL close thekey session associated with the object.
Closing the key session results in the destruction of any license(s) and key(s) that have not been explicitly stored.
Exactly when the key session is closed is an implementation detail, and applicationsSHOULD NOT rely on specific timing. Applications that want to ensure a session is closed before taking some other actionSHOULD callclose
()
and wait for the returned promise to be resolved.
For methods that return a promise, all errors are reported asynchronously by rejecting the returned Promise. This includes [WEBIDL] type mapping errors.
The following steps of an algorithm are always aborted when rejecting a promise.
WebIDLenumMediaKeySessionClosedReason
{"internal-error
","closed-by-application
","release-acknowledged
","hardware-context-reset
","resource-evicted
"};
TheMediaKeySessionClosedReason
enumeration is defined as follows:
Enumeration description | |
---|---|
internal-error | The session was closed because of an unrecoverable error in theCDM. When this occurs, applicationsMUST NOT create new sessions on thisMediaKeys instance. |
closed-by-application | The session was closed by the application calling theclose () method of the session explicitly. |
release-acknowledged | The session was closed because theCDM received arecord of license destruction acknowledgement. |
hardware-context-reset | The session was closed because theCDM's original hardware context was reset. When this occurs, the User AgentMUST allow the application to create new sessions on thisMediaKeys instance.Note This could occur for many reasons, including device hibernation, monitor configuration change, etc. The exact reasons for a hardware context reset are implementation-dependent. |
resource-evicted | The session was closed because the system needed to reclaim resources to allow the creation of other sessions. Note This would imply that the application is running into a device-specific limit on session resources. If the closed session is still needed for some reason, the application developer should consider some strategy to reduce the number of sessions needed or proactively close unneeded sessions. |
WebIDL[Exposed=Window,SecureContext] interfaceMediaKeySession
:EventTarget { readonly attributeDOMStringsessionId
; readonly attributeunrestricted doubleexpiration
; readonly attributePromise<MediaKeySessionClosedReason
>closed
; readonly attributeMediaKeyStatusMap
keyStatuses
; attributeEventHandleronkeystatuseschange
; attributeEventHandleronmessage
;Promise<undefined>generateRequest
(DOMStringinitDataType,BufferSourceinitData);Promise<boolean>load
(DOMStringsessionId);Promise<undefined>update
(BufferSourceresponse);Promise<undefined>close
();Promise<undefined>remove
();};
sessionId
of typeDOMString
, readonlyTheSession ID for this object and the associated key(s) or license(s).
expiration
of typeunrestricted double
, readonly Theexpiration time for all key(s) in the session, orNaN
if no such time exists or if the license explicitly never expires, as determined by theCDM.
This valueMAY change during the session lifetime, such as when an action triggers the start of a window.
closed
of typePromise<MediaKeySessionClosedReason
>, readonlySignals when the object becomesclosed as a result of theSession Closed algorithm being run. This promise can only be fulfilled and is never rejected.
keyStatuses
of typeMediaKeyStatusMap
, readonlyA reference to a read-only map ofkey IDsknown to the session to the current status of the associated key. Each entryMUST have a unique key ID.
The map entries and their values may be updated whenever the event loop spins. The mapMUST NOT ever be inconsistent or partially updated, but it may change between accesses if the event loop spins in between the accesses. Key IDs may be added as the result of aload
()
orupdate
()
call. Key IDs may be removed as the result of aupdate
()
call that removes knowledge of existing keys (or replaces the existing set of keys with a new set). Key IDsMUST NOT be removed because they became unusable, such as due to expiration. Instead, such keysMUST be given an appropriate status, such as "expired
".
Some older platforms may containKey System implementations that do not expose key IDs, making it impossible to provide a compliant user agent implementation. To maximize interoperability, user agent implementations exposing suchCDMsSHOULD implement this member as follows: Whenever a non-empty list is appropriate, such as when thekey session represented by this object may containkey(s), populate the map with a single pair containing the one-byte key ID0
and theMediaKeyStatus
most appropriate for the aggregated status of this object.
onkeystatuseschange
of typeEventHandler
Event handler for the
event.keystatuseschange
onmessage
of typeEventHandler
Event handler for the
event.message
generateRequest()
Generates a license request based on theinitData. A
of type "message
license-request
" or "individualization-request
" will always be queued if the algorithm succeeds and the promise is resolved.
When this method is invoked, the user agentMUST run the following steps:
If this object'sclosing or closed value is true, return a promise rejected with an
.InvalidStateError
If this object'suninitialized value is false, return a promise rejected with an
.InvalidStateError
Let this object'suninitialized value be false.
IfinitDataType is the empty string, return a promise rejected with a newly created
.TypeError
IfinitData is an empty array, return a promise rejected with a newly created
.TypeError
If theKey System implementation represented by this object'scdm implementation value does not supportinitDataType as anInitialization Data Type, return a promise rejected with a
. String comparison is case-sensitive.NotSupportedError
Letinit data be a copy of the contents of theinitData parameter.
Letsession type be this object'ssession type.
Letpromise be a new promise.
Run the following steps in parallel:
If theinit data is not valid forinitDataType, rejectpromise with a newly created
.TypeError
Letsanitized init data be a validated and sanitized version ofinit data.
The user agentMUST thoroughly validate theInitialization Data before passing it to theCDM. This includes verifying that the length and values of fields are reasonable, verifying that values are within reasonable limits, and stripping irrelevant, unsupported, or unknown data or fields. It isRECOMMENDED that user agents pre-parse, sanitize, and/or generate a fully sanitized version of theInitialization Data. If theInitialization Data format specified byinitDataType supports multiple entries, the user agentSHOULD remove entries that are not needed by theCDM. The user agentMUST NOT re-order entries within theInitialization Data.
If the preceding step failed, rejectpromise with a newly created
.TypeError
Ifsanitized init data is empty, rejectpromise with a
.NotSupportedError
Letsession id be the empty string.
Letmessage be null.
Letmessage type be null.
Letcdm be theCDM instance represented by this object'scdm instance value.
Use thecdm to execute the following steps:
If thesanitized init data is not supported by thecdm, rejectpromise with a
.NotSupportedError
Follow the steps for the value ofsession type from the following list:
temporary
"Letrequested license type be a temporary non-persistable license.
The returned license must not be persistable or require persisting information related to it.
persistent-license
"Letrequested license type be a persistable license.
Letsession id be a uniqueSession ID string.
If the result of running theIs persistent session type? algorithm onsession type istrue
, the IDMUST be unique within theorigin of this object'sDocument over time, including across Documents and browsing sessions.
Letmessage be a license request for therequested license type generated based on thesanitized init data interpreted perinitDataType.
ThecdmMUST NOT use any stream-specific data, includingmedia data, not provided via thesanitized init data.
ThecdmSHOULD NOT store session data, including the session ID, at this point. SeeSession Storage and Persistence.
Letmessage type be "license-request
".
Letmessage be the request that needs to be processed before a license request request for therequested license type can be generated based on thesanitized init data.
In a subsequent call toupdate
()
theCDMMUST generate a license request for therequested license type based on thesanitized init data, which is interpreted perinitDataType.
Letmessage type reflect the type ofmessage, either "license-request
" or "individualization-request
".
Queue a task to run the following steps:
If any of the preceding steps failed due to a lack of resources, rejectpromise with
.QuotaExceededError
If any of the preceding steps failed for any other reason, rejectpromise with a newDOMException
whose name is the appropriateerror name.
Set thesessionId
attribute tosession id.
Set this object'scallable value to true.
Resolvepromise withundefined
.
Run theQueue a "message" Event algorithm on thesession, providingmessage type andmessage.
Returnpromise.
load()
Loads the data stored for the specified session into this object.
When this method is invoked, the user agentMUST run the following steps:
If this object'sclosing or closed value is true, return a promise rejected with an
.InvalidStateError
If this object'suninitialized value is false, return a promise rejected with an
.InvalidStateError
Let this object'suninitialized value be false.
IfsessionId is the empty string, return a promise rejected with a newly created
.TypeError
If the result of running theIs persistent session type? algorithm on this object'ssession type isfalse
, return a promise rejected with a newly created
.TypeError
Letpromise be a new promise.
Run the following steps in parallel:
Letsanitized session ID be a validated and/or sanitized version ofsessionId.
The user agent should thoroughly validate the sessionId value before passing it to theCDM. At a minimum, this should include checking that the length and value are reasonable (e.g., not longer than tens of characters and alphanumeric).
If the preceding step failed, or ifsanitized session ID is empty, rejectpromise with a newly created
.TypeError
If there is aMediaKeySession
object that is notclosed in this object'sDocument whosesessionId
attribute issanitized session ID, rejectpromise with a
.QuotaExceededError
In other words, do not create a session if a non-closed session, regardless of type, already exists for thissanitized session ID in this browsing context.
Letexpiration time beNaN
.
Letmessage be null.
Letmessage type be null.
Letcdm be theCDM instance represented by this object'scdm instance value.
Use thecdm to execute the following steps:
If there is no data stored for thesanitized session ID in theorigin, resolvepromise withfalse
and abort these steps.
If the stored session'ssession type is not the same as the currentMediaKeySession
session type, rejectpromise with a newly created
.TypeError
Letsession data be the data stored for thesanitized session ID in theorigin. ThisMUST NOT include data from other origin(s) or that is not associated with an origin.
If there is aMediaKeySession
object that is notclosed in anyDocument and that represents thesession data, rejectpromise with a
.QuotaExceededError
In other words, do not create a session if a non-closed persistent session already exists for thissanitized session ID in any browsing context.
Load thesession data.
If thesession data indicates anexpiration time for the session, letexpiration time be that expiration time.
If a message needs to be sent, execute the following steps:
Letmessage be a message generated based on thesession data.
Letmessage type be the appropriateMediaKeyMessageType
for the message.
Queue a task to run the following steps:
If any of the preceding steps failed, rejectpromise with the appropriateerror name.
Set thesessionId
attribute tosanitized session ID.
Set this object'scallable value to true.
If the loaded session contains information about any keys (there areknown keys), run theUpdate Key Statuses algorithm on thesession, providing each key'skey ID along with the appropriateMediaKeyStatus
.
Should additional processing be necessary to determine with certainty the status of a key, use "status-pending
". Once the additional processing for one or more keys has completed, run theUpdate Key Statuses algorithm again with the actual status(es).
Run theUpdate Expiration algorithm on thesession, providingexpiration time.
Resolvepromise withtrue
.
Ifmessage is not null, run theQueue a "message" Event algorithm on thesession, providingmessage type andmessage.
Returnpromise.
update()
Provides messages, including licenses, to theCDM.
Theresponse parameter contains a message to be provided to theCDM. The contents areKey System-specific. ItMUST NOT contain executable code.
When this method is invoked, the user agentMUST run the following steps:
If this object'sclosing or closed value is true, return a promise rejected with an
.InvalidStateError
If this object'scallable value is false, return a promise rejected with an
.InvalidStateError
Ifresponse is an empty array, return a promise rejected with a newly created
.TypeError
Letresponse copy be a copy of the contents of theresponse parameter.
Letpromise be a new promise.
Run the following steps in parallel:
Letsanitized response be a validated and/or sanitized version ofresponse copy.
The user agent should thoroughly validate the response before passing it to theCDM. This may include verifying values are within reasonable limits, stripping irrelevant data or fields, pre-parsing it, sanitizing it, and/or generating a fully sanitized version. The user agent should check that the length and values of fields are reasonable. Unknown fields should be rejected or removed.
If the preceding step failed, or ifsanitized response is empty, rejectpromise with a newly created
.TypeError
Letmessage be null.
Letmessage type be null.
Letsession closed be false.
Letcdm be theCDM instance represented by this object'scdm instance value.
Use thecdm to execute the following steps:
If the format ofsanitized response is invalid in any way, rejectpromise with a newly created
.TypeError
Processsanitized response, following the stipulation for the first matching condition from the following list:
This includes an initial license, an updated license, and a license renewal message.
Processsanitized response, following the stipulation for the first matching condition from the following list:
temporary
" andsanitized response does not specify that session data, including any license, key(s), or similar session data it contains, should be storedpersistent-license
" andsanitized response contains a persistable license Rejectpromise with a newly created
.TypeError
See alsoSession Storage and Persistence.
State information, including keys, for each sessionMUST be stored in such a way that closing one session does not affect the observable state in other session(s), even if they contain overlapping key IDs.
Whensanitized response contains key(s) and/or related data,cdm will likely store (in memory) the key and related data indexed by key ID.
The replacement algorithm within a session isKey System-dependent.
It isRECOMMENDED thatCDM implementations support a standard and reasonably high minimum number of keys perMediaKeySession
object, including a standard replacement algorithm, and a standard and reasonably high minimum number ofMediaKeySession
objects. This enables a reasonable number of key rotation algorithms to be implemented across user agents and may reduce the likelihood of playback interruptions in use cases that involve various streams in the same element (e.g., adaptive streams, various audio and video tracks) using different keys.
persistent-license
"Run the following steps:
Close thekey session and clearall stored session data associated with this object, including thesessionId
andrecord of license destruction.
Setsession closed to true.
For example,sanitized response may contain information that will be used to generate another
event. In this case, there is no need to verify the contents against thesessionType.message
If a message needs to be sent, execute the following steps:
Letmessage be that message.
Letmessage type be the appropriateMediaKeyMessageType
for the message.
Queue a task to run the following steps:
Run theSession Closed algorithm on this object with reason "release-acknowledged
".
Run the following steps:
If the set of keysknown to theCDM for this object changed or the status of any key(s) changed, run theUpdate Key Statuses algorithm on thesession, providing each known key'skey ID along with the appropriateMediaKeyStatus
.
Should additional processing be necessary to determine with certainty the status of a key, use "status-pending
". Once the additional processing for one or more keys has completed, run theUpdate Key Statuses algorithm again with the actual status(es).
If theexpiration time for the session changed, run theUpdate Expiration algorithm on thesession, providing the new expiration time.
If any of the preceding steps failed, rejectpromise with a newDOMException
whose name is the appropriateerror name.
Ifmessage is not null, run theQueue a "message" Event algorithm on thesession, providingmessage type andmessage.
Resolvepromise withundefined
.
Returnpromise.
close()
Indicates that the application no longer needs the session and theCDM should release any resources associated with the session and close it. Persisted data should not be released or cleared.
The returned promise is resolved when the request has been processed, and theclosed
attribute promise is resolved with "closed-by-application
" when the session is closed.
When this method is invoked, the user agentMUST run the following steps:
If this object'sclosing or closed value is true, return a promise resolved withundefined
.
If this object'scallable value is false, return a promise rejected with an
.InvalidStateError
Letpromise be a new promise.
Set this object'sclosing or closed value to true.
Run the following steps in parallel:
Letcdm be theCDM instance represented by this object'scdm instance value.
Usecdm to close thekey session associated with this object.
Closing the key session results in the destruction of any license(s) and key(s) that have not been explicitly stored.
Queue a task to run the following steps:
Resolvepromise withundefined
.
Run theSession Closed algorithm on this object with reason "closed-by-application
".
Returnpromise.
remove()
Removes all license(s) and key(s) associated with the session. Forpersistent session types, other session data will be cleared as defined for each session type once a release message acknowledgment is processed byupdate
()
.
When this method is invoked, the user agentMUST run the following steps:
If this object'sclosing or closed value is true, return a promise rejected with an
.InvalidStateError
If this object'scallable value is false, return a promise rejected with an
.InvalidStateError
Letpromise be a new promise.
Run the following steps in parallel:
Letcdm be theCDM instance represented by this object'scdm instance value.
Letmessage be null.
Letmessage type be null.
Use thecdm to execute the following steps:
If any license(s) and/or key(s) are associated with the session:
Destroy the license(s) and/or key(s) associated with the session.
This implies destruction of the license(s) and/or keys(s) whether they are in memory, persistent store or both.
Follow the steps for the value of this object'ssession type from the following list:
temporary
"Continue with the following steps.
persistent-license
"Letrecord of license destruction be arecord of license destruction for the license represented by this object.
Store therecord of license destruction.
Letmessage be a message containing or reflecting therecord of license destruction.
Queue a task to run the following steps:
Run theUpdate Key Statuses algorithm on thesession, providing allkey ID(s) in the session along with the "released
"MediaKeyStatus
value for each.
Run theUpdate Expiration algorithm on thesession, providingNaN
.
If any of the preceding steps failed, rejectpromise with a newDOMException
whose name is the appropriateerror name.
Letmessage type be "license-release
".
Resolvepromise withundefined
.
Ifmessage is notnull
, run theQueue a "message" Event algorithm on thesession, providingmessage type andmessage.
Returnpromise.
TheMediaKeyStatusMap
object is a read-only map ofkey IDs to the current status of the associated key.
A key's status is independent of whether the key is currently being used and of media data.
For example, if a key has output requirements that cannot currently be met, the key's status should be "output-downscaled
" or "output-restricted
", as appropriate, regardless of whether that key has been or is currently needed to decrypt media data.
WebIDL[Exposed=Window,SecureContext] interfaceMediaKeyStatusMap
{iterable<BufferSource,MediaKeyStatus
>; readonly attributeunsigned longsize
;booleanhas
(BufferSourcekeyId); (MediaKeyStatus
orundefined)get
(BufferSourcekeyId);};
size
of typeunsigned long
, readonlyThe number ofknown keys.
has()
Returnstrue
if the status of the key identified bykeyId is known.
get()
Returns theMediaKeyStatus
of the key identified bykeyId orundefined
if the status of the key identified bykeyId is not known.
This interface hasentries
,keys
,values
,forEach
and@@iterator
methods brought byiterable [WebIDL].
The value pairs to iterate over are a snapshot of the set of pairs formed from thekey ID and associatedMediaKeyStatus
value for allknown keys, sorted bykey ID. Key IDs are compared as follows: For key IDsA of lengthm andB of lengthn, assigned such thatm <=n, letA <B if and only if them octets ofA are less in lexicographical order than the firstm octets ofB or those octets are equal andm <n.
WebIDLenumMediaKeyStatus
{"usable
","expired
","released
","output-restricted
","output-downscaled
","usable-in-future
","status-pending
","internal-error
"};
TheMediaKeyStatus
enumeration is defined as follows:
Enumeration description | |
---|---|
usable | TheCDM is certain the key is currentlyusable for decryption. Keys thatmay not currently beusable for decryptionMUST NOT have this status. |
expired | The key is no longerusable for decryption because itsexpiration time has passed. The time represented by the expiration attributeMUST be earlier than the current time. All other keys in the sessionMUST have this status. |
released | The key itself is no longer available to theCDM, but information about the key, such as arecord of license destruction, is available. |
output-restricted | There are output restrictions associated with the key that cannot currently be met. Media data decrypted with this key may be blocked from presentation, if necessary according to the output restrictions. The application should avoid using streams that will trigger the output restrictions associated with the key. |
output-downscaled | There are output restrictions associated with the key that cannot currently be met. Media data decrypted with this key may be presented at a lower quality (e.g., resolution), if necessary according to the output restrictions. The application should avoid using streams that will trigger the output restrictions associated with the key. Support for downscaling isOPTIONAL. ApplicationsSHOULD NOT rely on downscaling to ensure uninterrupted playback when output requirements cannot be met. |
usable-in-future | The key is not yetusable for decryption because the start time is in the future. The key will become usable when its start time is reached. |
status-pending | The status of the key is not yet known and is being determined. The status will be updated with the actual status when it has been determined. |
internal-error | The key is not currentlyusable for decryption because of an error in theCDM unrelated to the other values. This value is not actionable by the application. |
The MediaKeyMessageEvent object is used for the
event.message
WebIDLenumMediaKeyMessageType
{"license-request
","license-renewal
","license-release
","individualization-request
"};
TheMediaKeyMessageType
is defined as follows:
Enumeration description | |
---|---|
license-request | The message contains a request for a new license. |
license-renewal | The message contains a request to renew an existing license. |
license-release | The message contains arecord of license destruction. |
individualization-request | The message contains a request forApp-Assisted Individualization (or re-individualization). As with all other messages, any identifiers in the messageMUST bedistinctive per origin and profile andMUST NOT beDistinctive Permanent Identifiers. |
WebIDL[Exposed=Window,SecureContext]interfaceMediaKeyMessageEvent
:Event {constructor
(DOMStringtype,MediaKeyMessageEventInit
eventInitDict); readonly attributeMediaKeyMessageType
messageType
; readonly attributeArrayBuffermessage
;};
messageType
of typeMediaKeyMessageType
, readonlyImplementationsMUST NOT require applications to handle message types. ImplementationsMUST support applications that do not differentiate messages andMUST NOT require that applications handle message types. Specifically,Key SystemsMUST support passing all types of messages to a single URL.
This attribute allows an application to differentiate messages without parsing the message. It is intended to enable optional application and/or server optimizations, but applications are not required to use it.
message
of typeArrayBuffer
, readonlyWebIDLdictionaryMediaKeyMessageEventInit
:EventInit { requiredMediaKeyMessageType
messageType
; requiredArrayBuffermessage
;};
MediaKeyMessageEventInit
MembersmessageType
of typeMediaKeyMessageType
message
of typeArrayBuffer
This section is non-normative.
Event name | Interface | Dispatched when... |
---|---|---|
keystatuseschange | Event | There has been a change in the keys in the session or their status. |
message | MediaKeyMessageEvent | TheCDM has generated a message for the session. |
The Queue a "message" Event algorithm queues a message event to aMediaKeySession
object. Requests to run this algorithm include a targetMediaKeySession
object, amessage type, and amessage.
messageMUST NOT containDistinctive Permanent Identifier(s), even in an encrypted form.messageMUST NOT containDistinctive Identifier(s), even in an encrypted form, if theMediaKeySession
object'suse distinctive identifier value is false.
The following steps are run:
Let thesession be the specifiedMediaKeySession
object.
Queue a task to create an event named
that does not bubble and is not cancellable using themessage
MediaKeyMessageEvent
interface with itstype attribute set tomessage
and itsisTrusted attribute initialized totrue
, and dispatch it at thesession.
The event interfaceMediaKeyMessageEvent
has:
messageType
= the specifiedmessage typemessage
= the specifiedmessage The Update Key Statuses algorithm updates the set ofknown keys for aMediaKeySession
or the status of one or more of the keys. Requests to run this algorithm include a targetMediaKeySession
object and a sequence ofkey ID and associatedMediaKeyStatus
pairs.
The algorithm is always run in a task.
The following steps are run:
Let thesession be the associatedMediaKeySession
object.
Let theinput statuses be the sequence of pairs key ID and associatedMediaKeyStatus
pairs.
Let thestatuses besession'skeyStatuses
attribute.
Run the following steps to replace the contents ofstatuses:
Emptystatuses.
For each pair ininput statuses.
Letpair be the pair.
Insert an entry forpair's key ID intostatuses with the value ofpair'sMediaKeyStatus
value.
The effect of this steps is that the contents ofsession'skeyStatuses
attribute are replaced without invalidating existing references to the attribute. This replacement is atomic from a script perspective. That is, scriptMUST NOT ever see a partially populated sequence.
Queue a task tofire an event named
at thesession.keystatuseschange
Queue a task to run theAttempt to Resume Playback If Necessary algorithm on each of the media element(s) whosemediaKeys
attribute is theMediaKeys
object that created thesession.
The Update Expiration algorithm updates theexpiration time of aMediaKeySession
. Requests to run this algorithm include a targetMediaKeySession
object and the new expiration time, which may beNaN
.
The algorithm is always run in a task.
The following steps are run:
Let thesession be the associatedMediaKeySession
object.
Letexpiration time beNaN
.
If the new expiration time is notNaN
, letexpiration time be that expiration time.
Set thesession'sexpiration
attribute toexpiration time expressed astime.
The Session Closed algorithm updates theMediaKeySession
state after akey session has been closed by theCDM. Requests to run this algorithm include a targetMediaKeySession
object and aMediaKeySessionClosedReason
.
The algorithm is always run in a task.
When a session is closed, the license(s) and key(s) associated with it are no longer available to decryptmedia data. AllMediaKeySession
methods will fail and no further events will be queued for this object after this algorithm is run.
TheCDM may close a session at any point, such as when the session is no longer needed or when system resources are lost. In that case, theMonitor for CDM State Changes algorithm detects the change and runs this algorithm.
Keys in other sessionsMUST be unaffected, even if they have overlapping key IDs.
After this algorithm has run, event handlers for the events queued by this algorithm will be executed, but no further events can be queued. As a result, no messages can be sent by theCDM as a result of closing the session.
The following steps are run:
Letsession be the associatedMediaKeySession
object.
Letpromise be thesession'sclosed
attribute.
Ifpromise is resolved, abort these steps.
Set thesession'sclosing or closed value to true.
Run theUpdate Key Statuses algorithm on thesession, providing an empty sequence.
Run theUpdate Expiration algorithm on thesession, providingNaN
.
Resolvepromise with the provided reason.
The Monitor for CDM State Changes algorithm executes steps required when various aspects ofCDM state change.
This algorithm only applies toCDM state changes that are not covered by other algorithms. For example,update
()
may result in messages, key status changes and/or expiration changes, but those are all handled within that algorithm.
The algorithm is always run in parallel to the main event loop.
The following steps are run:
Letsession be theMediaKeySession
object.
Letcdm be theCDM instance represented bysession'scdm instance value.
Ifcdm has an outgoing message that has not yet been sent,queue a task to execute the following steps:
Letmessage type andmessage be the message type and message, respectively.
Run theQueue a "message" Event algorithm, passingsession,message type andmessage.
Ifcdm has changed the set of keysknown tosession or the status of one or more of the keys,queue a task to execute the following steps:
Letstatuses be a list of key ID andMediaKeyStatus
value pairs containing one pair for each keyknown tosession.
Run theUpdate Key Statuses algorithm, passingsession andstatuses.
Ifcdm has changed theexpiration time ofsession,queue a task to execute the following steps:
Letexpiration time be the new expiration time ofsession.
Run theUpdate Expiration algorithm, passingsession andexpiration time.
Ifcdm has closedsession,queue a task to run theSession Closed algorithm onsession with an appropriateMediaKeySessionClosedReason
value.
Ifcdm has become unavailable due to a hardware context reset,queue a task to run theCDM Unavailable algorithm with reason "hardware-context-reset
".
Ifcdm has become unavailable for any other reason,queue a task to run theCDM Unavailable algorithm with reason "internal-error
".
The methods report errors by rejecting the returned promise with asimple exception [WEBIDL] or aDOMException
. The followingsimple exceptions andDOMException names from [WEBIDL] are used in the algorithms. Causes specified specified in the algorithms are listed alongside each name, though these namesMAY be used for other reasons as well.
Name | Possible Causes (non-exhaustive) |
---|---|
TypeError | The parameter is empty. Invalid initialization data. Invalid response format. A persistent license was provided for a " temporary " session. |
NotSupportedError | The existingMediaKeys object cannot be removed.TheKey System is not supported. The initialization data type is not supported by theKey System. The session type is not supported by theKey System. The initialization data is not supported by theKey System. The operation is not supported by theKey System. |
InvalidStateError | The existingMediaKeys object cannot be removed at this time.The session has already been used. The session is not yet initialized. The session is closed. |
QuotaExceededError | TheMediaKeys object cannot be used with additionalHTMLMediaElement s.A non-closed session already exists for this sessionId. There are insufficient resources to create a new session or license request. |
This section provides an overview of session storage and persistence that complements the algorithms.
The following requirements apply in addition to those inStorage and Persistence.
If the result of running theIs persistent session type? algorithm on this object'ssession type isfalse
, the user agent andCDMMUST NOT persist a record of or data related to the session at any point. This includes license(s), key(s),record(s) of license destruction, and theSession ID.
The remainder of this section applies to session types for which theIs persistent session type? algorithm returnstrue
.
TheCDMSHOULD NOT store session data, including the Session ID, untilupdate
()
is called the first time. Specifically, theCDMSHOULD NOT store session data during thegenerateRequest
()
algorithm. This ensures that the application is aware of the session and knows it needs to eventually remove it.
All data associated with a sessionMUST be cleared when the session is cleared, such as inupdate
()
when processing arecord of license destruction acknowledgement. SeePersistent Data.
TheCDMMUST ensure that data for a given session is only present in oneMediaKeySession
object that is notclosed in anyDocument. In other words,load
()
MUST fail when there is already aMediaKeySession
representing the session specified by thesessionId parameter, either because the object that created it viagenerateRequest
()
is still active or it has been loaded into another object viaload
()
. A sessionMAY only be loaded again if all objects that have ever represented it areclosed.
An application that creates a session using a type for which theIs persistent session type? algorithm returnstrue
SHOULD later remove the stored data by first initiating the removal process usingremove
()
and then ensuring that the removal process, which may involve message exchange(s), successfully completes. TheCDMMAY also remove sessions as appropriate, but applicationsSHOULD NOT rely on this.
See10. Security and11. Privacy for additional considerations when supporting persistent storage.
This section specifies additions to and modifications of theHTMLMediaElement
[HTML] when the Encrypted Media Extensions are supported.
The following internal values are added to theHTMLMediaElement
:
attaching media keys, whichSHALL have a boolean value.
encrypted block queue, whichSHALL be a queue of encrypted blocks awaiting decryption.
decryption blocked waiting for key, whichSHALL have a boolean value.
playback blocked waiting for key, whichSHALL have a boolean value.
The following modifications are made to the behaviour of theHTMLMediaElement
:
When aHTMLMediaElement
is created, itsattaching media keys valueSHALL be initialized tofalse
, itsencrypted block queue valueSHALL be empty, itsdecryption blocked waiting for key valueSHALL be initialized tofalse
, and itsplayback blocked waiting for key valueSHALL be initialized tofalse
.
When thecurrent playback position is changed other than advancing in thedirection of playback as part of normal playback, theencrypted block queue valueSHALL be empty, thedecryption blocked waiting for key valueSHALL be initialized tofalse
, and theplayback blocked waiting for key valueSHALL be set tofalse
.
In other words, these values should be reset when, for example,loading the media resource orseeking.
In addition to the criteria specified in [HTML], anHTMLMediaElement
SHALL be considered ablocked media element if itsplayback blocked waiting for key value istrue
.
When the user agent is ready to begin playback and has encountered an indication that themedia data may contain encrypted blocks during theresource fetch algorithm, the user agentSHALL run theMedia Data May Contain Encrypted Blocks algorithm.
For some container formats, such indication is separate fromInitialization Data.
The algorithm is to be run after parsing the relevant container data, including running theInitialization Data Encountered algorithm, but before decoding starts.
When the user agent encountersInitialization Data in themedia data during theresource fetch algorithm, the user agentSHALL run theInitialization Data Encountered algorithm.
Some container formats may support encrypted media data that does not containInitialization Data and thus support media data that does not trigger this algorithm.
For each block of encryptedmedia data encountered during theresource fetch algorithm, the user agentSHALL run theEncrypted Block Encountered algorithm in the order the encrypted blocks were encountered.
The above step provides flexibility for user agent implementations to perform decryption at any time after an encrypted block is encountered before it is needed for playback.
When one of the following occurs while thedecryption blocked waiting for key value istrue
, the user agentSHALL run theWait for Key algorithm.
The user agent cannot advance thecurrent playback position in thedirection of playback.
The user agent cannot provide data for thecurrent playback position.
For example, at the beginning of playback or afterseeking.
Additional attributes and a method are added, as specified below.
For methods that return a promise, all errors are reported asynchronously by rejecting the returned Promise. This includes [WEBIDL] type mapping errors.
The steps of an algorithm are always aborted when rejecting a promise.
WebIDL[Exposed=Window] partial interfaceHTMLMediaElement
{ [SecureContext] readonly attributeMediaKeys
?mediaKeys
; attributeEventHandleronencrypted
; attributeEventHandleronwaitingforkey
; [SecureContext]Promise<undefined>setMediaKeys
(MediaKeys
?mediaKeys);};
mediaKeys
of typeMediaKeys
, readonly, nullable TheMediaKeys
being used when decrypting encryptedmedia data for this media element.
onencrypted
of typeEventHandler
Event handler for the
event. ItMUST be supported by allencrypted
HTMLMediaElement
s as both a content attribute and an IDL attribute.
onwaitingforkey
of typeEventHandler
Event handler for the
event. ItMUST be supported by allwaitingforkey
HTMLMediaElement
s as both a content attribute and an IDL attribute.
setMediaKeys()
Provides theMediaKeys
to use when decrypting media data during playback.
Support for clearing or replacing the associatedMediaKeys
object during playback is a quality of implementation issue. In many cases it will result in a bad user experience or rejected promise.
When this method is invoked, the user agentMUST run the following steps:
If this object'sattaching media keys value is true, return a promise rejected with an
.InvalidStateError
IfmediaKeys and themediaKeys
attribute are the same object, return a promise resolved withundefined
.
Let this object'sattaching media keys value be true.
Letpromise be a new promise.
Run the following steps in parallel:
If all the following conditions hold:
mediaKeys is not null,
theCDM instance represented bymediaKeys is already in use by another media element
the user agent is unable to use it with this element
then let this object'sattaching media keys value be false and rejectpromise with a
.QuotaExceededError
If themediaKeys
attribute is not null, run the following steps:
If the user agent orCDM do not support removing the association, let this object'sattaching media keys value be false and rejectpromise with a
.NotSupportedError
If the association cannot currently be removed, let this object'sattaching media keys value be false and rejectpromise with an
.InvalidStateError
For example, some implementations may not allow removal during playback.
Stop using theCDM instance represented by themediaKeys
attribute to decryptmedia data and remove the association with the media element.
If the preceding step failed, let this object'sattaching media keys value be false and rejectpromise with the appropriateerror name.
IfmediaKeys is not null, run the following steps:
Associate theCDM instance represented bymediaKeys with the media element for decryptingmedia data.
If the preceding step failed, run the following steps:
Set themediaKeys
attribute to null.
Let this object'sattaching media keys value be false.
Rejectpromise with a newDOMException
whose name is the appropriateerror name.
Queue a task to run theAttempt to Resume Playback If Necessary algorithm on the media element.
Set themediaKeys
attribute tomediaKeys.
Let this object'sattaching media keys value be false.
Resolvepromise withundefined
.
Returnpromise.
The MediaEncryptedEvent object is used for the
event.encrypted
WebIDL[Exposed=Window]interfaceMediaEncryptedEvent
:Event {constructor
(DOMStringtype, optionalMediaEncryptedEventInit
eventInitDict = {}); readonly attributeDOMStringinitDataType
; readonly attributeArrayBuffer?initData
;};
initDataType
of typeDOMString
, readonlyinitData
attribute.initData
of typeArrayBuffer
, readonly, nullableWebIDLdictionaryMediaEncryptedEventInit
:EventInit {DOMStringinitDataType
= "";ArrayBuffer?initData
= null;};
MediaEncryptedEventInit
MembersinitDataType
of typeDOMString
, defaulting to""
initData
of typeArrayBuffer
, nullable, defaulting tonull
This section is non-normative.
Event name | Interface | Dispatched when... | Preconditions |
---|---|---|---|
encrypted | MediaEncryptedEvent | The user agent encountersInitialization Data in themedia data. | The element'sreadyState is equal to or greater thanHAVE_METADATA .Note It is possible that the element is playing or has played. |
waitingforkey | Event | Playback is blocked waiting for a key. | ThereadyState is equal to or less thanHAVE_CURRENT_DATA . The element'splayback blocked waiting for key value is newlytrue . |
The Media Data May Contain Encrypted Blocks algorithm pauses playback if the user agent requires specification of aMediaKeys
object before playing the media data. Requests to run this algorithm include a targetHTMLMediaElement
object.
The following steps are run:
Let themedia element be the specifiedHTMLMediaElement
object.
If themedia element'smediaKeys
attribute is null and the implementation requires specification of aMediaKeys
object before decoding potentially-encryptedmedia data, run the following steps:
These steps may be reached when the application providesmedia data before callingsetMediaKeys
()
to provide aMediaKeys
object. Selecting aCDM may affect the pipeline and/or decoders used, so some implementations may delay playback of media data that may contain encrypted blocks until aCDM is specified by passing aMediaKeys
object tosetMediaKeys
()
.
Run theWait for Key algorithm on themedia element.
Wait for a signal to resume playback.
The Initialization Data Encountered algorithm queues an
event forInitialization Data encountered in themedia data. Requests to run this algorithm include a targetencrypted
HTMLMediaElement
object.
The following steps are run:
Let themedia element be the specifiedHTMLMediaElement
object.
LetinitDataType be the empty string.
LetinitData be null.
If themedia data isCORS-same-origin andnotmixed content, run the following steps:
LetinitDataType be the string representing theInitialization Data Type of the Initialization Data.
LetinitData be the Initialization Data.
While the media element may allow loading of "Upgradeable Content" [MIXED-CONTENT], the user agentMUST NOT expose Initialization Data from such media data to the application.
Queue a task to create an event named
that does not bubble and is not cancellable using theencrypted
MediaEncryptedEvent
interface with itstype attribute set toencrypted
and itsisTrusted attribute initialized totrue
, and dispatch it at themedia element.
The event interfaceMediaEncryptedEvent
has:
initDataType
=initDataTypeinitData
=initDatareadyState
isnot changed and no algorithms are aborted. This event merely provides information.
TheinitData
attribute will be null if the media data isnotCORS-same-origin or ismixed content. Applications may retrieve the Initialization Data from an alternate source.
The Encrypted Block Encountered algorithm queues a block of encrypted media data for decryption and attempts to decrypt if possible. Requests to run this algorithm include a targetHTMLMediaElement
object.
The following steps are run:
Let themedia element be the specifiedHTMLMediaElement
object.
Letblock be the block of encrypted media data.
Addblock to the end of themedia element'sencrypted block queue.
If themedia element'sdecryption blocked waiting for key value isfalse
, run theAttempt to Decrypt algorithm.
The Attempt to Decrypt algorithm attempts to decrypt media data that is queued for decryption. Requests to run this algorithm include a targetHTMLMediaElement
object.
The following steps are run:
Let themedia element be the specifiedHTMLMediaElement
object.
If themedia element'sencrypted block queue is empty, abort these steps.
If themedia element'smediaKeys
attribute is not null, run the following steps:
Letmedia keys be theMediaKeys
object referenced by that attribute.
Letcdm be theCDM instance represented bymedia keys'scdm instance value.
Ifcdm is no longer usable for any reason, run the following steps:
Run themedia data is corrupted steps of theresource fetch algorithm.
Run theCDM Unavailable algorithm onmedia keys with the reason "hardware-context-reset
" for a hardware context reset or "internal-error
" otherwise.
Abort these steps.
If there is at least oneMediaKeySession
created by themedia keys that is notclosed, run the following steps:
This check ensures thecdm has finished loading and is a prerequisite for a matching key being available.
Letblock be the first entry in themedia element'sencrypted block queue.
Let theblock key ID be the key ID ofblock.
The key ID is generally specified by the container.
Use thecdm to execute the following steps:
Letavailable keys be the union of keys in sessions that were created by themedia keys.
Letblock key be null.
If any of theavailable keys corresponds to theblock key ID and isusable for decryption, letsession be aMediaKeySession
object containing that key and letblock key be that key.
If multiple sessions contain a key that isusable for decryption for theblock key ID, which session and key to use isKey System-dependent.
If the status of any of theavailable keys changed as the result of running the preceding step,queue a task to run theUpdate Key Statuses algorithm on each affectedsession, providing allkey ID(s) in the session along with the appropriateMediaKeyStatus
value(s) for each.
Ifblock key is not null, run the following steps:
Use thecdm to decryptblock usingblock key.
Follow the steps for the first matching condition from the following list:
Run themedia data is corrupted steps of theresource fetch algorithm.
Ifcdm is no longer usable, run theCDM Unavailable algorithm onmedia keys with the reason "hardware-context-reset
" for a hardware context reset, or "internal-error
" otherwise.
Abort these steps.
Removeblock from the front of themedia element'sencrypted block queue.
Process the decrypted block as normal.
In other words, decode the block.
Return to the beginning of this algorithm.
Not all decryption problems (e.g., using the wrong key) will result in a decryption failure. In such cases, no error is fired here but one may be fired during decode.
Otherwise, there is no key for theblock key ID in any session so continue.
Set themedia element'sdecryption blocked waiting for key value totrue
.
This step is reached when there is no key that isusable for decryption forblock.
Once the user agent has rendered the blocks preceding the block that cannot be decrypted (as much as it can, such as, all complete video frames), it will run theWait for Key algorithm.
That algorithm is not run directly here in order to allow implementations to decrypt and decode media data ahead of the ahead of the current playback position without affecting the visible behavior.
For frame-based encryption, this may be implemented as follows when the media element attempts to decode a frame as part of theresource fetch algorithm:
Letencrypted be false.
Detect whether the frame is encrypted.
Decode the frame.
Provide the frame for rendering.
The Wait for Key algorithm queues a
event and updateswaitingforkey
readyState
. It should only be called when theHTMLMediaElement
object ispotentially playing and itsreadyState
is equal toHAVE_FUTURE_DATA
or greater. Requests to run this algorithm include a targetHTMLMediaElement
object.
The following steps are run:
Let themedia element be the specifiedHTMLMediaElement
object.
If themedia element'splayback blocked waiting for key value istrue
, abort these steps.
Set themedia element'splayback blocked waiting for key value totrue
.
As a result of the above step, the media element will become ablocked media element if it wasn't already. In that case, the media element will stop playback.
Follow the steps for the first matching condition from the following list:
Set thereadyState
ofmedia element toHAVE_CURRENT_DATA
.
Set thereadyState
ofmedia element toHAVE_METADATA
.
In other words, if the video frame and audio data for thecurrent playback position have been decoded because they were unencrypted and/or successfully decrypted, setreadyState
toHAVE_CURRENT_DATA
. Otherwise, including if this was previously the case but the data is no longer available, setreadyState
toHAVE_METADATA
.
Queue a task tofire an event named
at themedia element.waitingforkey
Suspend playback.
The Attempt to Resume Playback If Necessary algorithm resumes playback if the media element is blocked waiting for a key and necessary key is currentlyusable for decryption Requests to run this algorithm include a targetHTMLMediaElement
object.
The following steps are run:
Let themedia element be the specifiedHTMLMediaElement
object.
If themedia element'splayback blocked waiting for key isfalse
, abort these steps.
Run theAttempt to Decrypt algorithm on themedia element.
If the user agent can advance thecurrent playback position in thedirection of playback:
Set themedia element'sdecryption blocked waiting for key value tofalse
.
Set themedia element'splayback blocked waiting for key value tofalse
.
As a result of the above step, the media element may no longer be ablocked media element and thus playback may resume.
Set themedia element'sreadyState
value toHAVE_CURRENT_DATA
,HAVE_FUTURE_DATA
orHAVE_ENOUGH_DATA
asappropriate.
States beyondHAVE_CURRENT_DATA
and thecanplaythrough event do not (or are unlikely to) consider key availability beyond the current key.
The change in ready state may also causeHTMLMediaElement
events to be fired as describedhere.
This section is non-normative.
Media data processed by aCDMMAY be unavailable through web platform APIs in the usual way (for example using theCanvasRenderingContext2D
drawImage
()
method and theAudioContext
MediaElementAudioSourceNode
). This specification does not define conditions for such non-availability of media data, however, if media data is not available to through such APIs then theyMAY behave as if no media data was present at all.
Where media rendering is not performed by the UA, for example in the case of a hardware-based media pipeline, the full set of HTML rendering capabilities, for example CSS Transforms,MAY be unavailable. One likely restriction is that video mediaMAY be constrained to appear only in rectangular regions with sides parallel to the edges of the window and with normal orientation.
This section defines implementation requirements - for both user agents andKey Systems, including theCDM and server(s) - that may not be explicitly addressed in the algorithms. The requirements here and throughout the spec apply to all implementations, regardless of whether theCDM is separate from or a part of the user agent.
User agent implementersMUST ensure thatCDMs do not access any information, storage or system capabilities that are not reasonably required for playback of protected media using the features of this specification. Specifically, theCDMSHALL NOT:
Access network resources, either local or remote, except via the user agent as explicitly permitted by this specification.
Access storage (e.g., disk or memory), except where reasonably required for playback of protected media using the features of this specification.
Access user data other thanCDM state andpersistent data.
Access hardware components or devices, except where reasonably required for playback of protected media using the features of this specification.
User Agent implementers may use various techniques to meet the above requirements. For example, a User Agent implementer also implementing their ownCDM may include the above as design requirements for that component. A User Agent implementer making use of a third partyCDM may ensure that it executes in a constrained environment (e.g., "sandbox") without access to the prohibited information and components.
All messages and communication to and from theCDM, such as between theCDM and a license server,MUST be passed through the user agent. TheCDMMUST NOT make direct out-of band network requests. All messages and communication other than those described inDirect IndividualizationMUST be passed through the application via the APIs defined in this specification. Specifically, all communication that contains application-,origin-, or content-specific information or is sent to a URL specified by the application or based on its origin,MUST pass through the APIs. This includes all license exchange messages.
Persistent Data includes all data stored by theCDM, or by the User Agent on behalf of theCDM, that exists after the destruction of theMediaKeys
object. Specifically, it includes any identifiers (includingDistinctive Identifier(s)), licenses, keys, key IDs, orrecords of license destruction stored by theCDM or by the User Agent on behalf of theCDM.
Persistent Data that might impact messages or behavior in an application- or license server-visible wayMUST be stored in anorigin-specific andbrowsing profile-specific way andMUST NOT leak to or from private browsing sessions. Specifically but not exhaustively, session data, licenses, keys and per-origin identifiersMUST be stored per-origin and per-browsing profile.
Implementations that use Persistent DataMUST allow the user to clear that data such that it is no longer retrievable both outside, such as via the APIs defined in this specification, and on the client device.
User AgentsSHOULD:
Treat Persistent Data like other site data, such as cookies [COOKIES]. Specifically:
Allow users to clear Persistent Data along with cookies [COOKIES] and other site data.
Allow users to clear Persistent Data as part of user agent features to clear browsing history.
Include Persistent Data in "remove all data" features.
Present Persistent Data in the same UI locations as other site data.
Allow users to clear Persistent Data on a per-origin and per-browsing profile basis, particularly as part of a "Forget about this site" feature that forgets cookies [COOKIES], databases, etc. associated with a particular site.
Ensure that operations which clear Persistent Data are sufficiently atomic to prevent a "cookie resurrection" type of recorrelation of a new identifier with the old by relying on another type of locally stored data that did not get cleared at the same time. Seeincomplete clearing of data.
Present these interfaces in a way that helps users to understand the possibility ofincomplete clearing of data and enables them to delete data associated with all features that persist data, including cookies [COOKIES] and web storage, simultaneously.
Present the interfaces for disabling and re-enabling aKey System in a way that helps users to understand the possibility ofincomplete clearing of data and enables them to delete all such data in all persistent storage features simultaneously.
Allow users to specifically delete Persistent Data, byorigin and/or for all origins.
User agentsSHOULD treat Persistent Data as potentially sensitive; it is quite possible for user privacy to be compromised by the release of this information. To this end, user agentsSHOULD ensure that Persistent Data is securely stored and when deleting data, it is promptly deleted from the underlying storage.
Values exposed to or inferable by, such as via its use by theCDM, the application could be used to identify the client or user, regardless of whether they are designed to be identifiers. This section defines requirements for avoiding or at least mitigating such concerns. There are additional requirements forIdentifiers.
AllDistinctive Values exposed to or inferable by the applicationMUST be unique perorigin andbrowsing profile. That is, the value(s) used for oneorigin using the APIs defined in this specificationMUST be different from those used for any other origin using the APIs, and value(s) used in onebrowsing profileMUST be different from those used for any other profile, regardless of origin. Such valuesMUST NOT leak to or from private browsing sessions.
Values across origins and profilesMUST benon-associable by applications, meaning itMUST NOT be possible to correlate values from multiple origins or profiles, such as to determine that they came from the same client or user. Specifically, implementations that derive per-origin values from an origin-independent and/or profile-independent value,MUST do so in a way that ensures the above non-associability property, such as by using derivation functions with appropriate non-reversible properties.
As a consequence of the requirements inAllow Persistent Data to Be Cleared, all persisted values exposed to the applicationMUST be clearable such that the values are no longer retrievable, observable, or inferable both outside, such as via the APIs defined in this specification, and on the client device.
Once cleared, newnon-associable by applications value(s)MUST be generated when values are subsequently needed.
The use of identifiers, especiallyDistinctive Identifier(s) or Distinctive Permanent Identifier(s), by implementations presents a privacy concern. This section defines requirements for avoiding or at least mitigating such concerns. The requirements forValues Exposed to the Application also apply to identifiers exposed to the application.
In summary:
Limit or Avoid use of Distinctive Identifiers and Permanent Identifiers.
All identifers exceptPermanent IdentifiersMUST beunique per origin and profile,non-associable, andclearable.
All identifersSHOULD beencrypted when exposed outside the client.
Distinctive IdentifiersMUST beencrypted when exposed outside the client,unique per origin and profile, andclearable.
Distinctive Permanent IdentifiersMUST beencrypted when exposed outside the client andMUST NOT be exposed to the application.
All potential identifiers orDistinctive Values not covered above that are generated as a result of use of the APIs defined in this specificationMUST beunique per origin and profile andclearable. This includes but is not limited to random identifiers, session data, and otherCDM data.
ImplementationsSHOULD avoiduse of Distinctive Identifier(s) or Distinctive Permanent Identifier(s).
For example, use identifiers or other values that apply to a group of clients or devices rather than individual clients.
ImplementationsSHOULD onlyuse Distinctive Identifier(s) or Distinctive Permanent Identifier(s) when necessary to enforce the policies related to the specificCDM instance and session.
For example, "temporary
" and "persistent-license
" sessions may have different requirements.
Implementations thatuse Distinctive Identifier(s) or Distinctive Permanent Identifier(s)SHOULD support the option to not use them. Implementations with such supportSHOULD expose the ability for the user to select this option.
When supported, applications can select for this mode usingdistinctiveIdentifier
= "not-allowed
". Selecting such an option may affect the results of therequestMediaKeySystemAccess
()
call and/or the license requests that are generated from subsequently generated sessions.
Providing the user access to select or choose this implementation capability may allow the user to access content while maintaining a higher degree of privacy.
Distinctive Identifiers andDistinctive Permanent IdentifiersMUST be encrypted at the message exchange level when exposed outside the client. All other identifiersSHOULD be encrypted at the message exchange level when exposed outside the client. The encryptionMUST ensure that any two instances of the identifier ciphertext areassociable only by an entity in possession of the decryption key.
Identifiers may be exposed in the following ways:
To the application via a
event.message
In a message from a server, such as one that is passed toupdate
()
.
As part ofindividualization.
TheCDMMUST verify that the encryption key belongs to a valid server for itsKey System. For identifers exposed to the application, thisMAY be implemented using aserver certificate.
The serverMUST NOT expose aDistinctive Identifier to any entity other than theCDM that sent it.
Specifically, it should not be provided to the application or included unencrypted in messages to theCDM. This can be accomplished by encrypting the identifier or message with the identifier or such that it is only decryptable by that specificCDM.
Among other things, this means that:
Every signature made with device-specific or user-specific keysMUST be different, even given the same plaintext.
Identifiers, keys, or certificates relating to device-specific or user-specific keysMUST be encrypted for the license orindividualization server.
Messages from the license server to theCDMMUST NOT expose recipient-unique identifiers, such as the ID of the intended decryption key, on the outside of the encryption envelope.
All identifiers exceptDistinctive Permanent IdentifiersMUST be unique perorigin andbrowsing profile. See8.4.1 Use Per-Origin Per-Profile Values.
This includes but is not limited toDistinctive Identifiers.
Distinctive Permanent IdentifiersMUST NOT be exposed to the application or origin.
All identifiers, includingDistinctive Identifiers, exposed by the implementation to applications, even in encrypted form,MUST benon-associable by application(s) acrossorigins,browsing profiles, andclearing of identifiers.
For all such identifiers, itMUST NOT be possible for one or more applications, including related license or other servers to achieve such correlation or association.
As a consequence of the requirements inAllow Persistent Data to Be Cleared, all potential identifiers orDistinctive Values exceptDistinctive Permanent IdentifiersMUST be clearable such that the values are no longer retrievable, observable, or inferable both outside, such as via the APIs defined in this specification, and on the client device.
Implementations thatuse Distinctive Identifier(s)MUST allow the user to clear theDistinctive Identifier(s). Implementations thatuse Distinctive Permanent Identifier(s)MUST allow the user to clear values associated with theDistinctive Permanent Identifier(s).
Once cleared, newnon-associable by applications value(s)MUST be generated when values, such asDistinctive Identifiers, are subsequently needed.
Identifiers, especiallyDistinctive Identifiers, are sometimes generated or obtained via a process called individualization or provisioning. The resulting identifier(s)MUST benon-associable by applications anduse of themMUST only be exposed to asingle origin from a single profile. This processMAY be performed multiple times, such as after identifier(s) arecleared.
This processMUST be performed eitherdirectly by the user agent orthrough the application. The mechanisms, flow, and restrictions for the two types of individualization are different, as described in the following sections. Which method is used depends on theCDM implementation and application of the requirements of this specification, especially those below.
distinctiveIdentifier
controls whetherDistinctive Identifiers andDistinctive Permanent Identifiers may beused, including for individualization. Specifically, such identifiers may only beused when the value of thedistinctiveIdentifier
member of theMediaKeySystemAccess
used to create theMediaKeys
object is "required
".
Direct Individualization is performed between theCDM and an origin- and application-independent server. Although the server is origin-independent, the result of the individualization enables theCDM to provide origin-specific identifiers per the other requirements of this specification. The processMUST be performed by the user agent andMUST NOT use the APIs defined in this specification.
For example, such a process may initialize a client device and/or obtain aper-originclearable identifier fora single browsing profile by communicating with a pre-determined server hosted by the user agent or CDM vendor, possiblyusing Distinctive Permanent Identifier(s) or otherPermanent Identifier(s) from the client device.
For such individualization, all message exchanges:
MUST be handled by the user agent and performed by the user agent via the user agent's network stack.
MUST NOT be performed directly by theCDM.
MUST NOT be passed to or through the application via the APIs defined in this specification.
MUST be sent to a URL selected independently of any origin and application.
MUST encrypt allDistinctive Identifiers andDistinctive Permanent Identifiers.
MUST use TLS.
ImplementationsMUST NOT expose, even in encrypted form,origin(s), origin- or application-specific information, or values that areassociable with origin(s) to centralized servers since this could create a central record of all origins visited by a user or device.
App-Assisted Individualization is performed between theCDM and the application, including an application-selected server, and results in a per-origin identifier. The processMUST be performed via the APIs defined in this specification andMUST NOT involve other methods of communication. As with all other uses of the APIs, the processMAYuse one or more Distinctive Identifier(s), but itMUST NOTuse Distinctive Permanent Identifier(s) or non-origin-specific values, even in encrypted form. If the processuses one or more Distinctive Identifier(s), the resulting identifier is by definition also aDistinctive Identifier.
For such individualization, all message exchanges:
MUST be passed to or through the application via the APIs defined in this specification.
SHALL use the message type "individualization-request
" for all related
events.message
MUST NOT be performed by the user agent.
MUST NOT be performed directly by theCDM.
MUST NOT contain or otherwiseuse Distinctive Permanent Identifier(s).
MUST NOT contain non-origin-specific per-client information
MUST adhere to theidentifier requirements.
This includes only using values that areunique per origin and profile andclearable andencrypting them as required.
MUST NOT provide executable code to theCDM.
Whenassociable values, includingDistinctive Identifier(s), areused in the process, implementationsMUST NOT expose, even in encrypted form,origin(s)-, origin- or application-specific information, or values that areassociable with origin(s) to centralized servers since this could create a central record of all origins visited by a user or device.
With appropriate precautions, such individualization can provide better privacy thanDirect Individualization, though not as good as models that do notuse Distinctive Identifier(s). To preserve the benefits of such a design and to avoid introducing other privacy concerns, such implementations and the applications that support themSHOULD avoid deferring or forwarding individualization messages to a central server or other server not controlled by the application author.
ImplementationsMUST support multiple keys in eachMediaKeySession
object.
The mechanics of how multiple keys are supported is an implementation detail, but itMUST be transparent to the application and the APIs defined in this specification.
ImplementationsMUST support seamless switching between keys during playback. This includes both keys in the sameMediaKeySession
and keys in separateMediaKeySession
objects.
ImplementationsSHOULD allow licenses generated with anyInitialization Data Type they support to be used with any content type.
Otherwise, therequestMediaKeySystemAccess
()
algorithm might, for example, reject aMediaKeySystemConfiguration
because one of theinitDataTypes
is not supported with one of thevideoCapabilities
.
For any supportedInitialization Data Type that may appear in a supported container, the user agentsMUST supportextracting that type ofInitialization Data from each such supported container.
In other words, indicating support for anInitialization Data Type implies bothCDM support for generating license requests and, for container-specific types, user agent support for extracting it from the container. This doesnot mean that implementations must be able to parseany supportedInitialization Data fromany supported content type.
This section defines properties of content (media resource) supported by implementations of this specification.
The media containerMUST NOT be encrypted. This specification relies on the user agent's ability to parse the media container without having to decrypt any of the media data. This includes theEncrypted Block Encountered andInitialization Data Encountered algorithms as well as supporting standardHTMLMediaElement
[HTML] functionality, such asseeking.
Media resources, including all tracks,MUST be encrypted and packaged per a container-specific "common encryption" specification that allows the content to be decrypted in a fully specified and compatible way when a key or keys are provided.
TheEncrypted Media Extensions Stream Format Registry [EME-STREAM-REGISTRY] provides references to such stream formats.
In-band support content, such as captions, described audio, and transcripts,SHOULD NOT be encrypted.
Decryption of such tracks - especially such that they can be provided back the user agent - is not generally supported by implementations. Thus, encrypting such tracks would prevent them from being widely available for use with accessibility features in user agent implementations.
To ensure accessibility information is available in usable form, for implementations that choose to support encrypted in-band support content: a) theCDMMUST provide the decrypted data to the user agent and b) the user agentMUST process it in the same way as equivalent unencrypted support content. For example, to be exposed astimed text tracks [HTML].
All user agentsMUST support the commonKey Systems described in this section.
This ensures that there is a common baseline level of functionality that is guaranteed to be supported in all user agents, including those that are entirely open source. Thus, content providers that need only basic decryption can build simple applications that will work on all platforms without needing to work with any content protection providers.
The"org.w3.clearkey"
Key System uses plain-text clear (unencrypted) key(s) to decrypt the source. No additional client-side content protection is required. ThisKey System is described below.
The following describe howClear Key supportsKey System-specific capabilities:
encryptionScheme
: ImplementationsMUST support the
scheme, andMAY support other schemes."cenc"
robustness
: Only the empty string is supported.
distinctiveIdentifier
: "required
" is not supported.
persistentState
: Not "required
" unless the application intends to create non-"temporary
" sessions, if supported.
The "persistent-license
"MediaKeySessionType
: ImplementationsMAY support this type.
ThesetServerCertificate
()
method: Not supported.
ThegetStatusForPolicy
()
method: Implementations should always resolve promise with "usable
".
ThesetMediaKeys
()
method: ImplementationsMAY support associating theMediaKeys
object with more than oneHTMLMediaElement
.
The following describe howClear Key implementsKey System-specific behaviors:
In thegenerateRequest
()
algorithm:
The generatedmessage is a JSON object encoded in UTF-8 as described inLicense Request Format.
The request is generated by extracting the key IDs from thesanitized init data.
The "type" member value is the value of thesessionType parameter.
ThesessionId
attribute is a numerical value representable by a 32-bit integer.
Theexpiration
attribute is alwaysNaN
.
In theupdate
()
algorithm:
Theresponse parameter is either a JWK Set as described inLicense Format, or a JSON object encoded in UTF-8 as described inLicense Release Acknowledgement Format.
In the first case,sanitized response is considered invalid if it is not a valid JWK Set with at least one valid JWK key of a valid length for the audio/video type. In the second casesanitized response is considered invalid if it is not a valid JSON object.
For sessions of type "persistent-license
", in theremove
()
algorithm, themessage reflecting therecord of license destruction is a JSON object encoded in UTF-8 as described inLicense Release Format.
ThekeyStatuses
attribute method initially contains all key IDs that have been provided viaupdate
()
, with status "usable
". When theremove
()
algorithm is executed, thekeyStatuses
attribute will be set to an empty list.
Initialization Data: ImplementationsMAY support any combination of registered Initialization Data Types [EME-INITDATA-REGISTRY]. ImplementationsSHOULD support the"keyids"
type [EME-INITDATA-KEYIDS] and other types appropriate for content types supported by the user agent.
This section describes the format of the license request provided to the application via the message attribute of the
event.message
The format is a JSON object containing the following members:
MediaKeySessionType
. When contained in the ArrayBuffermessage
attribute of aMediaKeyMessageEvent
object, the JSON string is encoded in UTF-8 as specified in the Encoding specification [ENCODING]. ApplicationsMAY decode the contents of the ArrayBuffer to a JSON string using theTextDecoder
interface [ENCODING].
This section is non-normative.
The following example is a license request for a temporary license for two key IDs. (Line breaks are for readability only.)
{"kids":["LwVHf8JLtPrv2GUXFW2v_A","0DdtU9od-Bh5L3xbv0Xf_A"],"type":"temporary"}
This section describes the format of the license to be provided via theresponse parameter of theupdate
()
method.
The format is a JSON Web Key (JWK) Set containing representation of the symmetric key to be used for decryption, as defined in the JSON Web Key (JWK) specification [RFC7517].
For each JWK in the set, the parameter values are as follows:
The JSON objectMAY have an optional "type" member value, whichMUST be one of theMediaKeySessionType
values. If not specified, the default value of "temporary
" is used. Theupdate
()
algorithm compares this value to thesessionType.
When passed to theupdate
()
method as the ArrayBufferresponse parameter, the JSON stringMUST be encoded in UTF-8 as specified in the Encoding specification [ENCODING]. ApplicationsMAY encode the JSON string using theTextEncoder
interface [ENCODING].
This section is non-normative.
The following example is a JWK Set containing a single symmetric key. (Line breaks are for readability only.)
{"keys":[{"kty":"oct","k":"tQ0bJVWb6b0KPL6KtZIy_A","kid":"LwVHf8JLtPrv2GUXFW2v_A"}],"type":"temporary"}
This section describes the format of the license release message to be provided via the message attribute of the
event.message
The format is a JSON object. For sessions of type "persistent-license
", the object shall contain the following member:
When contained in the ArrayBuffermessage
attribute of aMediaKeyMessageEvent
object, the JSON string is encoded in UTF-8 as specified in the Encoding specification [ENCODING]. ApplicationsMAY decode the contents of the ArrayBuffer to a JSON string using theTextDecoder
interface [ENCODING].
This section is non-normative.
The following example is a license release for a "persistent-license
" session that contained two keys. (Line breaks are for readability only.)
{"kids":["LwVHf8JLtPrv2GUXFW2v_A","0DdtU9od-Bh5L3xbv0Xf_A"]}
This section describes the format of the license release acknowledgement provided via theresponse parameter of theupdate
()
method.
The format is a JSON object containing the following members:
When passed to theupdate
()
method as the ArrayBufferresponse parameter, the JSON stringMUST be encoded in UTF-8 as specified in the Encoding specification [ENCODING]. ApplicationsMAY encode the JSON string using theTextEncoder
interface [ENCODING].
This section is non-normative.
The following example is a license request for a temporary license for two key IDs. (Line breaks are for readability only.)
{"kids":["LwVHf8JLtPrv2GUXFW2v_A","0DdtU9od-Bh5L3xbv0Xf_A"]}
This section is non-normative.
For more information on base64url and working with it, see the "Base64url Encoding" terminology definition and "Notes on implementing base64url encoding without padding" in [RFC7515]. Specifically, there is no '=' padding, and the characters '-' and '_'MUST be used instead of '+' and '/', respectively.
User Agent andKey System implementationsMUST considermedia data,Initialization Data, data passed toupdate
()
, licenses, key data, and all other data provided by the application as untrusted content and potential attack vectors. TheyMUST use appropriate safeguards to mitigate any associated threats and take care to safely parse, decrypt, etc. such data. User AgentsSHOULD validate data before passing it to theCDM.
Such validation is especially important if theCDM does not run in the same (sandboxed) context as, for example, the DOM.
ImplementationsMUST NOT return active content or passive content that affects program control flow to the application.
For example, it is not safe to expose URLs or other information that may have come from media data, such as is the case for theInitialization Data passed togenerateRequest
()
. Applications must determine the URLs to use. ThemessageType
attribute of the
event can be used by the application to select among a set of URLs if applicable.message
User Agents are responsible for providing users with a secure way to browse the web. This responsibility applies to any functionality used by User Agents, including functionalities from third parties. User agent implementersMUST obtain sufficient information fromKey System implementers to enable them to properly assess the security implications of integrating with theKey System. User agent implementersMUST ensureCDM implementations provide and/or support sufficient controls for the user agent to provide security for the user. User agent implementersMUST ensureCDM implementations can and will be quickly and proactively updated in the event of security vulnerabilities.
Exploiting aCDM implementation that is not fully sandboxed and/or uses platform features may allow an attacker to access OS or platform features, elevate privilege (e.g., to run as system or root), and/or access drivers, kernel, firmware, hardware, etc. Such features, software, and hardware may not be written to be robust against hostile software or web-based attacks and may not be updated with security fixes, especially compared to the user agent. Lack of, infrequent, or slow updates for fixes to security vulnerabilities inCDM implementations increases the risk. SuchCDM implementations and UAs that expose themMUST be especially careful in all areas of security, including parsing ofall data.
User agents should be especially diligent when using aCDM or underlying mechanism that is part of or provided by the client OS, platform and/or hardware.
If a user agent chooses to support aKey System implementation that cannot be sufficiently sandboxed or otherwise secured, the user agentSHOULDensure that users are fully informed and/or give explicit consent before loading or invoking it.
Granting permissions to unauthenticated origins is equivalent to granting the permissions to any origin in the presence of a network attacker. Seeabuse of persisted consent.
This section is non-normative.
Potential network attacks and their implications include:
DNS spoofing attacks: One cannot guarantee that a host claiming to be in a certain domain (origin) really is from that domain.
Passive network attacks: One cannot guarantee that data, includingDistinctive Identifiers andDistinctive Permanent Identifiers, transmitted between the client and server is not viewed by other entities. SeeUser Tracking.
Active network attacks: One cannot guarantee that Additional scripts or iframes are not injected into pages (both those that use the APIs defined in this specification for legitimate purposes and pages that do not use them). The consequences are that:
Calls to the APIs defined in this specification can be injected into any page.
Calls to the APIs defined in this specification from pages using them for legitimate reasons can be manipulated, including modifying the requested functionality, modifying or adding calls, and modifying or injecting data. See alsoInput Data Attacks and Vulnerabilities
Data, includingDistinctive Identifiers andDistinctive Permanent Identifiers, transmitted between the client and server can be viewed and/or modified by other entities. SeeUser Tracking.
Abuse of persisted consent: One cannot guarantee that the host requesting use of the APIs defined in this specification is the host to which the user previously provided consent. The consequences are that granting permissions to unauthenticated origins is equivalent to granting the permissions to any origin in the presence of a network attacker.
The following techniques may mitigate the risks:
Applications using TLS can be sure that only the user, software working on behalf of the user, and other pages using TLS that have certificates identifying them as being from the same domain, can interact with that application. Furthermore,origin-specific permissions in combination with a secure origin, ensure that permissions granted to an application cannot be abused by a network attacker.
The APIs defined in this specification are only exposed on secure contexts. See alsoSecure Origin and Transport.
User agentsMUST properly handle Mixed Content [MIXED-CONTENT], including blocking "Blockable Content" [MIXED-CONTENT] to avoid potential exposure to insecure content. Such exposure could compromise other mitigations, such as use of TLS.
User agentsMAY choose to block all Mixed Content, including "Optionally-blockable Content" [MIXED-CONTENT] to further increase security by preventinguntrusted media data from being passed to theCDM (seeCDM Attacks and Vulnerabilities).
User agentsSHOULD ensure that users are fully informed and/or give explicit consent before aKey System that presents security concerns that are greater than other user agent features (e.g., DOM content) may be accessed by anorigin.
Such mechanismsMUST be perorigin to avoid valid uses enabling subsequent malicious access andMUST be perbrowsing profile.
The restriction of the APIs defined in this specification to secure contexts ensures that anetwork attacker cannot exploit permissions granted to an unauthenticated origin. Seeabuse of persisted consent.
This section is non-normative.
Malicious pages could host legitimate applications in an iframe in an attempt hide an attack or deceive the user as to the source, such as making the use appear to be from a legitimate content provider. This is especially relevent for implementations thatinform the user or require consent, such as for security and/orprivacy reasons. In addition toNetwork Attacks, attackers could try to exploit legitimate uses of the APIs defined in this specification by hosting them in aniframe
. By having the legitimate application performing the actions, the attacker can reuse existing granted permissions (or whitelisting) and/or appear to be a legitimate request or use.
User agents thatinform the user or require consent, including for security and/orprivacy reasons,SHOULD base the UI and persistence of consent on the combination oforigin of the top-levelDocument and theorigin using the APIs defined in this specification. This ensures that users are informed of the main document making the request and that persisting a permission for one (legitimate) combination does not inadvertently allow malicious use to go undetected.
AuthorsSHOULD prevent other entities from hosting their applications iniframe
s. Applications that must support being hosted for legitimate application-design reasonsSHOULD NOT allow hosting documents to provideany data to be passed to the CDM - either via the APIs defined in this specification or as media data - andSHOULD NOT allow hosting frames to invoke the APIs defined in this specification.
This section is non-normative.
Different authors sharing one host name, for example users hosting content ongeocities.com
, all share oneorigin. User agents do not provide features to restrict access to APIs by pathname.
Using the APIs defined in this specification on shared hosts compromises origin-based security and privacy mitigations implemented by user agents. For example, per-originDistinctive Identifiers are shared by all authors on one host name, and peristed data may be accessed and manipulated by any author on the host. The latter is especially important if, for example, modification or deletion of such data could erase a user's right to specific content.
Even if a path-restriction feature was made available by user agents, the usual DOM scripting security model would make it trivial to bypass this protection and access the data from any path.
Authors on shared hosts are thereforeRECOMMENDED to avoid using the APIs defined in this specification because doing so compromises origin-based security and privacy mitigations in user agents.
The presence or use ofKey System(s) on a user's device raises a number of privacy issues, falling into two categories: (a) user-specific information that may be disclosed by the EME interface itself or withinKey System messages and (b) user-specific information that may be persistently stored on the user's device.
User AgentsMUST take responsibility for providing users with adequate control over their own privacy. Since User Agents may integrate with third partyCDM implementations,CDM implementersMUST provide sufficient information and controls to user agent implementers to enable them to implement appropriate techniques to ensure users have control over their privacy, including but not limited to the techniques described below.
Concerns regarding information disclosed by EME andKey Systems fall into two categories: (a) concerns about non-specific information that may nevertheless contribute to the possibility of fingerprinting a user agent or device and (b) user-specific information that may be used directly foruser tracking.
Malicious applications may be able to fingerprint users or user agents by detecting or enumerating the list ofKey Systems that are supported and related information. If proper origin protections are not provided this could include detection of sites that have been visited and information stored for those sites. In particular,Key SystemsMUST not share key or other data betweenorigins.
This section is non-normative.
CDMs, especially those implemented outside the user agent, may not have the same fundamental isolations as the web platform. It is important that steps be taken to avoid information leakage, especially across origins. This includes both in-memory and stored data. Failure to do so could lead to information leakage to/from private browsing sessions, acrossbrowsing profiles (including across operating system user accounts) and even across different browsers or applications.
To avoid such issues, user agent andCDM implementationsMUST ensure that:
CDMs have a concept of aCDM instance that is associated one-to-one with aMediaKeys
object.
Keys, licenses, other session data, and the presence of sessions are restricted to theCDM instance associated with theMediaKeys
object that created the session.
Session data is not shared betweenMediaKeys
objects orCDM instances.
Session data is not shared with media elements not associated with theMediaKeys
object that created the session. Among other things, this means a session's keysMUST not be used to decrypt content loaded by a media element whosemediaKeys
attribute is not thatMediaKeys
object.
MediaKeys
objects and the underlying implementation do not expose information outside theorigin.
Persisted session data, if applicable, is stored on a per-origin basis.
Only data stored by the requestingorigin may be loaded.
It is not possible to extract, derive or infer information from theCDM that is not either explicitly described in this specification or available to the page through other web platform APIs without user permission. This applies to any information that is exposed outside the client device or to the application, including, for example, inCDM messages.
The type of information covered by this requirement includes but is not limited to:
Location, including geolocation
Credentials or identifiers other thanDistinctive Identifiers
OS account name and other potential PII
Local directory paths, which may contain similar information.
Local network details (for example, the device's local IP address)
Local devices, including but not limited to Bluetooth, USB, and user media.
User state not associated with or stored as a result of the APIs defined in this specification.
This section is non-normative.
A third-party host (or any entity, such as an advertiser, capable of getting content distributed to multiple sites) could use aDistinctive Identifier or persistent data, including licenses, keys, key IDs, orrecords of license destruction, stored by or on behalf of theCDM to track a user across multiple sessions (including acrossorigins andbrowsing profiles), building a profile of the user's activities or interests. Such tracking would undermine the privacy protections provided by the rest of the web platform and could, for example, enable highly-targeted advertising not otherwise possible. In conjunction with a site that is aware of the user's real identity (for example, a content provider or e-commerce site that requires authenticated credentials), this could allow oppressive groups to target individuals with greater accuracy than in a world with purely anonymous web usage.
User- or client-specific information that could be obtained via implementations of the APIs in this specification includes:
Origins visited (via stored or in-memory data, permissions, etc.)
Content viewed (via stored or in-memory licenses, keys, key IDs,records of license destruction, etc.)
This specification presents a specific concern because such information is commonly stored outside the user agent (and associatedbrowsing profile storage), often in theCDM.
Since the content of licenses andrecords of license destruction areKey System-specific and since key IDs may contain any value, these data items could be abused to store user-identifying information.
Key Systems may access or create persistent or semi-persistent identifier(s) for a device or user of a device. In some cases these identifiers may be bound to a specific device in a secure manner. If these identifiers are present inKey System messages, then devices and/or users may be tracked. If the mitigations below are not applied, this could include both tracking of users / devices over time and associating multiple users of a given device.
It is important to note that such identifiers, especially those that are non-clearable, non-origin-specific, orpermanent, exceed the tracking impact of existing techniques such as cookies [COOKIES] or session identifiers embedded in URLs.
If not mitigated, such tracking may take three forms depending on the design of theKey System:
In all cases, such identifiers are expected to be available to sites and/or servers that fully support theKey System (and thus can interpretKey System messages) enabling tracking by such sites.
If identifiers exposed byKey Systems are not origin-specific, then two sites and/or servers that fully support theKey System may collude to track the user.
IfKey System messages contain information derived from a user identifier in a consistent manner, for example such that a portion of the initialKey System message for a specific content item does not change over time and is dependent on the user identifier, then this information could be used by any application to track the device or user over time.
In addition, if aKey System permits keys or other data to be stored and to be re-used between origins, then it may be possible for two origins to collude and track a unique user by recording their ability to access a common key.
Finally, if any user interface for user control ofKey Systems presents data separately from data in HTTP session cookies [COOKIES] or persistent storage, then users are likely to modify site authorization or delete data in one and not the others. This would allow sites to use the various features as redundant backup for each other, defeating a user's attempts to protect his or her privacy.
In addition to the potential for sites and other third-parties to track users, the user agent implementer,CDM vendor, or device vendor could build a profile of the user's activities or interests, such as sites using the APIs defined in this specification that the user visits. Such tracking would undermine the privacy protections provided by the rest of the web platform, especially those related to isolation of origins.
Identifiers, such asDistinctive Identifiers, may be obtained from a server operated or provided by theCDM vendor, such as via anindividualization process. The process may include providing client identifier(s), includingDistinctive Permanent Identifier(s), to the server. In order to generate a per-origin identifier, a value representing the origin may also be provided.
In such an implementation, theCDM vendor may be able to track the activity of the user, such as number of origins visited or number of times a new identifier is required. If the origin or a valueassociable with the origin is provided in the identifier request, theCDM vendor could track the sites visited by the user or user(s) of a device.
The following section describes techniques that may mitigate the risks of tracking without user consent.
Key System implementationsSHOULD avoidusing Distinctive Identifiers and Distinctive Permanent Identifiers whenever possible and only use them when they meaningfully contribute to the robustness of the implementation. SeeLimit or Avoid use of Distinctive Identifiers and Permanent Identifiers.
ImplementationsMUST NOT exposeDistinctive Permanent Identifiers to the application or origin.
Distinctive Identifiers inKey System messagesMUST be encrypted, together with a timestamp or nonce, such that theKey System messages are always different. This prevents the use ofKey System messages for tracking except by servers fully supporting theKey System. SeeEncrypt Identifiers.
User agentsSHOULD present the presence ofDistinctive Identifiers and data stored byKey Systems to the user in a way that associates them strongly with HTTP session cookies [COOKIES], including it in "remove all data", and presenting it in the same UI locations. This might encourage users to view such identifiers with healthy suspicion. User agentsSHOULD help the user avoidIncomplete Clearing of Data.
Do not provideorigin(s) or valuesassociable with origins to individualization servers or other entities not related to the origin. Follow the requirements and recommendations in theIndividualization section if such a process is used by the implementation.
For allDistinctive Values exposed to the application, implementationsMUST use a differentnon-associable by applications value for eachorigin andbrowsing profile. See8.4.1 Use Per-Origin Per-Profile Values.
This is especially important for implementations thatuse Distinctive Identifier(s). See8.5.3 Use Per-Origin Per-Profile Identifiers.
Any data used by theCDM that might impact messages or behavior in an application- or license server-visible wayMUST be partitioned byorigin andbrowsing profile andMUST NOT leak to or from private browsing sessions. This includes both in-memory and persisted data. Specifically but not exhaustively, session data, licenses, keys, and per-origin identifiersMUST be partitioned per-origin and per-browsing profile. See8.3.1 Use origin-specific and browsing profile-specificKey System storage and8.4.1 Use Per-Origin Per-Profile Values.
User agentsMUST provide users with the ability to clear any persistent data, includingDistinctive Identifiers, maintained byKey Systems. SeeAllow Persistent Data to Be Cleared.
User agentsMAY, possibly in a manner configured by the user, automatically deleteDistinctive Identifiers and/or other Key System data after a period of time.
For example, a user agent could be configured to store such data as session-only storage, deleting the data once the user had closed all the browsing contexts that could access it.
This can restrict the ability of a site to track a user, as the site would then only be able to track the user across multiple sessions when the user authenticates with the site itself (e.g., by making a purchase or signing in to a service).
However, this can also put the user's access to content, especially purchased or rented content, at risk if the user does not fully understand the implications of such expiration.
User agentsMAY restrict access toKey Systems and/or features to scripts originating at theorigin of the top-levelDocument of the browsing context. For example,requestMediaKeySystemAccess
()
may deny requests for certain configurations for pages from other origins running iniframe
s.
User agentsMUST ensure that users are fully informed and/or give explicit consent beforeusing Distinctive Identifier(s) or Distinctive Permanent Identifier(s).
Such mechanismsMUST be perorigin to avoid valid uses enabling subsequent malicious access andMUST be perbrowsing profile.
The restriction of the APIs defined in this specification to secure contexts ensures that anetwork attacker cannot exploit permissions granted to an unauthenticated origin. Seeabuse of persisted consent.
User AgentsSHOULD provide users with a global control of whether aKey System is enabled and/or whetherKey Systemuse of Distinctive Identifier(s) or Distinctive Permanent Identifier(s) is enabled (if supported by theKey System). User agentsSHOULD help the user avoidIncomplete Clearing of Data.
User agentsMAY require the user to explicitly authorize access to eachKey System - and/or certain features - before a site can use it. User agentsSHOULD enable users to revoke this authorization either temporarily or permanently.
User agentsMAY allow users to share blacklists oforigins and/orKey Systems. This would allow communities to act together to protect their privacy.
While these suggestions prevent trivial use of the APIs defined in this specification for user tracking, they do not block it altogether. Within a single origin, a site can continue to track the user during a session, and can then pass all this information to a third party along with any identifying information (names, credit card numbers, addresses) obtained by the site. If a third party cooperates with multiple sites to obtain such information, and if identifiers are notunique per origin and profile, then a profile can still be created.
This section is non-normative.
Key Systems may store information on a user's device, or user agents may store information on behalf of Key Systems. Potentially, this could reveal information about a user to another user of the same device, including potentially theorigins that have used a particularKey System (i.e., sites visited) or even the content that has been decrypted using aKey System.
If information stored by one origin affects the operation of theKey System for another origin, then potentially the sites visited or content viewed by a user on one site may be revealed to another, potentially malicious, site.
If information stored for onebrowsing profile on the client device affects the operation of theKey System for otherbrowsing profiles, or browsers, then potentially the sites visited or content viewed in one may be revealed by or correlatable with anotherbrowsing profile, even including for different operating system user accounts or browsers.
Requirements mitigating these concerns are defined in8.3 Persistent Data.
This section is non-normative.
A user's attempts to protect his or her privacy by clearingDistinctive Identifiers and stored data and/or disabling aKey System may be defeated if all such data and functionality as well as cookies [COOKIES] and other site data are not cleared and/or disabled at the same time. For example:
If a user clears cookies or other persistent storage without also clearingDistinctive Identifiers and data stored by Key Systems, sites can defeat those attempts by using the various features as redundant backup for each other.
If a user clearsDistinctive Identifiers without also clearing data stored byKey Systems, including persistent sessions, as well as cookies and other persistent storage, sites can defeat those attempts by using the remaining data to associate the old and new identifiers.
If a user disables aKey System, especially for a specificorigin, without also clearing cookies or other persistent storage, sites can defeat those attempts by using the remaining features.
If a user disables aKey System, then later decide to enable theKey System, without also clearing cookies or other persistent storage,Distinctive Identifiers, and data stored byKey Systems, sites may be able to associate data prior to the disabling with data and behavior after theKey System is re-enabled.
Recommendations mitigating these concerns are defined in8.3 Persistent Data.
User agents may support a mode (e.g., private browsing) of operation intended to preserve user anonymity and/or ensure records of browsing activity are not persisted on the client. The privacy concerns discussed in previous sections may be especially concerning for users employing such modes.
User agent implementers that support such mode(s)SHOULD carefully consider whether access toKey Systems should be disabled in these mode(s). For example, such modesMAY prohibit creation ofMediaKeySystemAccess
objects that support or usepersistentState
or adistinctiveIdentifier
(either as part of theCDM implementation or because the application indicated they were "required
"). If implementations do not prohibit such creation, theySHOULD inform the user of the implications and potential consequences for the expected privacy properties of such modes before allowing their use.
The APIs defined in this specification are only supported on secure origins, protecting information discussed in previous sections. Identifiers are additionally encrypted as specified inEncrypt Identifiers.
Applications, including the servers they use,SHOULD use secure transport for all traffic involving or containing data or messages from theCDM, including but is not limited to all data passed from
events and tomessage
update
()
.
All user agentsMUST properly handle Mixed Content [MIXED-CONTENT] to avoid exposure to insecure content or transport when the user agent or application wish to enforce secure origin and transport.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key wordsMAY,MUST,MUST NOT,OPTIONAL,RECOMMENDED,REQUIRED,SHALL,SHALL NOT,SHOULD, andSHOULD NOT in this document are to be interpreted as described inBCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
This section is non-normative.
This section contains example solutions for various use cases using the proposed extensions. These are not the only solutions to these use cases. Video elements are used in the examples, but the same would apply to all media elements. In some cases, such as using synchronous XHR, the examples are simplified to keep the focus on the extensions.
In this simple example, the source file andclear-text license are hard-coded in the page. Only one session will ever be created.
<script>functiononLoad() {var video =document.getElementById('video');if (!video.mediaKeys) { navigator.requestMediaKeySystemAccess('org.w3.clearkey', [ {initDataTypes: ['webm'],videoCapabilities: [{contentType:'video/webm; codecs="vp8"' }] } ]).then(function(keySystemAccess) {var promise = keySystemAccess.createMediaKeys(); promise.catch(console.error.bind(console,'Unable to create MediaKeys') ); promise.then(function(createdMediaKeys) {return video.setMediaKeys(createdMediaKeys); } ).catch(console.error.bind(console,'Unable to set MediaKeys') ); promise.then(function(createdMediaKeys) {var te =newTextEncoder();var initData = te.encode('{"kids":["LwVHf8JLtPrv2GUXFW2v_A"]}');var keySession = createdMediaKeys.createSession(); keySession.addEventListener("message", handleMessage,false);return keySession.generateRequest('keyids', initData); } ).catch(console.error.bind(console,'Unable to create or initialize key session') ); } ); } }functionhandleMessage(event) {var keySession = event.target;var te =newTextEncoder();var license = te.encode('{"keys":[{"kty":"oct","k":"tQ0bJVWb6b0KPL6KtZIy_A","kid":"LwVHf8JLtPrv2GUXFW2v_A"}],"type":"temporary"}'); keySession.update(license).catch(console.error.bind(console,'update() failed') ); }</script><bodyonload='onLoad()'><videosrc='foo.webm'autoplayid='video'></video></body>
This example selects a supportedKey System using therequestMediaKeySystemAccess
()
method then uses theInitialization Data from themedia data to generate the license request and send it to the appropriate license server. One of the supported key systems uses a serverCertificate, which is provided proactively.
<script>var licenseUrl;var serverCertificate;// Returns a Promise<MediaKeys>.functioncreateSupportedKeySystem() { someSystemOptions = [ {initDataTypes: ['keyids','webm'],audioCapabilities: [ {contentType:'audio/webm; codecs="opus"' }, {contentType:'audio/webm; codecs="vorbis"' } ],videoCapabilities: [ {contentType:'video/webm; codecs="vp9"' }, {contentType:'video/webm; codecs="vp8"' } ] } ]; clearKeyOptions = [ {initDataTypes: ['keyids','webm'],audioCapabilities: [ {contentType:'audio/webm; codecs="opus"' }, {contentType:'audio/webm; codecs="vorbis"' } ],videoCapabilities: [ {contentType:'video/webm; codecs="vp9"',robustness:'foo' }, {contentType:'video/webm; codecs="vp9"',robustness:'bar' }, {contentType:'video/webm; codecs="vp8"',robustness:'bar' }, ] } ];return navigator.requestMediaKeySystemAccess('com.example.somesystem', someSystemOptions).then(function(keySystemAccess) {// Not shown:// 1. Use both attributes of keySystemAccess.getConfiguration().audioCapabilities[0]// and both attributes of keySystemAccess.getConfiguration().videoCapabilities[0]// to retrieve appropriate stream(s).// 2. Set video.src. licenseUrl ='https://license.example.com/getkey'; serverCertificate =newUint8Array([ ... ]);return keySystemAccess.createMediaKeys(); } ).catch(function(error) {// Try the next key system. navigator.requestMediaKeySystemAccess('org.w3.clearkey', clearKeyOptions).then(function(keySystemAccess) {// Not shown:// 1. Use keySystemAccess.getConfiguration().audioCapabilities[0].contentType// and keySystemAccess.getConfiguration().videoCapabilities[0].contentType// to retrieve appropriate stream(s).// 2. Set video.src. licenseUrl ='https://license.example.com/clearkey/request';return keySystemAccess.createMediaKeys(); } ); } ).catch(console.error.bind(console,'Unable to instantiate a key system supporting the required combinations') ); }functionhandleInitData(event) {var video = event.target;if (video.mediaKeysObject ===undefined) { video.mediaKeysObject =null;// Prevent entering this path again. video.pendingSessionData = [];// Will store all initData until the MediaKeys is ready.createSupportedKeySystem().then(function(createdMediaKeys) { video.mediaKeysObject = createdMediaKeys;if (serverCertificate) createdMediaKeys.setServerCertificate(serverCertificate);for (var i =0; i < video.pendingSessionData.length; i++) {var data = video.pendingSessionData[i];makeNewRequest(video.mediaKeysObject, data.initDataType, data.initData); } video.pendingSessionData = [];return video.setMediaKeys(createdMediaKeys); } ).catch(console.error.bind(console,'Failed to create and initialize a MediaKeys object') ); }addSession(video, event.initDataType, event.initData); }functionaddSession(video, initDataType, initData) {if (video.mediaKeysObject) {makeNewRequest(video.mediaKeysObject, initDataType, initData); }else { video.pendingSessionData.push({initDataType: initDataType,initData: initData}); } }functionmakeNewRequest(mediaKeys, initDataType, initData) {var keySession = mediaKeys.createSession(); keySession.addEventListener("message", licenseRequestReady,false); keySession.generateRequest(initDataType, initData).catch(console.error.bind(console,'Unable to create or initialize key session') ); }functionlicenseRequestReady(event) {var request = event.message;var xmlhttp =newXMLHttpRequest(); xmlhttp.keySession = event.target; xmlhttp.open("POST", licenseUrl); xmlhttp.onreadystatechange =function() {if (xmlhttp.readyState ==4) {var license =newUint8Array(xmlhttp.response); xmlhttp.keySession.update(license).catch(console.error.bind(console,'update() failed') ); } } xmlhttp.send(request); }</script><videoautoplayonencrypted='handleInitData(event)'></video>
Initialization is much simpler if encrypted events do not need to be handled duringMediaKeys
initialization. This can be accomplished either by providing theInitialization Data in other ways or setting the source after theMediaKeys
object has been created. This example does the latter.
<script>var licenseUrl;var serverCertificate;var mediaKeys;// See the previous example for implementations of these functions.functioncreateSupportedKeySystem() { ... }functionmakeNewRequest(mediaKeys, initDataType, initData) { ... }functionlicenseRequestReady(event) { ... }functionhandleInitData(event) {makeNewRequest(mediaKeys, event.initDataType, event.initData); }createSupportedKeySystem().then(function(createdMediaKeys) { mediaKeys = createdMediaKeys;var video =document.getElementById("v"); video.src ='foo.webm';if (serverCertificate) mediaKeys.setServerCertificate(serverCertificate);return video.setMediaKeys(mediaKeys); } ).catch(console.error.bind(console,'Failed to create and initialize a MediaKeys object') );</script><videoid="v"autoplayonencrypted='handleInitData(event)'></video>
This is a more complete example showing all events being used.
Note thathandleMessage()
could be called multiple times, including in response to theupdate
()
call if multiple round trips are required and for any other reason the Key System might need to send a message.
<script>var licenseUrl;var serverCertificate;var mediaKeys;// See previous examples for implementations of these functions.// createSupportedKeySystem() additionally sets renewalUrl.functioncreateSupportedKeySystem() { ... }functionhandleInitData(event) { ... }// This replaces the implementation in the previous example.functionmakeNewRequest(mediaKeys, initDataType, initData) {var keySession = mediaKeys.createSession(); keySession.addEventListener('message', handleMessage,false); keySession.addEventListener('keystatuseschange', handlekeyStatusesChange,false); keySession.closed.then(function(reason) {console.log('Session',this.sessionId,'closed, reason', reason); }.bind(keySession) ); keySession.generateRequest(initDataType, initData).catch(console.error.bind(console,'Unable to create or initialize key session') ); }functionhandleMessageResponse(keySession, response) {var license =newUint8Array(response); keySession.update(license).catch(function(err) {console.error('update() failed: ' + err); } ); }functionsendMessage(type, message, keySession) {var url = licenseUrl;if (type =="license-renewal") url = renewalUrl; xmlhttp =newXMLHttpRequest(); xmlhttp.keySession = keySession; xmlhttp.open('POST', url); xmlhttp.onreadystatechange =function() {if (xmlhttp.readyState ==4)handleMessageResponse(xmlhttp.keySession, xmlhttp.response); } xmlhttp.send(message); }functionhandleMessage(event) {sendMessage(event.messageType, event.message, event.target); }functionhandlekeyStatusesChange(event) {// Evaluate the current state using one of the map-like methods exposed by// event.target.keyStatuses.// For example: event.target.keyStatuses.forEach(function(status, keyId) {switch (status) {case"usable":break;case"expired":// Report an expired key.break;case"status-pending":// The status is not yet known. Consider the key unusable until the status is updated.break;default:// Do something with |keyId| and |status|. } }) }createSupportedKeySystem().then(function(createdMediaKeys) { mediaKeys = createdMediaKeys;var video =document.getElementById("v"); video.src ='foo.webm';if (serverCertificate) mediaKeys.setServerCertificate(serverCertificate);return video.setMediaKeys(mediaKeys); } ).catch(console.error.bind(console,'Failed to create and initialize a MediaKeys object') );</script><videoid="v"autoplayonencrypted='handleInitData(event)'></video>
This example requests a persistent license for future use and stores it. It also provides functions for later retrieving the license and for destroying it.
<script>var licenseUrl;var serverCertificate;var mediaKeys;// See the previous examples for implementations of these functions.// createSupportedKeySystem() additionally sets persistentState: "required" in each options dictionary.functioncreateSupportedKeySystem() { ... }functionsendMessage(message, keySession) { ... }functionhandleMessage(event) { ... }// Called if the application does not have a stored sessionId for the media resource.functionmakeNewRequest(mediaKeys, initDataType, initData) {var keySession = mediaKeys.createSession("persistent-license"); keySession.addEventListener('message', handleMessage,false); keySession.closed.then(function(reason) {console.log('Session',this.sessionId,'closed, reason', reason); }.bind(keySession) ); keySession.generateRequest(initDataType, initData).then(function() {// Store this.sessionId in the application. }.bind(keySession) ).catch(console.error.bind(console,'Unable to request a persistent license') ); }// Called if the application has a stored sessionId for the media resource.functionloadStoredSession(mediaKeys, sessionId) {var keySession = mediaKeys.createSession("persistent-license"); keySession.addEventListener('message', handleMessage,false); keySession.closed.then(function(reason) {console.log('Session',this.sessionId,'closed, reason', reason); }.bind(keySession) ); keySession.load(sessionId).then(function(loaded) {if (!loaded) {console.error('No stored session with the ID ' + sessionId +' was found.');// The application should remove its record of |sessionId|.return; } } ).catch(console.error.bind(console,'Unable to load or initialize the stored session with the ID ' + sessionId) ); }// Called when the application wants to stop using the session without removing the stored license.functioncloseSession(keySession) { keySession.close(); }// Called when the application wants to remove the stored license.// The stored session data has not been completely removed until the promise returned by remove() is fulfilled.// The remove() call may initiate a series of messages to/from the server that must be completed before this occurs.functionremoveStoredSession(keySession) { keySession.remove().then(function() {console.log('Session ' +this.sessionId +' removed');// The application should remove its record of this.sessionId. }.bind(keySession) ).catch(console.error.bind(console,'Failed to remove the session') ); }// This replaces the implementation in the previous example.functionhandleMessageResponse(keySession, response) {var license =newUint8Array(response); keySession.update(license).then(function() {// If this was the last required message from the server, the license is// now stored. Update the application state as appropriate. } ).catch(console.error.bind(console,'update() failed') ); }createSupportedKeySystem().then(function(createdMediaKeys) { mediaKeys = createdMediaKeys;var video =document.getElementById("v");if (serverCertificate) mediaKeys.setServerCertificate(serverCertificate);return video.setMediaKeys(mediaKeys); } ).catch(console.error.bind(console,'Failed to create and initialize a MediaKeys object') );</script><videoid='v'src='foo.webm'autoplay></video>
If some media will have an HDCP policy in the license, an application can check for that version before pre-fetching.
const status =await video.mediaKeys.getStatusForPolicy({minHdcpVersion:'1.4'});if (status ==='usable') {// Pre-fetch HD content.}else {// 'output-restricted'// Pre-fetch SD content.}
The editors would like to thank Aaron Colwell, Alex Russell, Anne van Kesteren, Bob Lund, Boris Zbarsky, Chris Needham, Chris Pearce, David Singer, Domenic Denicola, Frank Galligan, Glenn Adams, Henri Sivonen, Jer Noble, Joe Steele, Joey Parrish, John Simmons, Mark Vickers, Pavel Pergamenshchik, Philip Jägenstedt, Pierre Lemieux, Robert O'Callahan, Ryan Sleevi, Steve Heffernan, Steven Robertson Theresa O'Connor, Thomás Inskip, Travis Leithead, and Xiaohan Wang for their contributions to this specification. Thank you also to the many others who contributed to the specification, including through their participation on the mailing list and in the issues.
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: