[EME] Exposing key status to applications

tl;dr: We are seeking feedback from application authors on the best way to
provide them with information about key availability (based on license
policies).

*Background*
With the introduction of promises to EME, most errors are reported by
rejecting the promises returned by the methods. The remaining "errors" are
related to key validity issues, such as expiration and output protection.
Bug 26372 <https://www.w3.org/Bugs/Public/show_bug.cgi?id=26372> was filed
to identify a solution. The current proposals involve providing
status/reason information via an extension to the "keyschange"
event/getUsableKeyIds() mechanism currently defined in the spec.

*Questions for **Application Authors*

   1. Would you prefer to have just a list of valid/usable keys or to have
   a list of all known keys with an indication of whether they are valid (and
   the reason for those that are not)?
   2. How important is it to have access to the status per-key [ID] vs.
   just the reason for a change in the available keys?
   3. How would you prefer to receive/obtain key status information?
      1. Simple event and calling a method
      2. Per-status change event containing all affected keys with the same
      status
      3. Per-key per-status change event
      4. Via change records (similar to Object.observe(); see Option 5
      below)
   4. Would you prefer key IDs to be provided as binary ArrayBuffers (i.e.
   Uint8Array) or a base64url-encoded string?
   - Context: Although it feels natural to represent the binary ID in an
      ArrayBuffer, it's unclear whether this is the best solution for
      applications. If the application wants to track events, it might
be simpler
      to just compare and/or index by a base64url-encoded representation of the
      key ID. It may even use this format to communicate to the
server. Returning
      a DOMString or string representation in a JSON Object may make more sense
      for applications and avoid unnecessary conversions. Since the purpose of
      this event/method is to allow the application to understand and
manage the
      returned data, I think it's important that the data is easy for the
      application to use. Of course, the application can always convert an
      ArrayBuffer to whatever type it needs.


Note: In a key rotation scenario, keys from the past that are removed would
also be removed from any list of key IDs to avoid an indefinitely growing
list.

*Example Options*
The following are a sampling of options that have been proposed in no
particular order.

See comments 17 <https://www.w3.org/Bugs/Public/show_bug.cgi?id=26372#c17>
 and 22 <https://www.w3.org/Bugs/Public/show_bug.cgi?id=26372#c22> for some
of the analysis so far.

In all cases, there is an enum that looks something like this:
enum MediaKeyStatus { "valid", "expired", "outputprohibited", ... };

*Option 1: "keyschange" event contains a reason for the change*
IDL:
*interface MediaKeysChangeEvent : Event {*
*  readonly attribute MediaKeyStatus reason;*

*};*

function handleKeysChange(event) {
  *// Process event.reason.*
  event.target.getUsableKeyIds().then(
    function(keyIdSequence) {
      // Process keyIdSequence and respond appropriately.
    }
  );
}

*Option 2: *getKeyStatuses() provides a status for each key
IDL:
Promise<sequence<TBD>> getKeyStatuses();

function handleKeysChange(event) {
  event.target.getKeyStatuses().then(
    function(keyIdStatusList) {
      for (var i = 0; i < keyIdStatusList.length; i++) {
*        if (keyIdStatusList[i].id == ... && keyIdStatusList[i].status !=
"valid")*
        {
          // Do something.
        }
      }
    }
  );
}

*Option 3: **"keyschange" event contains a reason for the change and a list
of all keyIds **affected by this specific change** (getUsableKeyIds() is
removed)*
IDL:

*interface MediaKeysChangeEvent : Event {*
*  readonly attribute MediaKeyStatus status;*
*  readonly attribute sequence<ArrayBuffer> keyIds;*
*};*

function handleKeysChange(event) {
  for (var i = 0; i < event.keyIds.length; i++) {
*    if (event.keyIds[i] == ... && event.status != "valid")*
    {
      // Do something.
    }
  }
}

*Option 4: **"keychange" event is fired for each key whose status changes
and contains the key ID and status *
IDL:
interface MediaKeyChangeEvent : Event {
*  readonly attribute ArrayBuffer id;*
  readonly attribute MediaKeyStatus status;
};

function handleKeyChange(event) {
*  if (event.id <http://event.id> == ... && event.status != "valid")*
  {
    // Do something.
  }
}

*Option 5: Object.observe()-like records*
The exact IDL and mechanism are TBD, but the goal would be to have records
that look something like the following:

{ object: keyList, type: 'add', name: '0123456789abcdef', value: 'valid' },
{ object: keyList, type: 'update', name: '0123456789abcdef', value:
'expired', oldValue: 'valid' },
{ object: keyList, type: 'add', name: 'abcdef0101010101', value:
'outputnotallowed' },
{ object: keyList, type: 'delete', name: '0123456789abcdef', oldValue:
'expired' },
{ object: keyList, type: 'update', name: 'abcdef0101010101', value:
'valid', oldValue: 'outputnotallowed' },

Received on Thursday, 25 September 2014 21:32:19 UTC