- From: Glenn Adams <glenn@skynav.com>
- Date: Fri, 3 Oct 2014 16:55:04 -0600
- To: David Dorwin <ddorwin@google.com>
- Cc: "public-html-media@w3.org" <public-html-media@w3.org>, Anne van Kesteren <annevk@annevk.nl>, Boris Zbarsky <bzbarsky@mit.edu>
- Message-ID: <CACQ=j+eSbOkYba9ROd7zsZWjJYEr+e-zgVbm8gTFuSn_mTwDng@mail.gmail.com>
it is possible that textTrack type and capability will be required as well
On Fri, Oct 3, 2014 at 4:18 PM, David Dorwin <ddorwin@google.com> wrote:
> The following is an extension of my previous proposal that addresses
> scenarios that were previously unaddressed. It uses the second Possible
> Solution I listed: Allowing the application to specify conditions to
> requestMediaKeySystem().
>
> This solution gives applications a lot of control if they want it
> (including potentially 10s of configuration combinations) while also
> supporting simple cases. Most applications will specify a list of
> configurations for each key system. This is similar to how
> isTypeSupported() may have been used except that all combinations for a
> given key system can be checked at once. Other applications might make
> multiple calls for various key systems. For example, key system A
> configuration 1 might be preferred over key system B configuration 1, which
> might be preferred over key system A configuration 2.
>
> *Spec Text*
> The following IDL and text are added:
>
> enum MediaKeysRequirement { "required", "optional", "disallowed" }
>> dictionary MediaKeySystemOptions {
>> DOMString initDataType = "" ;
>> DOMString audioType = "";
>> DOMString audioCapability = "";
>> DOMString videoType = "";
>> DOMString videoCapability = "";
>> MediaKeysRequirement uniqueidentifier = "optional";
>> MediaKeysRequirement stateful = "optional";
>> };
>>
>> Non-standard additions to the this dictionary are strongly discouraged.
>> Any non-standard dictionary member MUST be of type MediaKeysRequirement.
>> This dictionary MUST NOT be used to pass state or data to the CDM.
>>
>> Note: Should dictionary members be added, it is recommended that they
>> have default values of “optional” to support the widest range of
>> application and client combinations.
>>
>>
> uniqueidentifier and stateful allow the application to check whether
> certain features are possible. This also allows the user agent to fail
> early if, for example, it is in a private browsing mode or does not support
> CDM storage.
>
>
> requestMediaKeySystem() is updated to optionally take a list of option
> dictionaries
>
> partial interface Navigator {
>> Promise<MediaKeySystemAccess> requestMediaKeySystem(DOMString
>> keySystem*, optional Sequence<MediaKeySystemOptions>
>> supportedConfigurations*);
>> };
>
>
> |supportedConfigurations| is a list of option combinations to be tried in
> order. The algorithm would look something like this:
>
> 1. If the |keySystem| is unsupported, reject the promise.
> 2. For each element of |supportedConfigurations|:
> 1. Let options be the element.
> 2. For each dictionary member:
> 1. If the member's name is unrecognized or unhandled and the
> value is not “optional”, continue to next iteration of the loop.
> 2. If the member’s value cannot be satisfied together in
> combination with the previous members, continue to next iteration of the
> loop.
> 3. If the origin is not allowed (i.e. by a user prompt) to use the
> |keySystem| in the configuration specified by the combination of the values
> in options, continue to next iteration of the loop.
> 4. Resolve the promise with a new MediaKeySystemAccess object.
> (Initialization is TBD - see Areas for Discussion.)
> 3. Reject the promise. // There were no supported combinations in
> |supportedConfigurations|.
>
>
> *Notes*
>
> - Implementations would only prompt if all the options in the
> dictionary can be satisfied together, avoiding unnecessarily prompting the
> user. Implementations may additionally optimize to prompt the user in such
> a way that a single prompt can be used to answer any combination.
> - Audio and video capabilities are separated to address previously
> discussed issues, such as in the "Different audio and video requirements"
> section of https://www.w3.org/Bugs/Public/show_bug.cgi?id=24873#c0.
> - |supportedConfigurations| is a Sequence instead of an Array because "The
> element type of an array must not be a sequence or dictionary type.
> <http://heycam.github.io/webidl/#idl-array>"
> - It's unclear why this is the case or why the same rule does not
> apply to Sequence. Maybe Boris knows.
> - It is TBD whether rejecting the promise is the correct behavior or
> whether the promise should instead be resolved with null. See the
> thread beginning at
> http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Oct/0011.html
> .
> - This proposal addresses most issues I listed in the Concerns section
> of my original email.
> - New Issue #1 is explicitly addressed.
> - Unaddressed Issue #1 could be better addressed because the user
> agent has all possible configurations at once (unless of course the same
> key system is checked twice, which is most likely to avoid prompts anyway).
> - Unaddressed Issue #2 is addressed - the application can make
> multiple requests for different options in any order.
> - Only New Issue #2 (serialization) remains. I think that is an
> artifact of the possibility of prompts. The only way I see to avoid this
> would be to allow an ordered list of key systems with option arrays. This
> seems overly complex and unnecessary, though.
>
>
> *Areas for Discussion*
>
> - The inclusion of (a single) initDataType in the dictionary means
> each combination may need to be duplicated (i.e. for "keyids" and "cenc").
> - We could make this an array, but that would be inconsistent with
> the audio/video types (i.e. all codecs must be supported).
> - Checking multiple types requires multiple configuration entries.
> - To address the two previous items, perhaps we should replace the
> type-capability pairs with an array of pairs, allowing any matching pair to
> represent a positive result. That might require defining another Dictionary
> or other type.
> - Depending on the outcome of the above items, we may need to add
> methods like isTypeSupported() and isRequirementSupported() to the
> MediaKeySystemAccess object.
>
>
> *Example Usage*
> The following assumes that non-satisfied configurations result in a
> rejected promise rather than a null value. (See the note above.) The code
> would be slightly different in the latter case.
>
> someSystemOptions = [
> {...},
> ...
> ];
> clearKeyOptions = [
> {...},
> ...
> ];
> navigator.requestMediaKeySystem("com.example.somesystem",
> someSystemOptions).then(
> function(keySystemAccess) {
> // Get the selected configuration in some TBD way.
> // Use it to select the source.
> return keySystemAccess.createMediaKeys();
> }
> ).catch(
> function(error) {
> // Try the next key system.
> navigator.requestMediaKeySystem("org.w3.clearkey",
> clearKeyOptions).then(
> ...
> }
> ...
> ).catch(
> // No supported key systems .
> ...
> );
>
> *Example Option Lists*
> The following list supports two different media formats, each in two
> different configuration (i.e. for different resolutions). Alternatively,
> the application could just check for the stream formats and adapt to what
> is available after the MediaKeySystemAccess object is returned.
>
> streamingOptions = [
> { audioType: "audio/webm; codecs=’opus’",
> videoType: "video/webm; codecs=’vp9’",
> videoCapability: "foo",
> uniqueidentifier: "required",
> },
> { audioType: "audio/mp4; codecs=’mp4a.XXXXXX’",
> videoType: "video/mp4; codecs=’avc1.XXXXXX’",
> videoCapability: "foo",
> uniqueidentifier: "required",
> },
> { audioType: "audio/webm; codecs=’vorbis’",
> videoType: "video/webm; codecs=’vp9’",
> videoCapability: "bar",
> },
> { audioType: "audio/mp4; codecs=’mp4a.XXXXXX’",
> videoType: "video/mp4; codecs=’avc1.XXXXXX’",
> videoCapability: "bar",
> }];
>
>
> In this scenario, an offline license requires a unique identifier and
> statefulness (to store the license).
> offlineOptions = [
> { audioType: "audio/webm; codecs=’opus’",
> videoType: "video/webm; codecs=’vp9’",
> videoCapability: "foo",
> uniqueidentifier: "required",
> stateful: "required"
> },
> ...
> ];
>
>
> Key release requires statefulness to store the key release receipt.
> keyReleaseOptions = [
> { audioType: "audio/mp4; codecs=’mp4a.XXXXXX’",
> videoType: "video/mp4; codecs=’avc1.XXXXXX’",
> stateful: "required"
> },
> ...
> ];
>
> On Wed, Sep 24, 2014 at 5:37 PM, David Dorwin <ddorwin@google.com> wrote:
>
>> In bug 25923 <https://www.w3.org/Bugs/Public/show_bug.cgi?id=25923>, we
>> have been discussing the proper way to report key system support when the
>> answer might depend on permissions, whether the user authorizes CDM
>> download, etc. I'd like to have a broader discussion on solving these
>> issues and get feedback from authors. I have included a concrete proposal
>> that I think is better than the current state, but it does have some
>> theoretical deficiencies.
>>
>> *Background*
>> EME currently has a synchronous isTypeSupported()
>> <https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-istypesupported>
>> method to determine whether key system, media type, and capability
>> combinations are supported by the user agent. Its design is similar to
>> canPlayType(). As with canPlayType(), it is expected that applications may
>> make many calls to check various combinations before picking one. The
>> current assumption is that any permission prompts would be presented during
>> the asynchronous MediaKeys.create().
>>
>> There are some scenarios that are not handled well in this model. For
>> example, how should isTypeSupported() respond if the user has not yet been
>> prompted (and thus allowed) the CDM to be used. There are other variants
>> where the CDM needs to be downloaded, which could add additional delay.
>>
>> *Proposal*
>> I propose a model inspired by Web MIDI's MIDIAccess object. Permissions,
>> installation delays, etc. would be handled as part of the creation of a new
>> object, MediaKeySystemAccess. In most cases, this object is returned
>> quickly, though asynchronously. Once the application has the object, it can
>> use it to check details (i.e. supported codecs) and instantiate the CDM
>> (creating a MediaKeys object). Since the MediaKeySystemAccess object should
>> be returned almost immediately in subsequent calls, applications should
>> still be able to use the codec checks to select streams to download just as
>> quickly (effectively) as with the current synchronous model.
>>
>> *IDL*
>> Add a new method to request access to a key system. All download and
>> permission prompts are handled here before resolving the promise. If the
>> |keySystem| is not supported (or is declined), the promise is rejected.
>> Otherwise, it is resolved with a new MediaKeySystemAccess object.
>>
>> partial interface Navigator { Promise<MediaKeySystemAccess> requestMediaKeySystem(DOMString keySystem);
>> };
>>
>>
>> MediaKeySystemAccess contains non-static methods that were once static
>> methods in MediaKeys:
>>
>> - isTypeSupported remains synchronous, but becomes a member and only
>> checks the codecs and capabilities.
>> - isInitDataTypeSupported() is added to handle exactly one attribute
>> of the CDM. (There is no reason to check combinations of Initialization
>> Data Types and containers/codecs.)
>> - createMediaKeys() is still asynchronous to allow the CDM to be
>> loaded asynchronously.
>>
>> enum IsTypeSupportedResult { "" /* empty string */, "maybe", "probably" };
>> interface MediaKeySystemAccess {
>> boolean isInitDataTypeSupported(DOMString initDataType);
>> IsTypeSupportedResult isTypeSupported(DOMString contentType, optional DOMString capability);
>> Promise<MediaKeys> createMediaKeys();
>> };
>>
>>
>> MediaKeys continues to exist, but is mainly used to create
>> sessions. MediaKeySession is unchanged.
>>
>> interface MediaKeys {
>> MediaKeySession createSession(optional SessionType sessionType = "temporary");
>> Promise<void> setServerCertificate((ArrayBuffer or ArrayBufferView) serverCertificate);
>> };
>>
>>
>> *Example Usage*
>>
>>> navigator.requestMediaKeySystem("com.example.somesystem").then(
>>> function(keySystemAccess) {
>>> if (keySystemAccess.isInitDataTypeSupported("keyids") &&
>>> (keySystemAccess.isTypeSupported("video/foo; codecs='bar,baz'")
>>> ||
>>> keySystemAccess.isTypeSupported("video/foo;
>>> codecs='bar2,baz'"))) {
>>> return keySystemAccess.createMediaKeys();
>>> }
>>> // Throw to fall into the catch.
>>> ...
>>> }
>>> ).catch(
>>> function(error) {
>>> // Try the next key system.
>>> navigator.requestMediaKeySystem("org.w3.clearkey").then(
>>
>> ...
>>
>> }
>>
>> ...
>>
>> ).catch(
>>
>> // No supported key systems .
>>
>> ...
>>
>> );
>>
>>
>> *Concerns*
>> Although this proposal solves the scenarios mentioned in the Background
>> and that motivated bug 25923, it introduces some new ones related to
>> multiple key system support and does not address others.
>>
>> *New Issues*
>> These new issues do not exist with the current synchronous
>> isTypeSupported() model. See also the discussion beginning with comment
>> 35 <https://www.w3.org/Bugs/Public/show_bug.cgi?id=25923#c35>.
>>
>> 1. An application looking for specific type support (i.e. codecs or
>> Initialization Data Type) may need to create multiple objects - and thus
>> generate multiple user prompts - to find a key system that supports those
>> type(s).
>> 2. Applications must serialize the *asynchronous* checks for multiple
>> key systems to avoid the possibility of multiple prompts, similar to the
>> above issue. (Note how the requestMediaKeySystem() calls are serialized in
>> the example.)
>>
>>
>> *Unaddressed Issues*
>> These issues exist in the current model *and* various proposed models.
>>
>> 1. CDM download/install and permission to use must be presented to
>> the user in the same UI. For example, it is not possible to download and
>> install the CDM without also approving exposure of a unique ID (without
>> some far-too-complex UI).
>> 2. There is no way for an application to prefer, for example, the key
>> system that will generate the least alarming UI (or none at all). Since
>> different CDMs (or even configurations) may have very different security
>> and privacy properties, the related UI/UX could be different.
>>
>>
>> *Possible Solutions*
>> One or more of the above issues could potentially be addressed by the
>> following:
>>
>> - Maintaining some level of synchronous checks for the best-case
>> support (i.e. respond as if the CDM is installed and allowed).
>> - Applications would still need to use the MediaKeySystemAccess
>> methods for definitive responses.
>> - Allowing the application to specify conditions
>> to requestMediaKeySystem().
>> - For example, types that must be supported or to fail if a prompt
>> is required,
>> - If the condition cannot be met, the promise would be rejected.
>> - Allowing the application to query/request multiple key systems at
>> once.
>>
>>
>
> On Wed, Sep 24, 2014 at 5:37 PM, David Dorwin <ddorwin@google.com> wrote:
>
>> In bug 25923 <https://www.w3.org/Bugs/Public/show_bug.cgi?id=25923>, we
>> have been discussing the proper way to report key system support when the
>> answer might depend on permissions, whether the user authorizes CDM
>> download, etc. I'd like to have a broader discussion on solving these
>> issues and get feedback from authors. I have included a concrete proposal
>> that I think is better than the current state, but it does have some
>> theoretical deficiencies.
>>
>> *Background*
>> EME currently has a synchronous isTypeSupported()
>> <https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#dom-istypesupported>
>> method to determine whether key system, media type, and capability
>> combinations are supported by the user agent. Its design is similar to
>> canPlayType(). As with canPlayType(), it is expected that applications may
>> make many calls to check various combinations before picking one. The
>> current assumption is that any permission prompts would be presented during
>> the asynchronous MediaKeys.create().
>>
>> There are some scenarios that are not handled well in this model. For
>> example, how should isTypeSupported() respond if the user has not yet been
>> prompted (and thus allowed) the CDM to be used. There are other variants
>> where the CDM needs to be downloaded, which could add additional delay.
>>
>> *Proposal*
>> I propose a model inspired by Web MIDI's MIDIAccess object. Permissions,
>> installation delays, etc. would be handled as part of the creation of a new
>> object, MediaKeySystemAccess. In most cases, this object is returned
>> quickly, though asynchronously. Once the application has the object, it can
>> use it to check details (i.e. supported codecs) and instantiate the CDM
>> (creating a MediaKeys object). Since the MediaKeySystemAccess object should
>> be returned almost immediately in subsequent calls, applications should
>> still be able to use the codec checks to select streams to download just as
>> quickly (effectively) as with the current synchronous model.
>>
>> *IDL*
>> Add a new method to request access to a key system. All download and
>> permission prompts are handled here before resolving the promise. If the
>> |keySystem| is not supported (or is declined), the promise is rejected.
>> Otherwise, it is resolved with a new MediaKeySystemAccess object.
>>
>> partial interface Navigator { Promise<MediaKeySystemAccess> requestMediaKeySystem(DOMString keySystem);
>> };
>>
>>
>> MediaKeySystemAccess contains non-static methods that were once static
>> methods in MediaKeys:
>>
>> - isTypeSupported remains synchronous, but becomes a member and only
>> checks the codecs and capabilities.
>> - isInitDataTypeSupported() is added to handle exactly one attribute
>> of the CDM. (There is no reason to check combinations of Initialization
>> Data Types and containers/codecs.)
>> - createMediaKeys() is still asynchronous to allow the CDM to be
>> loaded asynchronously.
>>
>> enum IsTypeSupportedResult { "" /* empty string */, "maybe", "probably" };
>> interface MediaKeySystemAccess {
>> boolean isInitDataTypeSupported(DOMString initDataType);
>> IsTypeSupportedResult isTypeSupported(DOMString contentType, optional DOMString capability);
>> Promise<MediaKeys> createMediaKeys();
>> };
>>
>>
>> MediaKeys continues to exist, but is mainly used to create
>> sessions. MediaKeySession is unchanged.
>>
>> interface MediaKeys {
>> MediaKeySession createSession(optional SessionType sessionType = "temporary");
>> Promise<void> setServerCertificate((ArrayBuffer or ArrayBufferView) serverCertificate);
>> };
>>
>>
>> *Example Usage*
>>
>>> navigator.requestMediaKeySystem("com.example.somesystem").then(
>>> function(keySystemAccess) {
>>> if (keySystemAccess.isInitDataTypeSupported("keyids") &&
>>> (keySystemAccess.isTypeSupported("video/foo; codecs='bar,baz'")
>>> ||
>>> keySystemAccess.isTypeSupported("video/foo;
>>> codecs='bar2,baz'"))) {
>>> return keySystemAccess.createMediaKeys();
>>> }
>>> // Throw to fall into the catch.
>>> ...
>>> }
>>> ).catch(
>>> function(error) {
>>> // Try the next key system.
>>> navigator.requestMediaKeySystem("org.w3.clearkey").then(
>>
>> ...
>>
>> }
>>
>> ...
>>
>> ).catch(
>>
>> // No supported key systems .
>>
>> ...
>>
>> );
>>
>>
>> *Concerns*
>> Although this proposal solves the scenarios mentioned in the Background
>> and that motivated bug 25923, it introduces some new ones related to
>> multiple key system support and does not address others.
>>
>> *New Issues*
>> These new issues do not exist with the current synchronous
>> isTypeSupported() model. See also the discussion beginning with comment
>> 35 <https://www.w3.org/Bugs/Public/show_bug.cgi?id=25923#c35>.
>>
>> 1. An application looking for specific type support (i.e. codecs or
>> Initialization Data Type) may need to create multiple objects - and thus
>> generate multiple user prompts - to find a key system that supports those
>> type(s).
>> 2. Applications must serialize the *asynchronous* checks for multiple
>> key systems to avoid the possibility of multiple prompts, similar to the
>> above issue. (Note how the requestMediaKeySystem() calls are serialized in
>> the example.)
>>
>>
>> *Unaddressed Issues*
>> These issues exist in the current model *and* various proposed models.
>>
>> 1. CDM download/install and permission to use must be presented to
>> the user in the same UI. For example, it is not possible to download and
>> install the CDM without also approving exposure of a unique ID (without
>> some far-too-complex UI).
>> 2. There is no way for an application to prefer, for example, the key
>> system that will generate the least alarming UI (or none at all). Since
>> different CDMs (or even configurations) may have very different security
>> and privacy properties, the related UI/UX could be different.
>>
>>
>> *Possible Solutions*
>> One or more of the above issues could potentially be addressed by the
>> following:
>>
>> - Maintaining some level of synchronous checks for the best-case
>> support (i.e. respond as if the CDM is installed and allowed).
>> - Applications would still need to use the MediaKeySystemAccess
>> methods for definitive responses.
>> - Allowing the application to specify conditions
>> to requestMediaKeySystem().
>> - For example, types that must be supported or to fail if a prompt
>> is required,
>> - If the condition cannot be met, the promise would be rejected.
>> - Allowing the application to query/request multiple key systems at
>> once.
>>
>>
>
Received on Friday, 3 October 2014 22:55:54 UTC