Copyright © 2017 W3C ® ( MIT , ERCIM , Keio , Beihang ). W3C liability , trademark and permissive document license rules apply.
This
proposal
extends
HTMLMediaElement
[
HTML51
]
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 the Clear 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. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.
The
"persistent-usage-record"
session
type
and
the
related
MediaKeySession
destroyed
algorithm
were
removed
since
the
previous
version.
This
document
was
published
by
the
HTML
Media
Extensions
Working
Group
as
a
Proposed
Recommendation.
This
an
Editor's
Draft.
Comments
regarding
this
document
is
intended
to
become
a
W3C
Recommendation.
The
W3C
Membership
and
other
interested
parties
are
invited
to
review
the
document
and
welcome.
Please
send
comments
via
GitHub
them
to
public-html-media@w3.org
(
subscribe
,
mailing
list
archives
)
through
13
April
2017.
Advisory
Committee
Representatives
should
consult
their
WBS
questionnaires
.
Note
that
substantive
technical
comments
were
expected
during
the
Candidate
Recommendation
review
period
that
ended
02
August
2016.
W3C
is
also
soliciting
feedback
of
the
W3C
Security
Disclosures
Best
Practices
.
This
Team
Submission
contains
a
template
intended
for
organizations
interested
in
protecting
their
users
and
applications
from
fraud,
malware,
and
computer
viruses,
as
well
as
interested
in
ensuring
proper
adherence
to
security
and
privacy
considerations
included
in
W3C
Recommendations.
It
also
helps
to
support
broad
participation,
testing,
and
audit
from
the
security
community
to
keep
users
safe
and
the
web’s
security
model
intact.
Please
send
comments
to
public-security-disclosure@w3.org
.
).
Please see the Working Group's implementation report .
Publication
as
a
Proposed
Recommendation
an
Editor's
Draft
does
not
imply
endorsement
by
the
W3C
Membership.
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 the 5 February 2004 W3C Patent Policy . W3C maintains a public 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 contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy .
This document is governed by the 1 March 2017 W3C 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
other
HTMLMediaElement
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 the Key System and its implementation(s). 8. Implementation Requirements contains security and privacy provisions related to the integration and use of underlying Key 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 more Key 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 a CDM and identify the source of a key-related event. User agents MUST support the Common Key Systems . User agents MAY also provide additional CDMs 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 is RECOMMENDED that CDMs 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
the
CDM
as
a
result
of
which
key(s)
are
made
available
to
the
CDM
.
CDM.
Sessions
are
embodied
as
MediaKeySession
objects.
Each
Key
session
is
associated
with
a
single
instance
of
Initialization
Data
provided
in
the
generateRequest()
call.
Each
Key
Session
is
associated
with
a
single
MediaKeys
object,
and
only
media
element(s)
associated
with
that
MediaKeys
object
may
access
key(s)
associated
with
the
session.
Other
MediaKeys
objects,
CDM
instances,
and
media
elements
MUST
NOT
access
the
key
session
or
use
its
key(s).
Key
sessions
and
the
keys
they
contain
are
no
longer
usable
for
decryption
once
the
session
has
been
closed,
including
when
the
MediaKeySession
object
is
destroyed.
All license(s) and key(s) associated with a Key Session which have not been explicitly stored MUST be destroyed when the Key Session is closed.
Key IDs MUST be unique within a session.
A
Session
ID
is
a
unique
string
identifier
generated
by
the
CDM
that
can
be
used
by
the
application
to
identify
MediaKeySession
objects.
A new Session ID is generated each time the user agent and CDM successfully create a new session.
Each
Session
ID
SHALL
be
unique
within
the
browsing
context
in
which
it
was
created.
For
session
types
for
which
the
Is
persistent
session
type?
algorithm
returns
true
,
Session
IDs
MUST
be
unique
within
the
origin
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
within
media
data
.
Each
such
key
is
uniquely
identified
by
a
key
ID
.
A
key
is
associated
with
the
session
used
to
provide
it
to
the
CDM.
CDM
.
(The
same
key
may
be
present
in
multiple
sessions.)
Such
keys
MUST
only
be
provided
to
the
CDM
via
an
update()
call.
(They
may
later
be
loaded
by
load()
as
part
of
the
stored
session
data.)
Authors SHOULD 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 streams SHOULD 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 the CDM is certain the key is currently usable to decrypt one or more blocks of media 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.
A key 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 the media data . Initialization Data MAY 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 the media data or media resource . Licenses provided to the CDM associate each key with a key ID so the CDM can select the appropriate key when decrypting an encrypted block of media data.
A
key
is
considered
to
be
known
to
a
session
if
the
CDM's
CDM
's
implementation
of
the
session
contains
any
information
-
specifically
the
key
ID
-
about
it,
regardless
of
whether
the
actual
key
is
usable
or
its
value
is
known.
Known
keys
are
exposed
via
the
keyStatuses
attribute.
Keys are considered known even after they become unusable, such as due to expiration or if they are removed but a record 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
an
update()
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 more key(s) - each associated with a key 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. It SHOULD always allow unique identification of the key(s) needed to decrypt the content. This initialization information MAY be obtained in some application-specific way or provided with the media data .
Initialization Data is a generic term for container-specific data that is used by a CDM to generate a license request.
The format of the initialization data depends upon the type of container, and containers MAY support more than one format of initialization data. The Initialization Data Type is a string that indicates the format of the accompanying Initialization Data. Initialization Data Type strings are always matched case-sensitively. It is RECOMMENDED that Initialization Data Type strings are lower-case ASCII strings.
The Encrypted Media Extensions Stream Format and Initialization Data Format Registry [ EME-INITDATA-REGISTRY ] provides the mapping from Initialization Data Type string to the specification for each format.
When
the
user
agent
encounters
Initialization
Data
in
the
media
data
,
it
provides
that
Initialization
Data
to
the
application
in
the
initData
attribute
of
the
encrypted
event.
The
user
agent
MUST
NOT
store
the
Initialization
Data
or
use
its
content
at
the
time
it
is
encountered.
The
application
provides
Initialization
Data
to
the
CDM
via
generateRequest()
.
The
user
agent
MUST
NOT
provide
Initialization
Data
to
the
CDM
by
other
means.
Initialization Data MUST be a fixed value for a given set of stream(s) or media data . It MUST only contain information related to the keys required to play a given set of stream(s) or media data . It MUST NOT contain application data, client-specific data, user-specific data, or executable code.
Initialization Data SHOULD NOT contain Key System-specific data or values. Implementations MUST support the common formats defined in [ EME-INITDATA-REGISTRY ] for each Initialization Data Type they support.
Use of proprietary formats/contents is discouraged, and supporting or using only 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 identical or it is possible - with a reasonable amount of time and effort - to correlate or associate them. Otherwise, the values are non-associable .
For example, values created in the following ways are associable :
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, are non-associable .
Two or more identifiers or other values are said to be associable 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 are non-associable by an entity .
Two or more identifiers or other values are said to be non-associable by the application if they are non-associable by an entity where the entity is 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 considered associable 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 is not 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 the CDM 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
A Distinctive Permanent Identifier is a Permanent Identifier that is distinctive .
When exposed outside the client, Distinctive Permanent Identifiers and values derived from or otherwise related to them MUST be encrypted . Distinctive Permanent Identifiers MUST 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 is not a Distinctive 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
the
distinctiveIdentifier
member
of
the
MediaKeySystemAccess
used
to
create
the
MediaKeys
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 are associable 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 a central server, such as an individualization server, to associate values across origins, such as because the individualization requests contained a common value, or because values provided in individualization requests are associable by such server even after attempts to clear browsing data. Possible causes of this include use of Distinctive Permanent Identifier(s) in the individualization process.
Distinctive Identifiers exposed to the application, even in encrypted form, MUST adhere to the identifier requirements , including being encrypted , unique per origin and profile , and clearable .
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. (The Distinctive 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
the
distinctiveIdentifier
member
of
the
MediaKeySystemAccess
used
to
create
the
MediaKeys
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 is distinctive .
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 more Distinctive Permanent Identifier(s) .
The generation, individualization , provisioning or other process that produced the value involved, used, provided, derived from, or similarly involved one or more Distinctive Permanent Identifier(s) or another Distinctive Identifier.
It is clearable but not along 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 a Distinctive Permanent Identifier .
It is not clearable .
Value(s) created after clearing identifier(s) may be associable by the application with previous value(s).
Values may not be unique per origin and profile .
Values for different origins may be associable 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 an individualization 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 thus associable by the application , regardless of whether generated on the client or involving an a individualization process. For example, XORing or otherwise integrating (part of) the origin with a fixed value.
While Distinctive Identifier are usually associable by the entity that generated them they MUST be non-associable by applications . In other words, such correlation or association is only possible by the entity, such as an individualization server, that originally generated the Distinctive Identifier values. Entities with access to the Distinctive Permanent Identifier(s) MUST NOT expose this capability to applications, as this would make resulting Distinctive Identifiers associable by the application , and SHOULD 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 a Distinctive 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 a Distinctive 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 a Distinctive 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 a Distinctive Permanent Identifier or provided by such a server after providing a Distinctive 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 the CDM binary or other file used by the CDM.
Examples of things that are not Distinctive Identifiers:
A public key shared among all copies of a given CDM 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 via individualization or similar.
Device-unique keys used in attestations between, for example, the video pipeline and the CDM when the CDM 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 is non-associable (not just non-associable by applications ), even by a central server such as an individualization server, AND one or more of the following:
No Distinctive Permanent Identifier or Distinctive Identifier was involved in the generation of the value.
It is a random value generated without 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 object uses 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 more Distinctive 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 object uses 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 more Distinctive 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 an individualization server. Such values MUST NOT be provided to the application.
An implementation, configuration, instance, or object uses Distinctive Identifier(s) or Distinctive Permanent Identifier(s) if it uses Distinctive Identifier(s) and/or uses Distinctive Permanent Identifier(s) .
distinctiveIdentifier
controls
whether
Distinctive
Identifiers
and
Distinctive
Permanent
Identifiers
may
be
used.
Specifically,
such
identifiers
may
only
be
used
when
the
value
of
the
distinctiveIdentifier
member
of
the
MediaKeySystemAccess
used
to
create
the
MediaKeys
object
is
"required"
.
During
playback,
embedded
media
data
is
exposed
to
script
in
the
embedding
origin
.
In
order
for
the
API
to
provide
Initialization
Data
in
the
encrypted
event,
media
data
MUST
be
CORS-same-origin
with
the
embedding
page.
If
media
data
is
cross-origin
with
the
embedding
document,
authors
SHOULD
use
the
crossorigin
attribute
on
the
HTMLMediaElement
and
CORS
headers
on
the
media
data
response
to
make
it
CORS-same-origin
.
During
playback,
embedded
media
data
is
exposed
to
script
in
the
embedding
origin
.
In
order
for
the
API
to
provide
Initialization
Data
in
the
encrypted
event,
media
data
MUST
NOT
be
Mixed
Content
[
MIXED-CONTENT
].
Time
represents
an
instant
in
time
with
millisecond
accuracy.
The
instants
in
time
it
can
represent
are
the
same
that
can
MUST
be
equivalent
to
that
represented
with
in
ECMAScript
Date
Time
Values
and
Time
Range
objects
(ECMA-262,
section
20.3
[
ECMA-262
])
–
namely,
every
millisecond
in
the
200,000,000
days
centered
around
midnight
of
1
January,
1970
UTC,
except
for
any
millisecond
that
is
part
of
an
inserted
leap
second.
Time
does
not
include
these
added
leap
milliseconds.
].
Time
will
equal
NaN
if
no
such
time
exists
or
if
the
time
is
indeterminate.
It
should
never
have
the
value
Infinity
.
Time
generally
represents
an
instant
in
time
with
millisecond
accuracy;
however,
that
alone
is
intended
to
not
a
sufficient
definition.
The
defined
Time
Values
and
Time
Range
reference
adds
other
important
requirements.
The
time
after
which
key(s)
will
no
longer
be
consistent
with
Unix
time.
usable
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.
A valid media MIME type is a media MIME type that is also a valid MIME type [ HTML51 ]. When a MIME type includes parameters, such as `"codecs"` [ RFC6381 ], such parameters MUST also be valid per the relevant specification.
When used with the features defined in this specification, MIME type strings SHOULD explicitly specify codecs and codec constraints (e.g., per [ RFC6381 ]) unless these are normatively implied by the container.
This section defines the mechanism for obtaining access to a key system. The inclusion of capabilities in the request also enables feature detection.
The steps of an algorithm are always aborted when rejecting a promise.
MediaKeySystemConfiguration
dictionary
] enum {[SecureContext] enum MediaKeysRequirement { "required", "optional", "not-allowed" };
Enumeration description | |
---|---|
required
|
|
optional
|
|
not-allowed
|
|
] dictionary {[SecureContext] dictionary MediaKeySystemConfiguration { DOMStringlabel
= ""; sequence<DOMString>initDataTypes
= []; sequence<MediaKeySystemMediaCapability
>audioCapabilities
= []; sequence<MediaKeySystemMediaCapability
>videoCapabilities
= [];MediaKeysRequirement
distinctiveIdentifier
= "optional";MediaKeysRequirement
persistentState
= "optional"; sequence<DOMString>sessionTypes
; };
MediaKeySystemConfiguration
Members
label
of
type
DOMString
,
defaulting
to
""
MediaKeySystemConfiguration
returned
from
the
getConfiguration()
method
of
MediaKeySystemAccess
.
initDataTypes
of
type
sequence<DOMString>
,
defaulting
to
[]
audioCapabilities
of
type
sequence<
MediaKeySystemMediaCapability
>
,
defaulting
to
[]
videoCapabilities
element
must
not
be
empty.
videoCapabilities
of
type
sequence<
MediaKeySystemMediaCapability
>
,
defaulting
to
[]
audioCapabilities
element
must
not
be
empty.
distinctiveIdentifier
of
type
MediaKeysRequirement
,
defaulting
to
"optional"
When
this
member
is
"not-allowed"
,
the
implementation
MUST
NOT
use
Distinctive
Identifier(s)
or
Distinctive
Permanent
Identifier(s)
for
any
operations
associated
with
any
object
created
from
this
configuration.
persistentState
of
type
MediaKeysRequirement
,
defaulting
to
"optional"
The
CDM
MUST
NOT
persist
any
state
related
to
the
application
or
origin
of
this
object's
Document
when
this
member
is
"not-allowed"
.
For
the
purposes
of
this
member,
persistent
state
does
not
include
persistent
unique
identifiers
(
Distinctive
Identifiers
)
controlled
by
the
Key
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
is
Key
System
implementation-specific
and
may
vary
by
feature
used.
Applications
intending
to
create
non-
"temporary"
sessions,
should
set
this
member
to
"required"
when
calling
requestMediaKeySystemAccess()
.
sessionTypes
of
type
sequence<DOMString>
MediaKeySessionType
s
that
must
be
supported.
All
values
must
be
supported.
If
this
member
is
not
present
[
WebIDL
]
when
the
dictionary
is
passed
to
requestMediaKeySystemAccess()
,
the
dictionary
will
be
treated
as
if
this
member
is
set
to
[
.
"temporary"
]
Implementations
SHOULD
NOT
add
members
to
the
this
dictionary.
Should
member(s)
be
added,
they
MUST
be
of
type
MediaKeysRequirement
,
and
it
is
RECOMMENDED
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
the
requestMediaKeySystemAccess()
algorithm.
Should
an
application
use
non-standard
dictionary
member(s),
it
MUST
NOT
rely
on
user
agent
implementations
rejecting
a
configuration
that
includes
such
dictionary
members.
This dictionary MUST NOT be used to pass state or data to the CDM.
MediaKeySystemMediaCapability
dictionary
] dictionary {[SecureContext] dictionary MediaKeySystemMediaCapability { DOMStringcontentType
= ""; DOMStringrobustness
= ""; };
MediaKeySystemMediaCapability
Members
contentType
of
type
DOMString
,
defaulting
to
""
The
type
of
the
media
resource
.
Its
value
must
be
a
valid
media
MIME
type
[
HTML51
].
The
codecs
parameter,
which
certain
MIME
types
define,
might
be
necessary
to
specify
exactly
how
the
resource
is
encoded.
[
RFC6381
]
.
The
empty
string
is
invalid.
robustness
of
type
DOMString
,
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.
Implementations MUST configure the CDM to support at least the robustness levels specified in the configuration of the MediaKeySystemAccess object used to create the MediaKeys object. Exact configuration of the CDM is implementation-specific, and implementations MAY configure the CDM to use the highest robustness level in the configuration even if a higher robustness level is available. If only the empty string is specified, implementations MAY be configured to use the lowest robustness level the implementation supports.
Applications SHOULD 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
with
robustness
.
If any of a set of codecs is acceptable, use a separate instances of this dictionary for each codec.
MediaKeySystemAccess
Interface
The MediaKeySystemAccess object provides access to a Key System .
][SecureContext] interface MediaKeySystemAccess { readonly attribute DOMStringkeySystem
;MediaKeySystemConfiguration
getConfiguration
(); Promise<MediaKeys
>createMediaKeys
(); };
keySystem
of
type
DOMString
,
readonly
getConfiguration
Returns
the
supported
combination
of
configuration
options
selected
by
the
requestMediaKeySystemAccess()
algorithm.
The
returned
object
is
a
non-strict
subset
(plus
any
implied
defaults)
of
the
first
satisfiable
MediaKeySystemConfiguration
configuration
passed
to
the
requestMediaKeySystemAccess()
call
that
returned
the
promise
that
was
resolved
with
this
object.
It
does
not
contain
values
capabilities
not
specified
in
that
single
configuration
(other
than
implied
defaults)
and
thus
may
not
reflect
all
capabilities
of
the
Key
System
implementation.
All
values
in
the
configuration
may
be
used
in
any
combination.
Members
of
type
MediaKeysRequirement
reflect
whether
the
capability
is
required
for
any
combination.
They
will
not
have
the
value
"optional"
.
MediaKeySystemConfiguration
When this method is invoked, the user agent must run the following steps:
Return this object's configuration value.
This results in a new object being created and initialized from configuration each time this method is called.
createMediaKeys
Creates
a
new
MediaKeys
object
for
keySystem
.
Promise<MediaKeys>
When this method is invoked, the user agent must run the following steps:
Let promise be a new promise.
Run the following steps in parallel:
Let configuration be the value of this object's configuration value.
Let
use
distinctive
identifier
be
true
if
the
value
of
configuration
's
distinctiveIdentifier
member
is
"required"
and
false
otherwise.
Let
persistent
state
allowed
be
true
if
the
value
of
configuration
's
persistentState
member
is
"required"
and
false
otherwise.
Load and initialize the Key System implementation represented by this object's cdm implementation value if necessary.
Let instance be a new instance of the Key System implementation represented by this object's cdm implementation value.
Initialize instance to enable, disable and/or select Key System features using configuration .
If
use
distinctive
identifier
is
false
,
prevent
instance
from
using
Distinctive
Identifier(s)
and
Distinctive
Permanent
Identifier(s)
.
If
persistent
state
allowed
is
false
,
prevent
instance
from
persisting
any
state
related
to
the
application
or
origin
of
this
object's
Document
.
If
any
of
the
preceding
steps
failed,
reject
promise
with
a
new
DOMException
whose
name
is
the
appropriate
error
name
.
Let
media
keys
be
a
new
MediaKeys
object,
and
initialize
it
as
follows:
Let the use distinctive identifier value be use distinctive identifier .
Let the persistent state allowed value be persistent state allowed .
Let
the
supported
session
types
value
be
be
the
value
of
configuration
's
sessionTypes
member.
Let the cdm implementation value be this object's cdm implementation value.
Let the cdm instance value be instance .
Resolve promise with media keys .
Return promise .
MediaKeys
Interface
The MediaKeys object represents a set of keys that an associated HTMLMediaElement can use for decryption of media data during playback. It also represents a CDM instance.
A
MediaKeys
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.
] enum {[SecureContext] enum MediaKeySessionType { "temporary", "persistent-license" };
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 is REQUIRED . |
persistent-license
|
A session for which the license (and potentially other data related to the session) will be persisted. A record of license destruction SHALL be persisted when the license and key(s) it contains are destroyed. The record of license destruction is a Key System -specific attestation that the license and key(s) it contains are no longer usable by the client. Support for this session type is OPTIONAL .
Sessions
of
this
type
can
only
be
created
if
the
configuration
associated
with
the
The
|
][SecureContext] interface MediaKeys {MediaKeySession
createSession
(optionalMediaKeySessionType
sessionType = "temporary"); Promise<boolean>setServerCertificate
(BufferSource serverCertificate); };
createSession
Returns
a
new
MediaKeySession
object.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
sessionType |
MediaKeySessionType
=
"temporary"
|
✘ | ✔ | The type of session to create. The session type affects the behavior of the returned object. |
MediaKeySession
When this method is invoked, the user agent must run the following steps:
If
this
object's
supported
session
types
value
does
not
contain
sessionType
,
throw
[
WebIDL
]
a
NotSupportedError
.
sessionType
values
for
which
the
Is
persistent
session
type?
algorithm
returns
true
will
fail
if
this
object's
persistent
state
allowed
value
is
false
.
If
the
implementation
does
not
support
MediaKeySession
operations
in
the
current
state,
throw
[
WebIDL
]
an
InvalidStateError
.
Some
implementations
are
unable
to
execute
MediaKeySession
algorithms
until
this
MediaKeys
object
is
associated
with
a
media
element
using
setMediaKeys()
.
This
step
enables
applications
to
detect
this
uncommon
behavior
before
attempting
to
perform
such
operations.
Let
session
be
a
new
MediaKeySession
object,
and
initialize
it
as
follows:
Let
the
sessionId
attribute
be
the
empty
string.
Let
the
expiration
attribute
be
NaN
.
Let
the
closed
attribute
be
a
new
promise.
Let
key
status
be
a
new
empty
MediaKeyStatusMap
object,
and
initialize
it
as
follows:
Let
the
size
attribute
be
0.
Let the session type value be sessionType .
Let the uninitialized value be true.
Let the callable value be false.
Let the closing or closed value be false.
Let the use distinctive identifier value be this object's use distinctive identifier value.
Let the cdm implementation value be this object's cdm implementation .
Let the cdm instance value be this object's cdm instance .
Return session .
setServerCertificate
Provides a server certificate to be used to encrypt messages to the license server.
Key Systems that use such certificates MUST also support requesting the certificate from the server via the Queue 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 the CDM request it. It is intended as an optimization, and applications are not required to use it.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
serverCertificate |
BufferSource
|
✘ | ✘ | The server certificate. The contents are Key System -specific. It MUST NOT contain executable code. |
Promise<boolean>
When this method is invoked, the user agent must run the following steps:
If
the
Key
System
implementation
represented
by
this
object's
cdm
implementation
value
does
not
support
server
certificates,
return
a
promise
resolved
with
false
.
If
serverCertificate
is
an
empty
array,
return
a
promise
rejected
with
a
new
a
newly
created
TypeError
.
Let certificate be a copy of the contents of the serverCertificate parameter.
Let promise be a new promise.
Run the following steps in parallel:
Let sanitized certificate be a validated and/or sanitized version of certificate .
The user agent should thoroughly validate the certificate before passing it to the CDM. 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's cdm instance to process sanitized certificate .
If
the
preceding
step
failed,
resolve
promise
with
a
new
DOMException
whose
name
is
the
appropriate
error
name
.
Resolve
promise
with
true
.
Return promise .
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
a
MediaKeySessionType
value.
The following steps are run:
Let
the
session
type
be
the
specified
MediaKeySessionType
value.
Follow the steps for the value of session type from the following list:
"temporary"
false
.
"persistent-license"
true
.
This section describes general requirements related to storage and persistence.
If
a
MediaKeys
object's
persistent
state
allowed
value
is
false
then
the
object's
cdm
instance
SHALL
NOT
persist
state
or
access
previously
persisted
state
as
a
result
of
operations
on
this
object
or
any
sessions
that
it
creates.
If
a
MediaKeys
object's
persistent
state
allowed
value
is
true
then
the
object's
cdm
instance
MAY
persist
state
or
access
previously
persisted
state
as
a
result
of
operations
on
this
object
or
any
sessions
that
it
creates.
Persisted data MUST always be stored such that only the origin of this object's Document can access it. In addition, the data MUST only be accessible by the current browsing profile ; other browsing profiles, user agents, and applications MUST NOT be able to access the stored data. See Information Stored on User Devices .
See
the
10.
Security
and
11.
Privacy
sections
for
additional
considerations
when
supporting
persistent
storage.
MediaKeySession
Interface
The MediaKeySession object represents a key session .
A
MediaKeySession
object
is
closed
if
and
only
if
the
Session
Closed
object's
closed
attribute
has
been
algorithm
run.
resolved.
The
User
Agent
SHALL
execute
the
Monitor
for
CDM
Changes
algorithm
continuously
for
each
MediaKeySession
object
that
is
not
closed
.
The
Monitor
for
CDM
Changes
algorithm
MUST
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.
A
MediaKeySession
object
SHALL
NOT
be
destroyed
and
SHALL
continue
to
receive
events
if
it
is
not
closed
and
the
MediaKeys
object
that
created
it
remains
accessible.
Otherwise,
a
MediaKeySession
object
that
is
no
longer
accessible
SHALL
NOT
receive
further
events
and
MAY
be
destroyed.
The
above
rule
implies
that
the
CDM
instance
must
not
be
destroyed
until
all
MediaKeys
objects
and
all
MediaKeySession
objects
associated
with
the
CDM
instance
are
destroyed.
If
a
MediaKeySession
object
is
not
closed
when
it
becomes
inaccessible
to
the
page,
the
CDM
SHALL
close
the
key
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
applications
SHOULD
NOT
rely
on
specific
timing.
Applications
that
want
to
ensure
a
session
is
closed
before
taking
some
other
action
SHOULD
call
close()
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.
][SecureContext] interface MediaKeySession : EventTarget { readonly attribute DOMStringsessionId
; readonly attribute unrestricted doubleexpiration
; readonly attribute Promise<void>closed
; readonly attributeMediaKeyStatusMap
keyStatuses
; attribute EventHandleronkeystatuseschange
; attribute EventHandleronmessage
; Promise<void>generateRequest
(DOMString initDataType, BufferSource initData); Promise<boolean>load
(DOMString sessionId); Promise<void>update
(BufferSource response); Promise<void>close
(); Promise<void>remove
(); };
sessionId
of
type
DOMString
,
readonly
The Session ID for this object and the associated key(s) or license(s).
expiration
of
type
unrestricted
double
,
readonly
The
expiration
time
after
which
the
for
all
key(s)
in
the
session
will
no
longer
be
usable
for
decryption
,
session,
or
NaN
if
no
such
time
exists
or
if
the
license
explicitly
never
expires,
as
determined
by
the
CDM.
This value MAY change during the session lifetime, such as when an action triggers the start of a window.
closed
of
type
Promise<void>
,
readonly
Signals when the object becomes closed as a result of the Session Closed algorithm being run. This promise can only be fulfilled and is never rejected.
keyStatuses
of
type
MediaKeyStatusMap
,
readonly
A reference to a read-only map of key IDs known to the session to the current status of the associated key. Each entry MUST have a unique key ID.
The
map
entries
and
their
values
may
be
updated
whenever
the
event
loop
spins.
The
map
MUST
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
a
load()
or
update()
call.
Key
IDs
may
be
removed
as
the
result
of
a
update()
call
that
removes
knowledge
of
existing
keys
(or
replaces
the
existing
set
of
keys
with
a
new
set).
Key
IDs
MUST
NOT
be
removed
because
they
became
unusable,
such
as
due
to
expiration.
Instead,
such
keys
MUST
be
given
an
appropriate
status,
such
as
"expired"
.
Some
older
platforms
may
contain
Key
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
such
CDMs
SHOULD
implement
this
member
as
follows:
Whenever
a
non-empty
list
is
appropriate,
such
as
when
the
key
session
represented
by
this
object
may
contain
key(s)
,
populate
the
map
with
a
single
pair
containing
the
one-byte
key
ID
0
and
the
MediaKeyStatus
most
appropriate
for
the
aggregated
status
of
this
object.
onkeystatuseschange
of
type
EventHandler
Event
handler
for
the
keystatuseschange
event.
onmessage
of
type
EventHandler
Event
handler
for
the
message
event.
generateRequest
Generates
a
license
request
based
on
the
initData
.
A
message
of
type
"license-request"
or
"individualization-request"
will
always
be
queued
if
the
algorithm
succeeds
and
the
promise
is
resolved.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
initDataType |
DOMString
|
✘ | ✘ | The Initialization Data Type of the initData . |
initData |
BufferSource
|
✘ | ✘ | Initialization Data |
Promise<void>
When this method is invoked, the user agent must run the following steps:
If
this
object
is
object's
closing
or
closed
,
value
is
true,
return
a
promise
rejected
with
an
InvalidStateError
.
If
this
object's
uninitialized
value
is
false,
return
a
promise
rejected
with
an
InvalidStateError
.
Let this object's uninitialized value be false.
If
initDataType
is
the
empty
string,
return
a
promise
rejected
with
a
newly
created
TypeError
.
If
initData
is
an
empty
array,
return
a
promise
rejected
with
a
newly
created
TypeError
.
If
the
Key
System
implementation
represented
by
this
object's
cdm
implementation
value
does
not
support
initDataType
as
an
Initialization
Data
Type
,
return
a
promise
rejected
with
a
NotSupportedError
.
String
comparison
is
case-sensitive.
Let init data be a copy of the contents of the initData parameter.
Let session type be this object's session type .
Let promise be a new promise.
Run the following steps in parallel:
If
the
init
data
is
not
valid
for
initDataType
,
reject
promise
with
a
newly
created
TypeError
.
Let sanitized init data be a validated and sanitized version of init data .
The user agent MUST thoroughly validate the Initialization Data before passing it to the CDM. 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 is RECOMMENDED that user agents pre-parse, sanitize, and/or generate a fully sanitized version of the Initialization Data . If the Initialization Data format specified by initDataType supports multiple entries, the user agent SHOULD remove entries that are not needed by the CDM. The user agent MUST NOT re-order entries within the Initialization Data .
If
the
preceding
step
failed,
reject
promise
with
a
newly
created
TypeError
.
If
sanitized
init
data
is
empty,
reject
promise
with
a
NotSupportedError
.
Let session id be the empty string.
Let message be null.
Let message type be null.
Let cdm be the CDM instance represented by this object's cdm instance value.
Use the cdm to execute the following steps:
If
the
sanitized
init
data
is
not
supported
by
the
cdm
,
reject
promise
with
a
NotSupportedError
.
Follow the steps for the value of session type from the following list:
"temporary"
Let requested license type be a temporary non-persistable license.
The returned license must not be persistable or require persisting information related to it.
"persistent-license"
Let requested license type be a persistable license.
Let session id be a unique Session ID string.
If
the
result
of
running
the
Is
persistent
session
type?
algorithm
on
session
type
is
true
,
the
ID
MUST
be
unique
within
the
origin
of
this
object's
Document
over
time,
including
across
Documents
and
browsing
sessions.
Let message be a license request for the requested license type generated based on the sanitized init data interpreted per initDataType .
The cdm MUST NOT use any stream-specific data, including media data , not provided via the sanitized init data .
The cdm SHOULD NOT store session data, including the session ID, at this point. See Session Storage and Persistence .
Let
message
type
be
"license-request"
.
Let message be the request that needs to be processed before a license request request for the requested license type can be generated based on the sanitized init data .
In
a
subsequent
call
to
update()
the
CDM
MUST
generate
a
license
request
for
the
requested
license
type
based
on
the
sanitized
init
data
,
which
is
interpreted
per
initDataType
.
Let
message
type
reflect
the
type
of
message
,
either
"license-request"
or
"individualization-request"
.
queue
Queue
a
task
to
run
the
following
steps:
If
any
of
the
preceding
steps
failed,
reject
promise
with
a
new
DOMException
whose
name
is
the
appropriate
error
name
.
Set
the
sessionId
attribute
to
session
id
.
Let
Set
this
object's
callable
value
be
to
true.
Run the Queue a "message" Event algorithm on the session , providing message type and message .
Resolve promise .
Since promise handlers are queued as microtasks, these will be executed ahead of any events queued by the preceding steps.
Return promise .
load
Loads the data stored for the specified session into this object.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
sessionId |
DOMString
|
✘ | ✘ | The Session ID of the session to load. |
Promise<boolean>
When this method is invoked, the user agent must run the following steps:
If
this
object
is
object's
closing
or
closed
,
value
is
true,
return
a
promise
rejected
with
an
InvalidStateError
.
If
this
object's
uninitialized
value
is
false,
return
a
promise
rejected
with
an
InvalidStateError
.
Let this object's uninitialized value be false.
If
sessionId
is
the
empty
string,
return
a
promise
rejected
with
a
newly
created
TypeError
.
If
the
result
of
running
the
Is
persistent
session
type?
algorithm
on
this
object's
session
type
is
false
,
return
a
promise
rejected
with
a
newly
created
TypeError
.
Let promise be a new promise.
Run the following steps in parallel:
Let sanitized session ID be a validated and/or sanitized version of sessionId .
The user agent should thoroughly validate the sessionId value before passing it to the CDM. 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
if
sanitized
session
ID
is
empty,
reject
promise
with
a
newly
created
TypeError
.
If
there
is
a
MediaKeySession
object
that
is
not
closed
in
this
object's
Document
whose
sessionId
attribute
is
sanitized
session
ID
,
reject
promise
with
a
QuotaExceededError
.
In other words, do not create a session if a non-closed session, regardless of type, already exists for this sanitized session ID in this browsing context.
Let
expiration
time
be
NaN
.
Let message be null.
Let message type be null.
Let cdm be the CDM instance represented by this object's cdm instance value.
Use the cdm to execute the following steps:
If
there
is
no
data
stored
for
the
sanitized
session
ID
in
the
origin
,
resolve
promise
with
false
and
abort
these
steps.
If
the
stored
session's
session
type
is
not
the
same
as
the
current
MediaKeySession
session
type
,
reject
promise
with
a
newly
created
TypeError
.
Let session data be the data stored for the sanitized session ID in the origin . This MUST NOT include data from other origin(s) or that is not associated with an origin.
If
there
is
a
MediaKeySession
object
that
is
not
closed
in
any
Document
and
that
represents
the
session
data
,
reject
promise
with
a
QuotaExceededError
.
In other words, do not create a session if a non-closed persistent session already exists for this sanitized session ID in any browsing context.
Load the session data .
If
the
session
data
indicates
an
expiration
time
for
the
session,
let
expiration
time
be
the
that
expiration
time
in
milliseconds
since
01
January
1970
UTC.
time.
If
the
CDM
a
message
needs
to
send
a
message:
be
sent,
execute
the
following
steps:
Let
message
be
a
message
generated
by
the
CDM
based
on
the
session
data
.
Let
message
type
be
the
appropriate
MediaKeyMessageType
for
the
message.
queue
Queue
a
task
to
run
the
following
steps:
If any of the preceding steps failed, reject promise with a the appropriate error name .
Set
the
sessionId
attribute
to
sanitized
session
ID
.
Let
Set
this
object's
callable
value
be
to
true.
If
the
loaded
session
contains
information
about
any
keys
(there
are
known
keys
),
run
the
Update
Key
Statuses
algorithm
on
the
session
,
providing
each
key's
key
ID
along
with
the
appropriate
MediaKeyStatus
.
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
the
Update
Key
Statuses
algorithm
again
with
the
actual
status(es).
Run the Update Expiration algorithm on the session , providing expiration time .
If message is not null, run the Queue a "message" Event algorithm on the session , providing message type and message .
Resolve
promise
with
true
.
Since promise handlers are queued as microtasks, these will be executed ahead of any events queued by the preceding steps.
Return promise .
update
Provides messages, including licenses, to the CDM.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
response |
BufferSource
|
✘ | ✘ | A message to be provided to the CDM. The contents are Key System -specific. It MUST NOT contain executable code. |
Promise<void>
When this method is invoked, the user agent must run the following steps:
If
this
object
is
object's
closing
or
closed
,
value
is
true,
return
a
promise
rejected
with
an
InvalidStateError
.
If
this
object's
callable
value
is
false,
return
a
promise
rejected
with
an
InvalidStateError
.
If
response
is
an
empty
array,
return
a
promise
rejected
with
a
newly
created
TypeError
.
Let response copy be a copy of the contents of the response parameter.
Let promise be a new promise.
Run the following steps in parallel:
Let sanitized response be a validated and/or sanitized version of response copy .
The user agent should thoroughly validate the response before passing it to the CDM. 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
if
sanitized
response
is
empty,
reject
promise
with
a
newly
created
TypeError
.
Let message be null.
Let message type be null.
Let session closed be false.
Let cdm be the CDM instance represented by this object's cdm instance value.
Use the cdm to execute the following steps:
If
the
format
of
sanitized
response
is
invalid
in
any
way,
reject
promise
with
a
newly
created
TypeError
.
Process sanitized 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.
Process sanitized response , following the stipulation for the first matching condition from the following list:
"temporary"
and
sanitized
response
does
not
specify
that
session
data,
including
any
license,
key(s),
or
similar
session
data
it
contains,
should
be
stored
"persistent-license"
and
sanitized
response
contains
a
persistable
license
Reject
promise
with
a
newly
created
TypeError
.
See also Session Storage and Persistence .
State information, including keys, for each session MUST 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.
When sanitized 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 is Key System -dependent.
It
is
RECOMMENDED
that
CDM
implementations
support
a
standard
and
reasonably
high
minimum
number
of
keys
per
MediaKeySession
object,
including
a
standard
replacement
algorithm,
and
a
standard
and
reasonably
high
minimum
number
of
MediaKeySession
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
the
key
session
and
clear
all
stored
session
data
associated
with
this
object,
including
the
sessionId
and
record
of
license
destruction
.
Set session closed to true.
For
example,
sanitized
response
may
contain
information
that
will
be
used
to
generate
another
message
event.
In
this
case,
there
is
no
need
to
verify
the
contents
against
the
sessionType
.
If
a
message
needs
to
be
sent
to
the
server,
sent,
execute
the
following
steps:
Let message be that message.
Let
message
type
be
the
appropriate
MediaKeyMessageType
for
the
message.
queue
Queue
a
task
to
run
the
following
steps:
Run the Session Closed algorithm on this object.
Run the following steps:
If
the
set
of
keys
known
to
the
CDM
for
this
object
changed
or
the
status
of
any
key(s)
changed,
run
the
Update
Key
Statuses
algorithm
on
the
session
,
providing
each
known
key's
key
ID
along
with
the
appropriate
MediaKeyStatus
.
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
the
Update
Key
Statuses
algorithm
again
with
the
actual
status(es).
If the expiration time for the session changed, run the Update Expiration algorithm on the session , providing the new expiration time.
If
any
of
the
preceding
steps
failed,
reject
promise
with
a
new
DOMException
whose
name
is
the
appropriate
error
name
.
If message is not null, run the Queue a "message" Event algorithm on the session , providing message type and message .
Resolve promise .
Since promise handlers are queued as microtasks, these will be executed ahead of any events queued by the preceding steps.
Return promise .
close
Indicates that the application no longer needs the session and the CDM 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
the
closed
attribute
promise
is
resolved
when
the
session
is
closed.
Promise<void>
When this method is invoked, the user agent must run the following steps:
Let
session
be
the
associated
MediaKeySession
object.
If
this
object's
session
closing
or
closed
value
is
closed
,
true,
return
a
resolved
promise.
If
session
's
this
object's
callable
value
is
false,
return
a
promise
rejected
with
an
InvalidStateError
.
Let promise be a new promise.
Set this object's closing or closed value to true.
Run the following steps in parallel:
Let
cdm
be
the
CDM
instance
represented
by
session
's
this
object's
cdm
instance
value.
Use
cdm
to
close
the
key
session
associated
with
session
.
this
object.
Closing the key session results in the destruction of any license(s) and key(s) that have not been explicitly stored.
queue
Queue
a
task
to
run
the
following
steps:
Run
the
Session
Closed
algorithm
on
the
session
.
this
object.
Resolve promise .
Since promise handlers are queued as microtasks, these will be executed ahead of any events queued by the preceding steps.
Return promise .
remove
Removes
all
license(s)
and
key(s)
associated
with
the
session.
For
persistent
session
types
,
other
session
data
will
be
cleared
as
defined
for
each
session
type
once
a
release
message
acknowledgment
is
processed
by
update()
.
Promise<void>
When this method is invoked, the user agent must run the following steps:
If
this
object
is
object's
closing
or
closed
,
value
is
true,
return
a
promise
rejected
with
an
InvalidStateError
.
If
this
object's
callable
value
is
false,
return
a
promise
rejected
with
an
InvalidStateError
.
Let promise be a new promise.
Run the following steps in parallel:
Let cdm be the CDM instance represented by this object's cdm instance value.
Let message be null.
Let message type be null.
Use the cdm 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's session type from the following list:
"temporary"
Continue with the following steps.
"persistent-license"
Let record of license destruction be a record of license destruction for the license represented by this object.
Store the record of license destruction .
Let message be a message containing or reflecting the record of license destruction .
queue
Queue
a
task
to
run
the
following
steps:
Run
the
Update
Key
Statuses
algorithm
on
the
session
,
providing
all
key
ID(s)
in
the
session
along
with
the
"released"
MediaKeyStatus
value
for
each.
Run
the
Update
Expiration
algorithm
on
the
session
,
providing
NaN
.
If
any
of
the
preceding
steps
failed,
reject
promise
with
a
new
DOMException
whose
name
is
the
appropriate
error
name
.
Let
message
type
be
"license-release"
.
If
message
is
not
null
,
run
the
Queue
a
"message"
Event
algorithm
on
the
session
,
providing
message
type
and
message
.
Resolve promise .
Since promise handlers are queued as microtasks, these will be executed ahead of any events queued by the preceding steps.
Return promise .
MediaKeyStatusMap
Interface
The MediaKeyStatusMap object is a read-only map of key 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.
][SecureContext] interface MediaKeyStatusMap { iterable<BufferSource,MediaKeyStatus
>; readonly attribute unsigned longsize
; booleanhas
(BufferSource keyId); anyget
(BufferSource keyId); };
size
of
type
unsigned
long
,
readonly
The number of known keys.
has
Returns
true
if
the
status
of
the
key
identified
by
keyId
is
known.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
keyId |
BufferSource
|
✘ | ✘ | The key ID of the key. |
boolean
get
Returns
the
MediaKeyStatus
of
the
key
identified
by
keyId
or
undefined
if
the
status
of
the
key
identified
by
keyId
is
not
known.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
keyId |
BufferSource
|
✘ | ✘ | The key ID of the key. |
any
This
interface
has
entries
,
keys
,
values
,
forEach
and
@@iterator
methods
brought
by
iterable
.
The
value
pairs
to
iterate
over
are
a
snapshot
of
the
set
of
pairs
formed
from
the
key
ID
and
associated
MediaKeyStatus
value
for
all
known
keys
,
sorted
by
key
ID
,
where
for
.
Key
IDs
are
compared
as
follows:
For
key
IDs
A
and
B
,
of
lengths
length
n
m
and
m
B
respectively,
with
of
length
n
,
assigned
such
that
m
<=
m
n
,
then
we
define
let
A
<
B
if
and
only
if
the
n
m
octets
of
A
are
less
in
lexicographical
order
than
the
first
n
m
octets
of
B
or
those
octets
are
equal
and
n
m
<
m
n
.
] enum {[SecureContext] enum MediaKeyStatus { "usable", "expired", "released", "output-restricted", "output-downscaled", "status-pending", "internal-error" };
Enumeration description | |
---|---|
usable
|
The
CDM
is
certain
the
key
is
currently
usable
for
decryption
.
Keys that may not currently be usable for decryption MUST NOT have this status. |
expired
|
The
key
is
no
longer
usable
for
decryption
because
its
expiration
time
has
passed.
The time represented by the
expiration
attribute
MUST
be
earlier
than
the
current
time.
All
other
keys
in
the
session
MUST
have
this
status.
|
released
|
The key itself is no longer available to the CDM, but information about the key, such as a record 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 is OPTIONAL . Applications SHOULD NOT rely on downscaling to ensure uninterrupted playback when output requirements cannot be met. |
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 currently usable for decryption because of an error in the CDM unrelated to the other values. This value is not actionable by the application. |
MediaKeyMessageEvent
The
MediaKeyMessageEvent
object
is
used
for
the
message
event.
Events are constructed as defined in Constructing events [ DOM ].
] enum {[SecureContext] enum MediaKeyMessageType { "license-request", "license-renewal", "license-release", "individualization-request" };
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 a record of license destruction . |
individualization-request
|
The
message
contains
a
request
for
App-Assisted
Individualization
(or
re-individualization).
As with all other messages, any identifiers in the message MUST be distinctive per origin and profile and MUST NOT be Distinctive Permanent Identifier(s) . |
,[SecureContext, Constructor(DOMString type,MediaKeyMessageEventInit
eventInitDict)] interfaceMediaKeyMessageEvent
: Event { readonly attributeMediaKeyMessageType
messageType
; readonly attribute ArrayBuffermessage
; };
MediaKeyMessageEvent
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
type |
DOMString
|
✘ | ✘ | |
eventInitDict |
MediaKeyMessageEventInit
|
✘ | ✔ |
messageType
of
type
MediaKeyMessageType
,
readonly
Implementations MUST NOT require applications to handle message types. Implementations MUST support applications that do not differentiate messages and MUST NOT require that applications handle message types. Specifically, Key Systems MUST 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
type
ArrayBuffer
,
readonly
MediaKeyMessageEventInit
] dictionary {[SecureContext] dictionary MediaKeyMessageEventInit : EventInit { requiredMediaKeyMessageType
messageType
; required ArrayBuffermessage
; };
MediaKeyMessageEventInit
Members
messageType
of
type
MediaKeyMessageType
message
of
type
ArrayBuffer
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
|
The CDM has generated a message for the session. |
The
Queue
a
"message"
Event
algorithm
queues
a
message
event
to
a
MediaKeySession
object.
Requests
to
run
this
algorithm
include
a
target
MediaKeySession
object,
a
message
type
,
and
a
message
.
message
MUST
NOT
contain
Distinctive
Permanent
Identifier(s)
,
even
in
an
encrypted
form.
message
MUST
NOT
contain
Distinctive
Identifier(s)
,
even
in
an
encrypted
form,
if
the
MediaKeySession
object's
use
distinctive
identifier
value
is
false.
The following steps are run:
Let
the
session
be
the
specified
MediaKeySession
object.
queue
Queue
a
task
to
create
an
event
named
message
that
does
not
bubble
and
is
not
cancellable
using
the
MediaKeyMessageEvent
interface
with
its
type
attribute
set
to
message
and
its
isTrusted
attribute
initialized
to
true
,
and
dispatch
it
at
the
session
.
The
event
interface
MediaKeyMessageEvent
has:
messageType
=
the
specified
message
type
message
=
the
specified
message
The
Update
Key
Statuses
algorithm
updates
the
set
of
known
keys
for
a
MediaKeySession
or
the
status
of
one
or
more
of
the
keys.
Requests
to
run
this
algorithm
include
a
target
MediaKeySession
object
and
a
sequence
of
key
ID
and
associated
MediaKeyStatus
pairs.
The algorithm is always run in a task.
The following steps are run:
Let
the
session
be
the
associated
MediaKeySession
object.
Let
the
input
statuses
be
the
sequence
of
pairs
key
ID
and
associated
MediaKeyStatus
pairs.
Let
the
statuses
be
session
's
keyStatuses
attribute.
Run the following steps to replace the contents of statuses :
Empty statuses .
For each pair in input statuses .
Let pair be the pair.
Insert
an
entry
for
pair
's
key
ID
into
statuses
with
the
value
of
pair
's
MediaKeyStatus
value.
The
effect
of
this
steps
is
that
the
contents
of
session
's
keyStatuses
attribute
are
replaced
without
invalidating
existing
references
to
the
attribute.
This
replacement
is
atomic
from
a
script
perspective.
That
is,
script
MUST
NOT
ever
see
a
partially
populated
sequence.
Queue
a
task
to
fire
a
simple
event
named
keystatuseschange
at
the
session
.
Queue
a
task
to
run
the
Attempt
to
Resume
Playback
If
Necessary
algorithm
on
each
of
the
media
element(s)
whose
mediaKeys
attribute
is
the
MediaKeys
object
that
created
the
session
.
The
Update
Expiration
algorithm
updates
the
expiration
time
of
a
MediaKeySession
.
Requests
to
run
this
algorithm
include
a
target
MediaKeySession
object
and
the
new
expiration
time,
which
may
be
NaN
.
The algorithm is always run in a task.
The following steps are run:
Let
the
session
be
the
associated
MediaKeySession
object.
Let
expiration
time
be
NaN
.
If
the
new
expiration
time
is
not
NaN
,
let
expiration
time
be
the
new
that
expiration
time
in
milliseconds
since
01
January
1970
UTC.
time.
Set
the
session
's
expiration
attribute
to
expiration
time
.
expressed
as
time
.
The
Session
Closed
algorithm
updates
the
MediaKeySession
state
after
a
key
session
has
been
closed
by
the
CDM
.
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
decrypt
media
data
.
All
MediaKeySession
methods
will
fail
and
no
further
events
will
be
queued
for
this
object
after
this
algorithm
is
run.
The CDM 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, the Monitor for CDM Changes algorithm detects the change and runs this algorithm.
Keys in other sessions MUST 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 the CDM as a result of closing the session.
The following steps are run:
Let
session
be
the
associated
MediaKeySession
object.
Let
promise
be
the
session
's
closed
attribute.
If promise is resolved, abort these steps.
Set the session 's closing or closed value to true.
Run the Update Key Statuses algorithm on the session , providing an empty sequence.
Run
the
Update
Expiration
algorithm
on
the
session
,
providing
NaN
.
Let
promise
be
the
closed
attribute
of
the
session
.
Resolve
promise
.
The Monitor for CDM State Changes algorithm executes steps required when various aspects of CDM state change.
This
algorithm
only
applies
to
CDM
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:
Let
session
be
the
MediaKeySession
object.
Let cdm be the CDM instance represented by session 's cdm instance value.
If
cdm
has
an
outgoing
message
that
has
not
yet
been
sent,
then
queue
a
task
to
execute
the
following
steps:
Let message type and message be the message type and message, respectively.
Run the Queue a "message" Event algorithm, passing session , message type and message .
If
cdm
has
changed
the
set
of
keys
known
to
session
or
the
status
of
one
or
more
of
the
keys,
then
queue
a
task
to
execute
the
following
steps:
Let
statuses
be
a
list
of
Key
key
ID
and
MediaKeyStatus
value
pairs
containing
one
pair
for
each
key
known
to
session
.
Run the Update Key Statuses algorithm, passing session and statuses .
If
cdm
has
changed
the
expiration
time
of
session
,
then
queue
a
task
to
execute
the
following
steps:
Let expiration time be the new expiration time of session .
Run the Update Expiration algorithm, passing session and expiration time .
If
cdm
has
closed
session
,
then
queue
a
task
to
run
the
Session
Closed
algorithm
on
session
.
If
cdm
had
become
unavailable,
then
queue
a
task
to
run
the
Session
Closed
algorithm
on
session
.
The
methods
report
errors
by
rejecting
the
returned
promise
with
a
simple
exception
[
WebIDL
]
or
a
DOMException
.
The
following
simple
exceptions
and
DOMException
names
from
[
WebIDL
]
are
used
in
the
algorithms.
Causes
specified
specified
in
the
algorithms
are
listed
alongside
each
name,
though
these
names
MAY
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
existing
MediaKeys
object
cannot
be
removed.
The key system is not supported. The initialization data type is not supported by the key system. The session type is not supported by the key system. The initialization data is not supported by the key system. The operation is not supported by the key system. |
InvalidStateError
|
The
existing
MediaKeys
object
cannot
be
removed
at
this
time.
The session has already been used. The session is not yet initialized. The session is closed. |
QuotaExceededError
|
The
MediaKeys
object
cannot
be
used
with
additional
HTMLMediaElements.
A non-closed session already exists for this sessionId. |
This section provides an overview of session storage and persistence that complements the algorithms.
The following requirements apply in addition to those in Storage and Persistence .
If
the
result
of
running
the
Is
persistent
session
type?
algorithm
on
this
object's
session
type
is
false
,
the
user
agent
and
CDM
MUST
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
the
Session
ID
.
The
remainder
of
this
section
applies
to
session
types
for
which
the
Is
persistent
session
type?
algorithm
returns
true
.
The
CDM
SHOULD
NOT
store
session
data,
including
the
Session
ID,
until
update()
is
called
the
first
time.
Specifically,
the
CDM
SHOULD
NOT
store
session
data
during
the
generateRequest()
algorithm.
This
ensures
that
the
application
is
aware
of
the
session
and
knows
it
needs
to
eventually
remove
it.
All
data
associated
with
a
session
MUST
be
cleared
when
the
session
is
cleared,
such
as
in
update()
when
processing
a
record
of
license
destruction
acknowledgement.
See
Persistent
Data
.
The
CDM
MUST
ensure
that
data
for
a
given
session
is
only
present
in
one
MediaKeySession
object
that
is
not
closed
in
any
Document
.
In
other
words,
load()
MUST
fail
when
there
is
already
a
MediaKeySession
representing
the
session
specified
by
the
sessionId
parameter,
either
because
the
object
that
created
it
via
generateRequest()
is
still
active
or
it
has
been
loaded
into
another
object
via
load()
.
A
session
MAY
only
be
loaded
again
if
all
objects
that
have
ever
represented
it
are
closed
.
An
application
that
creates
a
session
using
a
type
for
which
the
Is
persistent
session
type?
algorithm
returns
true
SHOULD
later
remove
the
stored
data
by
first
initiating
the
removal
process
using
remove()
and
then
ensuring
that
the
removal
process,
which
may
involve
message
exchange(s),
successfully
completes.
The
CDM
MAY
also
remove
sessions
as
appropriate,
but
applications
SHOULD
NOT
rely
on
this.
.
See
the
10.
Security
and
11.
Privacy
sections
for
additional
considerations
when
supporting
persistent
storage.
HTMLMediaElement
Extensions
This
section
specifies
additions
to
and
modifications
of
the
HTMLMediaElement
[
HTML51
]
when
the
Encrypted
Media
Extensions
are
supported.
The
following
internal
values
are
added
to
the
HTMLMediaElement
:
attaching media keys , which SHALL have a boolean value, and
encrypted block queue , which SHALL be a queue of encrypted blocks awaiting decryption, and
decryption blocked waiting for key , which SHALL have a boolean value.
playback blocked waiting for key , which SHALL have a boolean value.
The
following
modifications
are
made
to
the
behaviour
of
the
HTMLMediaElement
:
When
a
HTMLMediaElement
is
created,
its
attaching
media
keys
value
SHALL
be
initialized
to
false
,
its
encrypted
block
queue
value
SHALL
be
empty,
its
decryption
blocked
waiting
for
key
value
SHALL
be
initialized
to
false
,
and
its
playback
blocked
waiting
for
key
value
SHALL
be
initialized
to
false
.
When
the
current
playback
position
is
changed
other
than
advancing
in
the
direction
of
playback
as
part
of
normal
playback,
the
encrypted
block
queue
value
SHALL
be
empty,
the
decryption
blocked
waiting
for
key
value
SHALL
be
initialized
to
false
,
and
the
playback
blocked
waiting
for
key
value
SHALL
be
set
to
false
.
In other words, these values should be reset when, for example, loading the media resource or seeking .
In
addition
to
the
criteria
specified
in
[
HTML51
],
an
HTMLMediaElement
SHALL
be
considered
a
blocked
media
element
if
its
playback
blocked
waiting
for
key
value
is
true
.
When the user agent is ready to begin playback and has encountered an indication that the media data may contain encrypted blocks during the resource fetch algorithm , the user agent SHALL run the Media Data May Contain Encrypted Blocks algorithm.
For some container formats, such indication is separate from Initialization Data .
The algorithm is to be run after parsing the relevant container data, including running the Initialization Data Encountered algorithm, but before decoding starts.
When the user agent encounters Initialization Data in the media data during the resource fetch algorithm , the user agent SHALL run the Initialization Data Encountered algorithm.
Some container formats may support encrypted media data that does not contain Initialization Data and thus support media data that does not trigger this algorithm.
For each block of encrypted media data encountered during the resource fetch algorithm , the user agent SHALL run the Encrypted 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
the
decryption
blocked
waiting
for
key
value
is
true
,
the
user
agent
SHALL
run
the
Wait
for
Key
algorithm.
The user agent cannot advance the current playback position in the direction of playback .
The user agent cannot provide data for the current playback position .
For example, at the beginning of playback or after seeking .
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.
partial interface HTMLMediaElement {
]
[SecureContext]
readonly attribute MediaKeys
? mediaKeys;
]
attribute EventHandler onencrypted
;
attribute EventHandler onwaitingforkey
;
[SecureContext]
Promise<void> setMediaKeys
(MediaKeys
? mediaKeys);
};
mediaKeys
of
type
MediaKeys
,
readonly
,
nullable
The MediaKeys being used when decrypting encrypted media data for this media element.
onencrypted
of
type
EventHandler
Event
handler
for
the
encrypted
event.
It
MUST
be
supported
by
all
HTMLMediaElements
as
both
a
content
attribute
and
an
IDL
attribute.
onwaitingforkey
of
type
EventHandler
Event
handler
for
the
waitingforkey
event.
It
MUST
be
supported
by
all
HTMLMediaElements
as
both
a
content
attribute
and
an
IDL
attribute.
setMediaKeys
Provides the MediaKeys to use when decrypting media data during playback.
Support for clearing or replacing the associated MediaKeys object during playback is a quality of implementation issue. In many cases it will result in a bad user experience or rejected promise.
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
mediaKeys |
MediaKeys
|
✔ | ✘ | A MediaKeys object. |
Promise<void>
When this method is invoked, the user agent must run the following steps:
If
mediaKeys
and
the
mediaKeys
attribute
are
the
same
object,
return
a
resolved
promise.
If
this
object's
attaching
media
keys
value
is
true,
return
a
promise
rejected
with
an
InvalidStateError
.
If
mediaKeys
and
the
mediaKeys
attribute
are
the
same
object,
return
a
resolved
promise.
Let this object's attaching media keys value be true.
Let promise be a new promise.
Run the following steps in parallel:
If all the following conditions hold:
mediaKeys is not null,
the CDM instance represented by mediaKeys is already in use by another media element
the user agent is unable to use it with this element
then
let
this
object's
attaching
media
keys
value
be
false
and
reject
promise
with
a
QuotaExceededError
.
If
the
mediaKeys
attribute
is
not
null,
run
the
following
steps:
If
the
user
agent
or
CDM
do
not
support
removing
the
association,
let
this
object's
attaching
media
keys
value
be
false
and
reject
promise
with
a
NotSupportedError
.
If
the
association
cannot
currently
be
removed,
let
this
object's
attaching
media
keys
value
be
false
and
reject
promise
with
an
InvalidStateError
.
For example, some implementations may not allow removal during playback.
Stop
using
the
CDM
instance
represented
by
the
mediaKeys
attribute
to
decrypt
media
data
and
remove
the
association
with
the
media
element.
If the preceding step failed, let this object's attaching media keys value be false and reject promise with the appropriate error name .
If mediaKeys is not null, run the following steps:
Associate the CDM instance represented by mediaKeys with the media element for decrypting media data .
If the preceding step failed, run the following steps:
Set
the
mediaKeys
attribute
to
null.
Let this object's attaching media keys value be false.
Reject
promise
with
a
new
DOMException
whose
name
is
the
appropriate
error
name
.
Queue a task to run the Attempt to Resume Playback If Necessary algorithm on the media element.
Set
the
mediaKeys
attribute
to
mediaKeys
.
Let this object's attaching media keys value be false.
Resolve promise .
Return promise .
MediaEncryptedEvent
The
MediaEncryptedEvent
object
is
used
for
the
encrypted
event.
Events are constructed as defined in Constructing events [ DOM ].
[Constructor(DOMString type, optional MediaEncryptedEventInit
eventInitDict)]
interface MediaEncryptedEvent
: Event {
readonly attribute DOMString initDataType
;
readonly attribute ArrayBuffer? initData
;
};
MediaEncryptedEvent
Parameter | Type | Nullable | Optional | Description |
---|---|---|---|---|
type |
DOMString
|
✘ | ✘ | |
eventInitDict |
MediaEncryptedEventInit
|
✘ | ✔ |
initDataType
of
type
DOMString
,
readonly
initData
attribute.
initData
of
type
ArrayBuffer
,
readonly
,
nullable
MediaEncryptedEventInit
dictionary MediaEncryptedEventInit : EventInit {
DOMString initDataType
= "";
ArrayBuffer? initData
= null;
};
MediaEncryptedEventInit
Members
initDataType
of
type
DOMString
,
defaulting
to
""
initData
of
type
ArrayBuffer
,
nullable,
defaulting
to
null
This section is non-normative.
Event name | Interface | Dispatched when... | Preconditions |
---|---|---|---|
encrypted
|
MediaEncryptedEvent
|
The user agent encounters Initialization Data in the media data . |
The
element's
readyState
is
equal
to
or
greater
than
HAVE_METADATA
.
Note
It is possible that the element is playing or has played. |
waitingforkey
|
Event
|
Playback is blocked waiting for a key. |
The
readyState
is
equal
to
or
less
than
HAVE_CURRENT_DATA
.
The
element's
playback
blocked
waiting
for
key
value
is
newly
true
.
|
The
Media
Data
May
Contain
Encrypted
Blocks
algorithm
pauses
playback
if
the
user
agent
requires
specification
of
a
MediaKeys
object
before
playing
the
media
data.
Requests
to
run
this
algorithm
include
a
target
HTMLMediaElement
object.
The following steps are run:
Let
the
media
element
be
the
specified
HTMLMediaElement
object.
If
the
media
element
's
mediaKeys
attribute
is
null
and
the
implementation
requires
specification
of
a
MediaKeys
object
before
decoding
potentially-encrypted
media
data
,
run
the
following
steps:
These
steps
may
be
reached
when
the
application
provides
media
data
before
calling
setMediaKeys()
to
provide
a
MediaKeys
object.
Selecting
a
CDM
may
affect
the
pipeline
and/or
decoders
used,
so
some
implementations
may
delay
playback
of
media
data
that
may
contain
encrypted
blocks
until
a
CDM
is
specified
by
passing
a
MediaKeys
object
to
setMediaKeys()
.
Run the Wait for Key algorithm on the media element .
Wait for a signal to resume playback.
The
Initialization
Data
Encountered
algorithm
queues
an
encrypted
event
for
Initialization
Data
encounterd
in
the
media
data
.
Requests
to
run
this
algorithm
include
a
target
HTMLMediaElement
object.
The following steps are run:
Let
the
media
element
be
the
specified
HTMLMediaElement
object.
Let initDataType be the empty string.
Let initData be null.
If the media data is CORS-same-origin and not mixed content , run the following steps:
Let initDataType be the string representing the Initialization Data Type of the Initialization Data.
Let initData be the Initialization Data.
While the media element may allow loading of "Optionally-blockable Content" [ MIXED-CONTENT ], the user agent MUST NOT expose Initialization Data from such media data to the application.
queue
Queue
a
task
to
create
an
event
named
encrypted
that
does
not
bubble
and
is
not
cancellable
using
the
MediaEncryptedEvent
interface
with
its
type
attribute
set
to
and
its
isTrusted
attribute
initialized
to
message
encrypted
true
,
and
dispatch
it
at
the
media
element
.
The
event
interface
MediaEncryptedEvent
has:
initDataType
=
initDataType
initData
=
initData
readyState
is
not
changed
and
no
algorithms
are
aborted.
This
event
merely
provides
information.
The
initData
attribute
will
be
null
if
the
media
data
is
not
CORS-same-origin
or
is
mixed
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
target
HTMLMediaElement
object.
The following steps are run:
Let
the
media
element
be
the
specified
HTMLMediaElement
object.
Let block be the block of encrypted media data.
Add block to the end of the media element 's encrypted block queue .
If
the
media
element
's
decryption
blocked
waiting
for
key
value
is
false
,
run
the
Attempt
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
target
HTMLMediaElement
object.
The following steps are run:
Let
the
media
element
be
the
specified
HTMLMediaElement
object.
If the media element 's encrypted block queue is empty, abort these steps.
If
the
media
element
's
mediaKeys
attribute
is
not
null,
run
the
following
steps:
Let
media
keys
be
the
MediaKeys
object
referenced
by
that
attribute.
Let cdm be the CDM instance represented by media keys 's cdm instance value.
If cdm is no longer usable for any reason, run the following steps:
These steps are intended to be run on unrecoverable failures of the CDM.
Run the media data is corrupted steps of the resource fetch algorithm .
Run the CDM Unavailable algorithm on media keys .
Abort these steps.
If
there
is
at
least
one
MediaKeySession
created
by
the
media
keys
that
is
not
closed
,
run
the
following
steps:
This check ensures the cdm has finished loading and is a prerequisite for a matching key being available.
Let block be the first entry in the media element 's encrypted block queue .
Let the block key ID be the key ID of block .
The key ID is generally specified by the container.
Use the cdm to execute the following steps:
Let available keys be the union of keys in sessions that were created by the media keys .
Let block key be null.
If
any
of
the
available
keys
corresponds
to
the
block
key
ID
and
is
usable
for
decryption
,
let
session
be
a
MediaKeySession
object
containing
that
key
and
let
block
key
be
that
key.
If multiple sessions contain a key that is usable for decryption for the block key ID , which session and key to use is Key System -dependent.
If
the
status
of
any
of
the
available
keys
changed
as
the
result
of
running
the
preceding
step,
queue
a
task
to
run
the
Update
Key
Statuses
algorithm
on
each
affected
session
,
providing
all
key
ID(s)
in
the
session
along
with
the
appropriate
MediaKeyStatus
value(s)
for
each.
If block key is not null, run the following steps:
Use the cdm to decrypt block using block key .
Follow the steps for the first matching condition from the following list:
Run the media data is corrupted steps of the resource fetch algorithm .
If cdm is no longer usable for any reason then run the CDM Unavailable algorithm on media keys .
Abort these steps.
Remove block from the front of the media element 's encrypted 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 the block key ID in any session so continue.
Set
the
media
element
's
decryption
blocked
waiting
for
key
value
to
true
.
This step is reached when there is no key that is usable for decryption for block .
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 the Wait 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 the resource fetch algorithm :
Let encrypted be false.
Detect whether the frame is encrypted.
Decode the frame.
Provide the frame for rendering.
The
Wait
for
Key
algorithm
queues
a
waitingforkey
event
and
updates
readyState
.
It
should
only
be
called
when
the
HTMLMediaElement
object
is
potentially
playing
and
its
readyState
is
equal
to
HAVE_FUTURE_DATA
or
greater.
Requests
to
run
this
algorithm
include
a
target
HTMLMediaElement
object.
The following steps are run:
Let
the
media
element
be
the
specified
HTMLMediaElement
object.
If
the
media
element
's
playback
blocked
waiting
for
key
value
is
true
,
abort
these
steps.
Set
the
media
element
's
playback
blocked
waiting
for
key
value
to
true
.
As a result of the above step, the media element will become a blocked 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
the
readyState
of
media
element
to
HAVE_CURRENT_DATA
.
Set
the
readyState
of
media
element
to
HAVE_METADATA
.
In
other
words,
if
the
video
frame
and
audio
data
for
the
current
playback
position
have
been
decoded
because
they
were
unencrypted
and/or
successfully
decrypted,
set
readyState
to
HAVE_CURRENT_DATA
.
Otherwise,
including
if
this
was
previously
the
case
but
the
data
is
no
longer
available,
set
readyState
to
HAVE_METADATA
.
Queue
a
task
to
fire
a
simple
event
named
waitingforkey
at
the
media
element
.
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
currently
usable
for
decryption
Requests
to
run
this
algorithm
include
a
target
HTMLMediaElement
object.
The following steps are run:
Let
the
media
element
be
the
specified
HTMLMediaElement
object.
If
the
media
element
's
playback
blocked
waiting
for
key
is
false
,
abort
these
steps.
Run the Attempt to Decrypt algorithm on the media element .
If the user agent can advance the current playback position in the direction of playback :
Set
the
media
element
's
decryption
blocked
waiting
for
key
value
to
false
.
Set
the
media
element
's
playback
blocked
waiting
for
key
value
to
false
.
As a result of the above step, the media element may no longer be a blocked media element and thus playback may resume.
Set
the
media
element
's
readyState
value
to
HAVE_CURRENT_DATA
,
HAVE_FUTURE_DATA
or
HAVE_ENOUGH_DATA
as
appropriate
.
States
beyond
HAVE_CURRENT_DATA
and
the
canplaythrough
event
do
not
(or
are
unlikely
to)
consider
key
availability
beyond
the
current
key.
The
change
in
ready
state
may
also
cause
HTMLMediaElement
events
to
be
fired
as
described
here
.
This section is non-normative.
Media data processed by a CDM MAY be unavailable through web platform APIs in the usual way (for example using the CanvasRenderingContext2D drawImage() method and the AudioContext 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 they MAY 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,
then
the
full
set
of
HTML
rendering
capabilities,
for
example
CSS
Transforms,
MAY
be
unavailable.
One
likely
restriction
is
that
video
media
MAY
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
and
Key
Systems
,
including
the
CDM
and
server
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
the
CDM
is
separate
from
or
a
part
of
the
user
agent.
User agent implementers MUST ensure that CDMs 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, the CDM SHALL 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 than CDM state and persistent 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 own CDM may include the above as design requirements for that component. A User Agent implementer making use of a third party CDM 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 the CDM, such as between the CDM and a license server, MUST be passed through the user agent. The CDM MUST NOT make direct out-of band network requests. All messages and communication other than those described in Direct Individualization MUST 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
the
CDM,
or
by
the
User
Agent
on
behalf
of
the
CDM,
that
exists
after
the
destruction
of
the
MediaKeys
object.
Specifically,
it
includes
any
identifiers
(including
Distinctive
Identifier(s)
),
licenses,
keys,
key
IDs,
or
records
of
license
destruction
stored
by
the
CDM
or
by
the
User
Agent
on
behalf
of
the
CDM.
Persistent Data that might impact messages or behavior in an application- or license server-visible way MUST be stored in an origin -specific and browsing profile -specific way and MUST NOT leak to or from private browsing sessions. Specifically but not exhaustively, session data, licenses, keys and per-origin identifiers MUST be stored per- origin and per- browsing profile .
Implementations that use Persistent Data MUST 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 Agents SHOULD :
Treat Persistent Data like other site data, such as cookies [ COOKIES ]. Specifically:
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. See incomplete clearing of data .
Present these interfaces in a way that helps users to understand the possibility of incomplete 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 a Key System in a way that helps users to understand the possibility of incomplete clearing of data and enables them to delete all such data in all persistent storage features simultaneously.
Allow users to specifically delete Persistent Data, by origin and/or for all origins.
User agents SHOULD 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 agents SHOULD 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 the CDM, 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 for Identifiers .
All distinctive values exposed to or inferable by the application MUST be unique per origin and browsing profile . That is, the value(s) used for one origin using the APIs defined in this specification MUST be different from those used for any other origin using the APIs, and value(s) used in one browsing profile MUST be different from those used for any other profile, regardless of origin. Such values MUST NOT leak to or from private browsing sessions.
Values across origins and profiles MUST be non-associable by applications , meaning it MUST 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 in Allow Persistent Data to Be Cleared , all persisted values exposed to the application MUST 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, new non-associable by applications value(s) MUST be generated when values are subsequently needed.
The use of identifiers, especially Distinctive 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 for Values 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 except Permanent Identifiers MUST be unique per origin and profile , non-associable , and clearable .
All identifers SHOULD be encrypted when exposed outside the client.
Distinctive Identifiers MUST be encrypted when exposed outside the client, unique per origin and profile , and clearable .
Distinctive Permanent Identifiers MUST be encrypted when exposed outside the client and MUST NOT be exposed to the application.
All potential identifiers or distinctive values not covered above that are generated as a result of use of the APIs defined in this specification MUST be unique per origin and profile and clearable . This includes but is not limited to random identifiers, session data, and other CDM data.
Implementations SHOULD avoid use 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.
Implementations SHOULD only use Distinctive Identifier(s) or Distinctive Permanent Identifier(s) when necessary to enforce the policies related to the specific CDM instance and session.
For
example,
"temporary"
and
"persistent-license"
sessions
may
have
different
requirements.
Implementations that use Distinctive Identifier(s) or Distinctive Permanent Identifier(s) SHOULD support the option to not use them. Implementations with such support SHOULD expose the ability for the user to select this option.
When
supported,
applications
can
select
for
this
mode
using
distinctiveIdentifier
=
"not-allowed"
.
Selecting
such
an
option
may
affect
the
results
of
the
requestMediaKeySystemAccess()
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 and Distinctive Permanent Identifiers MUST be encrypted at the message exchange level when exposed outside the client. All other identifiers SHOULD be encrypted at the message exchange level when exposed outside the client. The encryption MUST ensure that any two instances of the identifier ciphertext are associable only by an entity in possession of the decryption key.
Identifiers may be exposed in the following ways:
To
the
application
via
a
message
event.
In
a
message
from
a
server,
such
as
one
that
is
passed
to
update()
.
As part of individualization .
The CDM MUST verify that the encryption key belongs to a valid server for its Key System. For identifers exposed to the application, this MAY be implemented using a server certificate .
The server MUST NOT expose a Distinctive Identifier to any entity other than the CDM that sent it.
Specifically, it should not be provided to the application or included unencrypted in messages to the CDM. This can be accomplished by encrypting the identifier or message with the identifier or such that it is only decryptable by that specific CDM.
Among other things, this means that:
Every signature made with device-specific or user-specific keys MUST be different, even given the same plaintext.
Identifiers, keys, or certificates relating to device-specific or user-specific keys MUST be encrypted for the license or individualization server.
Messages from the license server to the CDM MUST NOT expose recipient-unique identifiers, such as the ID of the intended decryption key, on the outside of the encryption envelope.
All
identifiers
except
Distinctive
Permanent
Identifiers
MUST
be
unique
per
origin
and
browsing
profile
.
See
8.2.1
8.4.1
Use
Per-Origin
Per-Profile
Values
.
This includes but is not limited to Distinctive Identifiers .
Distinctive Permanent Identifiers MUST NOT be exposed to the application or origin.
All identifiers, including Distinctive Identifiers , exposed by the implementation to applications, even in encrypted form, MUST be non-associable by application(s) across origins , browsing profiles , and clearing of identifiers .
For all such identifiers, it MUST 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 in Allow Persistent Data to Be Cleared , all potential identifiers or distinctive values except Distinctive Permanent Identifiers MUST 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 that use Distinctive Identifier(s) MUST allow the user to clear the Distinctive Identifier(s) . Implementations that use Distinctive Permanent Identifier(s) MUST allow the user to clear values associated with the Distinctive Permanent Identifier(s) .
Once cleared, new non-associable by applications value(s) MUST be generated when values, such as Distinctive Identifiers , are subsequently needed.
Identifiers, especially Distinctive Identifiers , are sometimes generated or obtained via a process called individualization or provisioning. The resulting identifier(s) MUST be non-associable by applications and use of them MUST only be exposed to a single origin from a single profile . This process MAY be performed multiple times, such as after identifier(s) are cleared .
This process MUST be performed either directly by the user agent or through 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 the CDM implementation and application of the requirements of this specification, especially those below.
distinctiveIdentifier
controls
whether
Distinctive
Identifiers
and
Distinctive
Permanent
Identifiers
may
be
used
,
including
for
individualization.
Specifically,
such
identifiers
may
only
be
used
when
the
value
of
the
distinctiveIdentifier
member
of
the
MediaKeySystemAccess
used
to
create
the
MediaKeys
object
is
"required"
.
Direct Individualization is performed between the CDM and an origin- and application-independent server. Although the server is origin-independent, the result of the individualization enables the CDM to provide origin-specific identifiers per the other requirements of this specification. The process MUST be performed by the user agent and MUST NOT use the APIs defined in this specification.
For example, such a process may initialize a client device and/or obtain a per-origin clearable identifier for a single browsing profile by communicating with a pre-determined server hosted by the user agent or CDM vendor, possibly using Distinctive Permanent Identifier(s) or other Permanent 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 the CDM.
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 all Distinctive Identifiers and Distinctive Permanent Identifiers .
MUST use TLS.
Implementations MUST NOT expose, even in encrypted form, origin(s) , origin- or application-specific information, or values that are associable 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 the CDM and the application, including an application-selected server, and results in a per-origin identifier. The process MUST be performed via the APIs defined in this specification and MUST NOT involve other methods of communication. As with all other uses of the APIs, the process MAY use one or more Distinctive Identifier(s) , but it MUST NOT use Distinctive Permanent Identifier(s) or non-origin-specific values, even in encrypted form. If the process use one or more Distinctive Identifier(s) , the resulting identifier is by definition also a Distinctive 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
message
events.
MUST NOT be performed by the user agent.
MUST NOT be performed directly by the CDM.
MUST NOT contain or otherwise use Distinctive Permanent Identifier(s) .
MUST NOT contain non-origin-specific per-client information
MUST adhere to the identifier requirements .
This includes only using values that are unique per origin and profile and clearable and encrypting them as required.
MUST NOT provide executable code to the CDM.
When associable values, including Distinctive Identifier(s) , are used in the process, implementations MUST NOT expose, even in encrypted form, origin(s) -, origin- or application-specific information, or values that are associable 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 than Direct Individualization , though not as good as models that do not use 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 them SHOULD avoid deferring or forwarding individualization messages to a central server or other server not controlled by the application author.
Implementations
MUST
support
multiple
keys
in
each
MediaKeySession
object.
The mechanics of how multiple keys are supported is an implementation detail, but it MUST be transparent to the application and the APIs defined in this specification.
Implementations
MUST
support
seamless
switching
between
keys
during
playback.
This
includes
both
keys
in
the
same
MediaKeySession
and
keys
in
separate
MediaKeySession
objects.
Implementations SHOULD allow licenses generated with any Initialization Data Type they support to be used with any content type.
Otherwise,
the
requestMediaKeySystemAccess()
algorithm
might,
for
example,
reject
a
MediaKeySystemConfiguration
because
one
of
the
initDataTypes
is
not
supported
with
one
of
the
videoCapabilities
.
For any supported Initialization Data Type that may appear in a supported container, the user agents MUST support extracting that type of Initialization Data from each such supported container.
In other words, indicating support for an Initialization Data Type implies both CDM support for generating license requests and, for container-specific types, user agent support for extracting it from the container. This does not mean that implementations must be able to parse any supported Initialization Data from any supported content type.
This
section
defines
properties
of
content
(
media
resources
resource
)
supported
by
implementations
of
this
specification.
The
media
container
MUST
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
the
Encrypted
Block
Encountered
and
Initialization
Data
Encountered
algorithms
as
well
as
supporting
standard
HTMLMediaElement
[
HTML51
]
functionality,
such
as
seeking
.
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.
The Encrypted Media Extensions Stream Format and Initialization Data 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.
Implementations
To
ensure
accessibility
information
is
available
in
usable
form,
for
implementations
that
choose
to
support
encrypted
in-band
support
content
content:
a)
the
CDM
MUST
provide
the
decrypted
data
to
the
user
agent
to
be
processed
and
b)
the
user
agent
MUST
process
it
in
the
same
way
as
equivalent
unencrypted
support
content.
For
example,
to
be
exposed
as
timed
text
tracks
[
HTML51
].
.
All user agents MUST support the common key 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.
This
Key
System
is
described
below.
The following describe how Clear Key supports key system-specific capabilities:
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
:
Implementations
MAY
support
this
type.
The
setServerCertificate()
method:
Not
supported.
The
setMediaKeys()
method:
Implementations
MAY
support
associating
the
MediaKeys
object
with
more
than
one
HTMLMediaElement
.
The following describe how Clear Key implements key system-specific behaviors:
In
the
generateRequest()
algorithm:
The generated message is a JSON object encoded in UTF-8 as described in License Request Format .
The request is generated by extracting the key IDs from the sanitized init data .
The "type" member value is the value of the sessionType parameter.
The
sessionId
attribute
is
a
numerical
value
representable
by
a
32-bit
integer.
The
expiration
attribute
is
always
NaN
.
In
the
update()
algorithm:
The response parameter is either a JWK Set as described in License Format , or a JSON object encoded in UTF-8 as described in License 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 case sanitized response is considered invalid if it is not a valid JSON object.
For
sessions
of
type
"persistent-license"
,
in
the
remove()
algorithm,
the
message
reflecting
the
record
of
license
destruction
is
a
JSON
object
encoded
in
UTF-8
as
described
in
License
Release
Format
.
The
keyStatuses
attribute
method
initially
contains
all
key
IDs
that
have
been
provided
via
update()
,
with
status
"usable"
.
When
the
remove()
algorithm
is
executed,
the
keyStatuses
attribute
will
be
set
to
an
empty
list.
Initialization
Data
:
Implementations
MAY
support
any
combination
of
registered
Initialization
Data
Types
[
EME-INITDATA-REGISTRY
].
Implementations
SHOULD
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
message
event.
The format is a JSON object containing the following members:
MediaKeySessionType
When
contained
in
the
ArrayBuffer
message
attribute
of
a
MediaKeyMessageEvent
object,
the
JSON
string
is
encoded
in
UTF-8
as
specified
in
the
Encoding
specification
[
ENCODING
].
Applications
MAY
decode
the
contents
of
the
ArrayBuffer
to
a
JSON
string
using
the
TextDecoder
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":
}
This
section
describes
the
format
of
the
license
to
be
provided
via
the
response
parameter
of
the
update()
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
object
MAY
have
an
optional
"type"
member
value,
which
MUST
be
one
of
the
MediaKeySessionType
values.
If
not
specified,
the
default
value
of
"temporary"
is
used.
The
update()
algorithm
compares
this
value
to
the
sessionType
.
When
passed
to
the
update()
method
as
the
ArrayBuffer
response
parameter,
the
JSON
string
MUST
be
encoded
in
UTF-8
as
specified
in
the
Encoding
specification
[
ENCODING
].
Applications
MAY
encode
the
JSON
string
using
the
TextEncoder
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':
}
This
section
describes
the
format
of
the
license
release
message
to
be
provided
via
the
message
attribute
of
the
message
event.
The
format
is
a
JSON
object.
For
sessions
of
type
"persistent-license"
,
the
object
shall
contain
the
following
member:
When
contained
in
the
ArrayBuffer
message
attribute
of
a
MediaKeyMessageEvent
object,
the
JSON
string
is
encoded
in
UTF-8
as
specified
in
the
Encoding
specification
[
ENCODING
].
Applications
MAY
decode
the
contents
of
the
ArrayBuffer
to
a
JSON
string
using
the
TextDecoder
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
the
response
parameter
of
the
update()
method.
The format is a JSON object containing the following members:
When
passed
to
the
update()
method
as
the
ArrayBuffer
response
parameter,
the
JSON
string
MUST
be
encoded
in
UTF-8
as
specified
in
the
Encoding
specification
[
ENCODING
].
Applications
MAY
encode
the
JSON
string
using
the
TextEncoder
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
and
Key
System
implementations
MUST
consider
media
data
,
Initialization
Data
,
data
passed
to
update()
,
licenses,
key
data,
and
all
other
data
provided
by
the
application
as
untrusted
content
and
potential
attack
vectors.
They
MUST
use
appropriate
safeguards
to
mitigate
any
associated
threats
and
take
care
to
safely
parse,
decrypt,
etc.
such
data.
User
Agents
SHOULD
validate
data
before
passing
it
to
the
CDM.
Such validation is especially important if the CDM does not run in the same (sandboxed) context as, for example, the DOM.
Implementations MUST 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
the
Initialization
Data
passed
to
generateRequest()
.
Applications
must
determine
the
URLs
to
use.
The
messageType
attribute
of
the
message
event
can
be
used
by
the
application
to
select
among
a
set
of
URLs
if
applicable.
User
Agents
are
responsible
for
providing
users
with
a
secure
way
to
browse
the
web,
including
web.
This
responsibility
applies
to
any
functionality,
such
as
CDMs,
functionality
used
by
User
Agents,
including
functionalities
from
third
parties.
User
agent
implementers
MUST
obtain
sufficient
information
from
Key
System
implementers
to
enable
them
to
properly
assess
the
security
implications
of
integrating
with
the
Key
System.
User
agent
implementers
MUST
ensure
CDM
implementations
provide
and/or
support
sufficient
controls
for
the
user
agent
to
provide
security
for
the
user.
User
agent
implementers
MUST
ensure
CDM
implementations
can
and
will
be
quickly
and
proactively
updated
in
the
event
of
security
vulnerabilities.
Exploiting a CDM 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 in CDM implementations increases the risk. Such CDM implementations and UAs that expose them MUST be especially careful in all areas of security, including parsing of all data .
User agents should be especially diligent when using a CDM or underlying mechanism that is part of or provided by the client OS, platform and/or hardware.
If a user agent chooses to support a Key System implementation that cannot be sufficiently sandboxed or otherwise secured, the user agent SHOULD ensure 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. See abuse 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, including Distinctive Identifiers and Distinctive Permanent Identifiers , transmitted between the client and server is not viewed by other entities. See User 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 also Input Data Attacks and Vulnerabilities
Data, including Distinctive Identifiers and Distinctive Permanent Identifiers , transmitted between the client and server can be viewed and/or modified by other entities. See User 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 also Secure Origin and Transport .
User agents MUST 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 agents MAY choose to block all Mixed Content, including "Optionally-blockable Content" [ MIXED-CONTENT ] to further increase security by preventing untrusted media data from being passed to the CDM (see CDM Attacks and Vulnerabilities ).
User agents SHOULD ensure that users are fully informed and/or give explicit consent before a Key System that presents security concerns that are greater than other user agent features (e.g., DOM content) may be accessed by an origin .
Such mechanisms MUST be per origin to avoid valid uses enabling subsequent malicious access and MUST be per browsing profile .
The restriction of the APIs defined in this specification to secure contexts ensures that a network attacker cannot exploit permissions granted to an unauthenticated origin. See abuse of persisted consent .
iframe
Attacks
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
that
inform
the
user
or
require
consent
,
such
as
for
security
and/or
privacy
reasons
.
In
addition
to
Network
Attacks
,
attackers
could
try
to
exploit
legitimate
uses
of
the
APIs
defined
in
this
specification
by
hosting
them
in
an
iframe
.
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 that inform the user or require consent , including for security and/or privacy reasons , SHOULD base the UI and persistence of consent on the combination of origin of the top-level Document and the origin 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.
Authors
SHOULD
prevent
other
entities
from
hosting
their
applications
in
iframe
s.
Applications
that
must
support
being
hosted
for
legitimate
application-design
reasons
SHOULD
NOT
allow
hosting
documents
to
provide
any
data
to
be
passed
to
the
CDM
-
either
via
the
APIs
defined
in
this
specification
or
as
media
data
-
and
SHOULD
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
on
geocities.com
,
all
share
one
origin
.
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-origin Distinctive 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 therefore RECOMMENDED 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 of Key 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 within Key System messages and (b) user-specific information that may be persistently stored on the user's device.
User Agents MUST take responsibility for providing users with adequate control over their own privacy. Since User Agents may integrate with third party CDM implementations, CDM implementers MUST 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 and Key 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 for user tracking .
Malicious applications may be able to fingerprint users or user agents by detecting or enumerating the list of Key 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 Systems MUST not share key or other data between origins .
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, across browsing profiles (including across operating system user accounts) and even across different browsers or applications.
To avoid such issues, user agent and CDM implementations MUST ensure that:
CDMs have a concept of a CDM instance that is associated one-to-one with a MediaKeys object.
Keys, licenses, other session data, and the presence of sessions are restricted to the CDM instance associated with the MediaKeys object that created the session.
Session data is not shared between MediaKeys objects or CDM instances.
Session
data
is
not
shared
with
media
elements
not
associated
with
the
MediaKeys
object
that
created
the
session.
Among
other
things,
this
means
a
session's
keys
MUST
not
be
used
to
decrypt
content
loaded
by
a
media
element
whose
mediaKeys
attribute
is
not
that
MediaKeys
object.
MediaKeys objects and the underlying implementation do not expose information outside the origin .
Persisted session data, if applicable, is stored on a per- origin basis.
Only data stored by the requesting origin may be loaded.
It is not possible to extract, derive or infer information from the CDM 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, in CDM messages.
The type of information covered by this requirement includes but is not limited to:
Location, including geolocation
Credentials or identifiers other than Distinctive 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 a Distinctive Identifier or persistent data, including licenses, keys, key IDs, or records of license destruction , stored by or on behalf of the CDM to track a user across multiple sessions (including across origins and browsing 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 associated browsing profile storage), often in the CDM.
Since the content of licenses and records of license destruction are Key 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
in
Key
System
messages,
then
devices
and/or
users
may
be
tracked.
If
the
mitigations
below
are
not
applied
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, or permanent , 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 the Key System:
In all cases, such identifiers are expected to be available to sites and/or servers that fully support the Key System (and thus can interpret Key System messages) enabling tracking by such sites.
If identifiers exposed by Key Systems are not origin-specific, then two sites and/or servers that fully support the Key System may collude to track the user.
If Key System messages contain information derived from a user identifier in a consistent manner, for example such that a portion of the initial Key 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 a Key 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 of Key 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 as Distinctive Identifiers , may be obtained from a server operated or provided by the CDM vendor, such as via an individualization process. The process may include providing client identifier(s), including Distinctive 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, the CDM 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 value associable with the origin is provided in the identifier request, the CDM 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 implementations SHOULD avoid using Distinctive Identifiers and Distinctive Permanent Identifiers whenever possible and only use them when they meaningfully contribute to the robustness of the implementation. See Limit or Avoid use of Distinctive Identifiers and Permanent Identifiers .
Implementations MUST NOT expose Distinctive Permanent Identifiers to the application or origin.
Distinctive Identifiers in Key System messages MUST be encrypted, together with a timestamp or nonce, such that the Key System messages are always different. This prevents the use of Key System messages for tracking except by servers fully supporting the Key System. See Encrypt Identifiers .
User agents SHOULD present the presence of Distinctive Identifiers and data stored by Key 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 agents SHOULD help the user avoid Incomplete Clearing of Data .
Do not provide origin(s) or values associable with origins to individualization servers or other entities not related to the origin. Follow the requirements and recommendations in the Individualization section if such a process is used by the implementation.
For
all
distinctive
values
exposed
to
the
application,
implementations
MUST
use
a
different
non-associable
by
applications
value
for
each
origin
and
browsing
profile
.
See
8.2.1
8.4.1
Use
Per-Origin
Per-Profile
Values
.
This
is
especially
important
for
implementations
that
use
Distinctive
Identifier(s)
.
See
8.3.3
8.5.3
Use
Per-Origin
Per-Profile
Identifiers
.
Any
data
used
by
the
CDM
that
might
impact
messages
or
behavior
in
an
application-
or
license
server-visible
way
MUST
be
partitioned
by
origin
and
browsing
profile
and
MUST
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
identifiers
MUST
be
partitioned
per-
origin
and
per-
browsing
profile
.
See
8.1.1
8.3.1
Use
origin-specific
and
browsing
profile-specific
Key
System
storage
and
8.2.1
8.4.1
Use
Per-Origin
Per-Profile
Values
.
User agents MUST provide users with the ability to clear any persistent data, including Distinctive Identifiers , maintained by Key Systems. See Allow Persistent Data to Be Cleared .
User agents MAY , possibly in a manner configured by the user, automatically delete Distinctive 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
agents
MAY
restrict
access
to
Key
Systems
and/or
features
to
scripts
originating
at
the
origin
of
the
top-level
Document
of
the
browsing
context.
For
example,
requestMediaKeySystemAccess()
may
deny
requests
for
certain
configurations
for
pages
from
other
origins
running
in
iframe
s.
User agents MUST ensure that users are fully informed and/or give explicit consent before using Distinctive Identifier(s) and Distinctive Permanent Identifier(s) .
Such mechanisms MUST be per origin to avoid valid uses enabling subsequent malicious access and MUST be per browsing profile .
The restriction of the APIs defined in this specification to secure contexts ensures that a network attacker cannot exploit permissions granted to an unauthenticated origin. See abuse of persisted consent .
User Agents SHOULD provide users with a global control of whether a Key System is enabled and/or whether Key System use of Distinctive Identifier(s) and Distinctive Permanent Identifier(s) is enabled (if supported by the Key System). User agents SHOULD help the user avoid Incomplete Clearing of Data .
User agents MAY require the user to explicitly authorize access to each Key System - and/or certain features - before a site can use it. User agents SHOULD enable users to revoke this authorization either temporarily or permanently.
User agents MAY allow users to share blacklists of origins and/or Key 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 not unique 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 the origins that have used a particular Key System (i.e., sites visited) or even the content that has been decrypted using a Key System.
If information stored by one origin affects the operation of the Key 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 one browsing profile on the client device affects the operation of the Key System for other browsing profiles , or browsers, then potentially the sites visited or content viewed in one may be revealed by or correlatable with another browsing profile , even including for different operating system user accounts or browsers.
Requirements
mitigating
these
concerns
are
defined
in
8.1
8.3
Persistent
Data
.
This section is non-normative.
A user's attempts to protect his or her privacy by clearing Distinctive Identifiers and stored data and/or disabling a Key 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 clearing Distinctive 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 clears Distinctive Identifiers without also clearing data stored by Key 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 a key system, especially for a specific origin , without also clearing cookies or other persistent storage, sites can defeat those attempts by using the remaining features.
If a user disables a key system, then later decide to enable the key system, without also clearing clearing cookies or other persistent storage, Distinctive Identifiers , and data stored by Key Systems, sites may be able to associate data prior to the disabling with data and behavior after the key system is re-enabled.
Recommendations
mitigating
these
concerns
are
defined
in
8.1
8.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
to
Key
Systems
should
be
disabled
in
these
mode(s).
For
example,
such
modes
MAY
prohibit
creation
of
MediaKeySystemAccess
objects
that
support
or
use
persistentState
or
a
distinctiveIdentifier
(either
as
part
of
the
CDM
implementation
or
because
the
application
indicated
they
were
"required"
).
If
implementations
do
not
prohibit
such
creation,
they
SHOULD
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 in Encrypt Identifiers .
Applications,
including
the
servers
they
use,
SHOULD
use
secure
transport
for
all
traffic
involving
or
containing
data
or
messages
from
the
CDM,
including
but
is
not
limited
to
all
data
passed
from
message
events
and
to
update()
.
All user agents MUST 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 words MAY , MUST , MUST NOT , OPTIONAL , RECOMMENDED , REQUIRED , SHALL , SHALL NOT , SHOULD , and SHOULD NOT are to be interpreted as described in [ RFC2119 ].
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 and clear-text license are hard-coded in the page. Only one session will ever be created.
<script>
function onLoad() {
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 = new TextEncoder();
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')
);
}
);
}
}
function handleMessage(event) {
var keySession = event.target;
var te = new TextEncoder();
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>
<body onload='onLoad()'>
<video src='foo.webm' autoplay id='video'></video>
</body>
This
example
selects
a
supported
Key
System
using
the
requestMediaKeySystemAccess()
method
then
uses
the
Initialization
Data
from
the
media
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
>.
function createSupportedKeySystem() {
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 = new Uint8Array([ ... ]);
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')
);
}
function handleInitData(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
);
}
function addSession(video, initDataType, initData) {
if (video.mediaKeysObject) {
makeNewRequest(video.mediaKeysObject, initDataType, initData);
} else {
video.pendingSessionData.push({initDataType: initDataType, initData: initData});
}
}
function makeNewRequest(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')
);
}
function licenseRequestReady(event) {
var request = event.message
;
var xmlhttp = new XMLHttpRequest();
xmlhttp.keySession = event.target;
xmlhttp.open("POST", licenseUrl);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
var license = new Uint8Array(xmlhttp.response);
xmlhttp.keySession.update
(license).catch(
console.error.bind(console, 'update() failed')
);
}
}
xmlhttp.send(request);
}
</script>
<video autoplay onencrypted
='handleInitData(event)'></video>
Initialization is much simpler if encrypted events do not need to be handled during MediaKeys initialization. This can be accomplished either by providing the Initialization Data in other ways or setting the source after the MediaKeys 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.
function createSupportedKeySystem() { ... }
function makeNewRequest(mediaKeys, initDataType, initData) { ... }
function licenseRequestReady(event) { ... }
function handleInitData(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>
<video id="v" autoplay onencrypted
='handleInitData(event)'></video>
This is a more complete example showing all events being used.
Note
that
handleMessage()
could
be
called
multiple
times,
including
in
response
to
the
update()
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.
function createSupportedKeySystem() { ... }
function handleInitData(event) { ... }
// This replaces the implementation in the previous example.
function makeNewRequest(mediaKeys, initDataType, initData) {
var keySession = mediaKeys.createSession
();
keySession.addEventListener('message
', handleMessage, false);
keySession.addEventListener('keystatuseschange
', handlekeyStatusesChange, false);
keySession.closed
.then(
console.log.bind(console, 'Session closed')
);
keySession.generateRequest
(initDataType, initData).catch(
console.error.bind(console, 'Unable to create or initialize key session')
);
}
function handleMessageResponse(keySession, response) {
var license = new Uint8Array(response);
keySession.update
(license).catch(
function(err) {
console.error('update() failed: ' + err);
}
);
}
function sendMessage(type, message, keySession) {
var url = licenseUrl;
if (type == "license-renewal"
)
url = renewalUrl;
xmlhttp = new XMLHttpRequest();
xmlhttp.keySession = keySession;
xmlhttp.open('POST', url);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4)
handleMessageResponse(xmlhttp.keySession, xmlhttp.response);
}
xmlhttp.send(message);
}
function handleMessage(event) {
sendMessage(event.messageType
, event.message
, event.target);
}
function handlekeyStatusesChange(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>
<video id="v" autoplay onencrypted
='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.
function createSupportedKeySystem() { ... }
function sendMessage(message, keySession) { ... }
function handleMessage(event) { ... }
// Called if the application does not have a stored sessionId for the media resource.
function makeNewRequest(mediaKeys, initDataType, initData) {
var keySession = mediaKeys.createSession
("persistent-license"
);
keySession.addEventListener('message
', handleMessage, false);
keySession.closed
.then(
function() {
console.log('Session ' + this.sessionId
+ ' closed');
}.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.
function loadStoredSession(mediaKeys, sessionId) {
var keySession = mediaKeys.createSession
("persistent-license"
);
keySession.addEventListener('message
', handleMessage, false);
keySession.closed
.then(
console.log.bind(console, 'Session closed')
);
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.
function closeSession(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.
function removeStoredSession(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.
function handleMessageResponse(keySession, response) {
var license = new Uint8Array(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>
<video id='v' src='foo.webm' autoplay></video>