This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 24081 - The READY state is too limiting and should be more like the PENDING state
Summary: The READY state is too limiting and should be more like the PENDING state
Status: RESOLVED FIXED
Alias: None
Product: HTML WG
Classification: Unclassified
Component: Encrypted Media Extensions (show other bugs)
Version: unspecified
Hardware: PC All
: P2 normal
Target Milestone: ---
Assignee: David Dorwin
QA Contact: HTML WG Bugzilla archive list
URL:
Whiteboard:
Keywords:
Depends on: 25199
Blocks:
  Show dependency treegraph
 
Reported: 2013-12-12 23:11 UTC by Adrian Bateman [MSFT]
Modified: 2014-04-15 21:21 UTC (History)
4 users (show)

See Also:


Attachments

Description Adrian Bateman [MSFT] 2013-12-12 23:11:52 UTC
Based on the discussion in Bug 21854, we need to consider whether there are any conditions where we need to support an application calling update() even when the session isn't in the PENDING state. This bug is to track this specific issue so that we don't use Bug 21854 to track any life cycle issue.
Comment 1 Adrian Bateman [MSFT] 2013-12-12 23:19:54 UTC
As I discussed in Bug 21854, I don't think we should allow this unless we have a specific need to do so. It is easier to allow this later if implementation experience shows that we need it than to allow it now and choose to remove this later.

I am resolving this LATER to see if we get this from implementation.
Comment 2 David Dorwin 2014-01-10 23:26:14 UTC
Note: The original bug report was "There may be use cases for calling update() in states other than PENDING". I've changed the summary to cover the general problem. Also, I don't currently have a use case for calling update() in ERROR or CLOSED.


There are other (more likely) cases where the requirement that (paraphrasing) "a message event must put the MediaKeySession in the PENDING state and update() may only be called in pending" is problematic.

Consider the renewal request case where the following occurs during playback:
 1. The CDM fires a message event to request renewal.
 2. As a result, the state must go to PENDING - even though the session is still valid/"READY" and continues to be usable.
 3. The application replies with a renewal: update() causes the state to return to READY.

Should a valid/usable session remain in PENDING just because it sent a message or might expect a message? Technically, it probably doesn't matter since PENDING is just a superset of READY (see below), but it could be confusing/unexpected. Also, while we might expect to return receive a response within a few seconds and return to the READY state, this may not happen when offline (something the CDM cannot detect).


Stepping back, do we even need the READY state or it be merged it into PENDING?
Currently, the only differences are:
 * update() cannot be called in READY - I think this is a bug (see the discussion starting at https://www.w3.org/Bugs/Public/show_bug.cgi?id=21854#c23).
 * READY cannot transition to ERROR - I think this is a bug (see https://www.w3.org/Bugs/Public/show_bug.cgi?id=21798#c11).
 * The ready event is fired when transitioning to READY
 * As a result of the separation, the ready and message events cannot be fired as part of the same algorithm. (See the loadSession() discussion below.)


In the state transition diagram, if we make both READY arrows go to PENDING, we can remove the READY state. We'd probably want to rename PENDING, but that's a minor issue.

Alternatively, we can leave the two states distinct but add:
 * A MESSAGE arrow that loops back to the READY state
 * An arrow for ERROR
 * Appropriate modifications to the algorithms such that the states are essentially the same.

The distinct states may be easier to reason about and name (and leave flexibility for future changes), but it adds duplicate checks as well as logic in the update() algorithm to describe which state to enter. The distinct states do make it easy to reason about when to fire a ready event if we want to limit it to the PENDING->READY transition.


The steps above could also happen when loading a session:
 0a. loadSession()
 0b. Session is found and a ready event is fired, transitioning to the READY state.
 1-3. Same as above.

However, looking at the loadSession() algorithm, this flow may not be appropriate and the separation of PENDING and READY is problematic. In the loadSession() scenario above, the existing loadSession() algorithm would have implementations fire the keymessage and transition to PENDING then wait for an update() call before firing the ready event. This behavior is undesirable for applications. For loadsession(), at least, I think we need to allow firing both a ready and message event. Otherwise, CDMs must suppress a true response to "If a message exchange (e.g. a license request) is required" OR applications will have to wait for a successful license exchange before getting a ready event, which is undesirable from a user experience perspective.
Comment 3 Mark Watson 2014-01-11 02:07:45 UTC
Are you essentially saying that there are two orthogonal aspects to the session state ?
(1) message state: whether it has sent a message and is waiting for a response
(2) ready state: whether the session has the keys it needs for playback

We can be ready for playback without going through a message exchange (loadSession).

We can be ready for playback during a message exchange (renewal).

If both (1) and (2) are useful, we should have "PENDING-READY' and 'PENDING-NOT-READY', but perhaps (1) is not very useful. We would still need a 'NOT READY' state, but perhaps that is a renamed 'CREATED' state ?
Comment 4 David Dorwin 2014-01-17 23:52:12 UTC
tl;dr: Skip to PROPOSAL below.

(In reply to Mark Watson from comment #3)
> Are you essentially saying that there are two orthogonal aspects to the
> session state ?
> (1) message state: whether it has sent a message and is waiting for a
> response
> (2) ready state: whether the session has the keys it needs for playback
I think I'm saying that the messaging is mostly orthogonal to the active states (PENDING and READY)[1]. The ready event may be similarly orthogonal. (I think it's fine to disallow messages, update() calls, and ready events in the ERROR, CLOSED, or CREATED states.) I'm also questioning the value of the READY state and - to a lesser extent - the ready event.

> We can be ready for playback without going through a message exchange
> (loadSession).
In this case, the ready event means "loaded/created, no message".

> We can be ready for playback during a message exchange (renewal).
Yes. In this case, the ready event simply served to indicate "initialized, no message for now" and the renewal request indicates there is a message.


Currently the READY state/event simply indicates there are no more messages to pass: "The CDM currently has all the information it needs to use keys/licenses from this session." In practice, this likely means the license request has been satisfied with all necessary keys, but we don't know for sure. *Neither the READY state or anything else actually indicates that the session or CDM has the key needed for playback* - there is no such check in the algorithms and some formats allow new key IDs to appear in the stream without new Initialization Data.


We need to decide what we want the 'ready' event to indicate and consider how app developers might use it. If those two things are not consistent, we might run into trouble. This seems likely given the confusion about the event's meaning just within this group. Once we determine the meaning and use cases, we can determine when we need to fire an event then figure out what the state machine and algorithms should be.

Below are some potential uses for the current event:
1) Indicate that the session has been initialized (created/loaded) when no 'message' event is needed.
  * This seems like the primary need.
2) There was also a use case for (optionally) firing the event if another session already exists (PENDING or READY) for the initData. [2][3]
3) There may be a UI-related use case where the application can indicate whether it is waiting for a key.
  * However, what should the application do during the renewal request?
  * Maybe this use case is best handled by bug 18515.
  * Also, there is no guarantee that the keys are actually present.
4) It could also be used as an ACK for the last update() call, informing the application there are no more messages (for now).
  * I'm not sure what an application would do with this information (other than the case above).
  * Aa message _could_ be fired for other reasons, meaning a message does not definitively acknowledge an update() call.
  * It could be argued that acknowledging an update() call has no effect on whether the session is "ready".
5) Wait for the 'ready' event before appending data or calling play().
  * There should be no need to do this since playback should start/resume automatically when the key(s) are available.
  * Also, there is no guarantee that the keys are actually present.

In the discussion of the loadSession() scenario at the end of comment #2, the 'ready' event must fired to avoid problems with applications that might fit into #1, #3, and/or #5. I'd prefer a simpler, less-ambiguous model.


*** PROPOSAL ***
Since createSession() and loadSession() are asynchronous (and must wait for the CDM to be initialized), it seems useful to always have an indication that those functions have completed and are initialized/opened. For discussion purposes, I propose we fire an 'open' event to transition to the OPEN state. The 'open' event would be fired unless there is a failure to create/load the session, in which case the 'error' event is fired. The 'open' event also serves as an indication that update() may be called.

The OPEN state would replace the current PENDING and READY states. The 'open' event would be fired before any 'message' event and in place of the 'ready' event in the transition from CREATED to READY. A unified event/state transition from CREATED would allow applications to handle a single event if they need to know that createSession()/loadSession() was successful, the sessionId attribute is valid, or update() may be called, regardless of whether there are any messages and without the ambiguity of other 'ready' events/READY state transitions.

The 'message' event and update() calls have no effect on the OPEN state or whether the session is "ready" in any way.

The 'close' and 'error' events and their respective states remain unchanged.

The effective differences from the current PENING/READY/'ready' design are:
 * No indication that no messages will be passed for this session (#2).
   - This was never definitive anyway, especially in the loadSession() case.
 * No way to know when a series of messages is complete (#4).
   - Is this important?
 * No way to infer that all keys are now available.
   - This was a misuse of the 'ready' event, so this is an improvement.

Revisiting the use cases above:
 #1 is addressed by the 'open' event. The same event is fired regardless of whether a 'message' event will be fired.
 #2 could also be addressed by an 'open' event where no 'message' event is fired. I don't think the app needs to know that no message is necessary for the session.
 #3 is addressed by bug 18515.
 #4 is not supported.
 #5 was invalid.


[1] Per the discussion starting at https://www.w3.org/Bugs/Public/show_bug.cgi?id=21854#c23, it seems unclear that we need to track the message state.
[2] https://www.w3.org/Bugs/Public/show_bug.cgi?id=21855#c7
[3] https://dvcs.w3.org/hg/html-media/rev/cba144274140
Comment 5 Adrian Bateman [MSFT] 2014-01-28 15:55:18 UTC
We've discussed this at Microsoft and we can live with David's proposal. We think there are use cases for the ready event but we understand David's concerns and believe it is acceptable to update the spec as David suggests and to gain additional implementation experience to see if this becomes a problem later. We can consider adding a new event/state in future if it becomes necessary.
Comment 6 Mark Watson 2014-01-28 16:19:42 UTC
David's proposal looks good to me.
Comment 7 Adrian Bateman [MSFT] 2014-02-21 22:29:07 UTC
Assigning to David per the telcon.
http://www.w3.org/2014/02/18-html-media-minutes.html#item18
Comment 8 David Dorwin 2014-04-15 21:21:36 UTC
The issues in this bug are resolved by the implementation of promises (bug 25199) and removal of states.

(In reply to David Dorwin from comment #4)
> *** PROPOSAL ***
> Since createSession() and loadSession() are asynchronous (and must wait for
> the CDM to be initialized), it seems useful to always have an indication
> that those functions have completed and are initialized/opened. For
> discussion purposes, I propose we fire an 'open' event to transition to the
> OPEN state. The 'open' event would be fired unless there is a failure to
> create/load the session, in which case the 'error' event is fired. The
> 'open' event also serves as an indication that update() may be called.

createSession() and loadSession() now return a promise that is resolved when the algorithms complete (equivalent of the 'open' event above) and rejected when an error occurs ('error' event above). The resolve function receives the session object, which allows update() to be called.