RE: [EME] Persistent license

Please find my comments tagged with [sm] inline.

From: David Dorwin [mailto:ddorwin@google.com]
Sent: Saturday, April 05, 2014 5:26 AM
To: Joe Steele
Cc: Maruyama, Shinya; Mark Watson; public-html-media@w3.org
Subject: Re: [EME] Persistent license



On Fri, Apr 4, 2014 at 9:25 AM, Joe Steele <steele@adobe.com<mailto:steele@adobe.com>> wrote:
Replies inline —

On Apr 4, 2014, at 1:21 AM, Maruyama, Shinya <Shinya.Maruyama@jp.sony.com<mailto:Shinya.Maruyama@jp.sony.com>> wrote:


I think we need to address the disagreement for the way of loading persisted license.
The following is the downsides of loadSession I have come up with.
Your opinion?

1) No sufficient sessionId generation rule
Currently solo UA is allowed to generate a sessionId. It leads to sessionId collision which causes unspecified behavior; e.g. overriding, error, etc, because persisted sessionId is known to only CDM. Even if we go for loadSession, we need to add an explicit rule to avoid sessionId collision.

The text covering the session ID (https://dvcs.w3.org/hg/html-media/raw-file/tip/encrypted-media/encrypted-media.html#session-id) specifies that it must be unique per browsing context and can be generated by the CDM. So at least for your CDM you can control this. I don’t see an issue here.



2) Performance penalty
Even if we have a fixed rule of #1 above, it requires CDM to look through all the persisted sessionId each time createSession is called

I agree.

I don't understand. How does loadSession() impact createSession() in this way? If anything, using loadSession() to load persisted sessions avoids performance penalties that may occur if createSession() is allowed to load persisted sessions.

[sm] If UA supports loadSession, it is required to ensure sessionId uniqueness across browsing context but this is not clearly specified as of now.
For the details, please see my previous replies to Joe.




3) SessionId is losable reference to persisted license
As an application need to persist a sessionId BEFORE or AFTER the sessionId is persisted in CDM (most probably update() context). In case of AFTER (I think this sequence is typical), it possibly causes sessionId being lost to application due to, for example, failing to store sessionId in localStorage. Then, application can no longer remove the persisted license.

I agree, but I am not sure this is problem the spec can correct for. The application can always fail to store information which later turns out to be needed. I don’t think we can solve for this in a general way.



4) Optional loadSession is dependent on user agent implementation
If loadSession is not supported in a user agent, we can’t support persisted license in the user agent even though CDM supports it.
If we allow createSession (or new mandatory explicit method) to load persisted license, whether to support persisting license is up to CDM implementation.
User agents are ultimately responsible for what is exposed to the web platform and ensuring security<https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#security> and privacy<https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html#privacy>. They are also responsible for vetting the key systems (CDMs) they expose and deciding what features to expose. Whether loadSession() is mandatory or not does not affect this.

Nothing actually says loadSession() is optional. The method must exist. However, a user agent could choose to only execute step 1.

[sm] As mentioned above, currently whether to be able to support loadSession is dependent on sessionId generation algorithm of createSession. Thus, CDM implementers can’t implement loadSession without making sure what sessionId generation algorithm is implemented in a user agent.


I agree. I don’t see the benefit loadSession provides over createSession.

Applications will see a consistent and expected behavior. They will know when data is being loaded and when a new session is being created. This goes hand in hand with being explicit about when data is persisted. If this is not explicit, applications won't know when they need to clear it. There is a real world issue right now with some implementations that is directly related to this issue. Also, separating the methods avoids potential performance issues in the non-persisted case.

[sm] I agree on explicit way for the persistence. I believe both of Joe’s proposal and my proposal are also based on the policy.
As for the performance issues, it is not a problem because our proposals also have separate methods; loadKey()/queryKey for Joe’s, load() for mine.





Shinya

From: Joe Steele [mailto:steele@adobe.com]
Sent: Tuesday, April 01, 2014 5:28 AM
To: Maruyama, Shinya; David Dorwin; Mark Watson
Cc: public-html-media@w3.org<mailto:public-html-media@w3.org>
Subject: Re: [EME] Persistent license

Hi Shinya,

Replies inline —

Joe

On Mar 19, 2014, at 7:30 AM, Maruyama, Shinya <Shinya.Maruyama@jp.sony.com<mailto:Shinya.Maruyama@jp.sony.com>> wrote:

Joe, I agree on those three models.
As for the API, I’ve come up with something I want to share with you.

* store license : createSession() vs. persist()/store()
Adding a parameter (enum?) to createSession enables update() method to store the license. It means we add a new step like “cdm stores license if license permits persisting” before step 3-3-2 of update() method; https://dvcs.w3.org/hg/html-media/raw-file/tip/encrypted-media/encrypted-media.html#dom-update. Because this additional step is run before resuming playback, it may cause performance penalty.
As for new persist()/store() method, it does not pay such a performance penalty. However, if a cdm does not support storing license, the timing of when application receives the error is delayed after license is acquired whereas createSession with additional parameter can return the error before firing message event.

This is a good point. Providing an error up front when the session is created would be useful to avoid later errors.


* load license : createSession vs. loadSession
createSession with an enum(?) parameter enables UA/CDM to implement comprehensive models. I still could not understand the reason why loading license in createSession is problem

This does not make sense to me either. I think we can load existing keys in createSession as needed.

loadSession with using sessionId looks problematic for me; e.g. if sessionId stored in application is lost - for instance, after cdm store the license and before storing it in local storage etc - application can no longer remove the license stored in cdm. It possibly leads to sessionId leak and then eventually runs out of numerical sessionId.
I think it would be better that the license stored in CDM can be removed as long as application has the associated content. createSession(type, initData) makes it possible whenever license is loaded and then released by the content.
Maybe I missed some reason why createSession should not load the license but I do not think current loadSession is good enough as a solo solution for the use of persistent license.

I would prefer we use something like the key ID to load/store/remove licenses. Session is not specific enough.


Probably we need to take into account the case license is stored by application on behalf of CDM (maybe whether to support this should be discussed separately though). Actually UltraViolet support this use case by introducing DMP. Given this case, adding granular methods for each case might be better for license store; e.g. store() for CDM level persisting, unload() for app level.
For loading license, additional method loadLicense(license) might better. This method is called upon createSession(type, initData, mode=USE_APP_LICENSE) which neither loads cached license nor firing message event. USE_APP_LICENSE expects license(s) to be loaded by the laodLicense.

I agree with allowing the application to manages licenses to the extent possible. However — there is currently no mechanism for the CDM to provide a license appropriate for storing by the application. The key server response which contains licenses may contain other things as well. Since there is no way for the application to be aware of this in a  general way, the application will have to have key-system specific code to handle this case.

If we provide a mechanism which allows the application to:
a) query if a license exists by key id and return the license as an opaque blob
b) load a license by key id
c) remove that license by key id

This would allow us to do all the things required for Ultraviolet and would also allow applications requiring authenticated key release to manage their keys directly.


Thanks,
Shinya

From: Joe Steele [mailto:steele@adobe.com]
Sent: Tuesday, March 18, 2014 3:44 AM
To: David Dorwin
Cc: Maruyama, Shinya; Mark Watson; public-html-media@w3.org<mailto:public-html-media@w3.org>
Subject: Re: [EME] Persistent license

Just to give a specific usage model — in our applications today we have three modes for license persistence:

1) Use if available - if a cached license is available, use it. Otherwise try to request one.
2) Force Offline - if a cached license is available, use it. Otherwise FAIL.
3) Force Online - Ignore any cached licenses. Request a fresh license from the server.

We have not run into any use cases this does not cover. I would suggest that is a good model for the enum to follow.

As far as the application loading stored sessions explicitly — I still have a problem with that. Since the application has no visibility into what licenses actually came back in the license server responses, it will have not choice but to load all the stored sessions it has ever seen. This seems quite heavy weight to me. Maybe I am missing something about the notification mechanism?

Joe

On Mar 17, 2014, at 10:27 AM, David Dorwin <ddorwin@google.com<mailto:ddorwin@google.com>> wrote:


tl;dr: Ignore the existing proposal for a “persistent” attribute. I’ll provide an updated proposal this week. Also, createSession() should not be loading persisted licenses.


Joe makes a good point that the license would specify whether the CDM is allowed to such a license.

After thinking about this more, I do not think an attribute or the proposal for it are the right way to handle this. Persistence is really a property of the license request and thus should be passed to createSession(). I’ll update the bug with a new proposal. More details below.


The original intent of such a value was to indicate to the CDM that it should create license request(s) for a persistent license (if there are any applicable differences). This was lost in the “persistent” attribute rough proposal, which incorrectly focused on license storage.

In either case, the state (i.e. license) was to be stored by session ID as the result of the update() call. loadSession() would load the state associated with the session ID.


The proposed “persistent” attribute would have applied to the entire MediaKeys object, but it is really only used in generating license requests when handling createSession() calls. In addition, loadSession() probably isn’t useful without unless persistent=true. Thus, it seems that the intended behavior would be better addressed by an optional parameter to createSession(). This would also allow throwing a NOT_SUPPORTED_ERR if persistent licenses (and requests for them) are not supported.


One remaining question is whether the CDM should implicitly store a license that allows itself to be persisted while handling the update() call. If the server did not grant a persistable license, it is possible that the CDM will not store a license that the application expected to be stored. This would likely be an application problem, but it is still unexpected. Do we need an explicit store()/persist() method on MediaKeySession? This would, of course, only succeed when the license allows.

There might also be a use case where a special license request is needed but the application will store the license (and thus loadSession() is not used). With a single Boolean, there is no way to differentiate the two use cases. This could be solved using an enum instead of a Boolean for the extra parameter. This could also be solved by requiring an explicit persist()/store() call as mentioned above. (Regardless of this use case, I propose that the new createSession() parameter be an enum named licenseType.)


Returning to the original topic of this thread, persisting sessions requires more application logic than the simpler “streaming” use case. Such an application likely wants to know what it has persisted, so storing the related session IDs with that information seems reasonable.

There was no intent to be able to load stored sessions using createSession(). There has been discussion of allowing implementations to not fire a “message” event when the CDM already has a license for the initData - as a way of dealing with the numerous “needkey” events that may occur for the same key(s) - but this was always in the context of normal streaming licenses. I don’t think this should be a method of loading stored/persisted licenses. There are a variety of performance, interoperability, algorithmic, and design reasons not to do so.

David

On Mon, Mar 17, 2014 at 1:52 AM, Maruyama, Shinya <Shinya.Maruyama@jp.sony.com<mailto:Shinya.Maruyama@jp.sony.com>> wrote:
Hi Joe,

I think we can’t have an assumption that the 'license policy' can be available to CDM only through DRM license because retailer/ecosystem may requires some complemental limitations or obligations which the system (rather than solo DRM client) must comply with.

In general, DRM license describes fundamental usage rules which DRM client must comply with; e.g.
- user-bound or device-bound
- validity period
etc
while retailer or ecosystem may require non-DRM limitations or obligations along with the license; e.g.
examples for UltraViolet
 - The maximum number of Devices concurrently joined to a Domain
- The maximum number of concurrent LASP Sessions
etc

In case of caching license, the DRM license must have the permission for 'persist' but it is not sufficient. In addition, the distributing retailer or ecosystem should also allow to persist it.
For instance, retailer may expect receiving license acquisition for every streaming to count the number of licenses issued concurrently or to check whether or not requesting client is revoked, etc. This may be accomplished by license acquisition (may be accomplished in out-of-band way though).

My proposal is to add normative way substitute for existing loadSession to switch whether to store or load the license at runtime. Therefore, your proposal“ignore_cached_licenses” is also fine with me (although the name looks confusing because the flag also should have an affect on whether to store the license for the ‘privacy mode’).

Thanks,
Shinya

From: Joe Steele [mailto:steele@adobe.com<mailto:steele@adobe.com>]
Sent: Thursday, March 13, 2014 2:58 AM
To: Maruyama, Shinya
Cc: Mark Watson; public-html-media@w3.org<mailto:public-html-media@w3.org>

Subject: Re: [EME] Persistent license


I don’t think it is useful for the application to determine the persistence of session information.

Assume an application wants to set this attribute to “false”:
The consequence for some CDMs would be a significant performance penalty. Most CDMs require an “individualization” step where device-specific keys are acquired. For some CDMs this step is costly in terms of battery cost, processor time, additional network transactions. So applications that want reasonable performance will have to figure out which key systems have this cost and always set this flag “true” in those cases anyway.

Assume an application wants to set this attribute to “true”:
The retailer sets a license policy that determines whether licenses can be cached and for how long. So even if the application says to cache the licenses the CDM will ignore this in favor of the license policy. Since the application is generally controlled by the retailer that is setting the license policy, and setting the license policy will have a more comprehensive effect than setting the application attribute, the retailer has no incentive to set the application attribute and will instead set the license policy at the time the license is issued.

If the goal of this attribute is to protect user privacy, the user would be better served by running the application in “privacy mode” where no transaction results are cached by the browser.

If the goal of this attribute is to protect retailer assets, the retailer would be better served by applying an appropriate license policy and selecting a key system that enforces it properly.

I think your specific concern would be better resolved by a more specific attribute like “ignore_cached_licenses”. This would direct the CDM to ignore any cached licenses (excluding “individualized” keys mentioned above) and allow the application to acquire a fresh set of licenses. I would support that attribute.

Joe

On Mar 11, 2014, at 5:46 PM, Maruyama, Shinya <Shinya.Maruyama@jp.sony.com<mailto:Shinya.Maruyama@jp.sony.com>> wrote:

You mean whether to load persistent license in createSession is not specified explicitly but is already left to CDM implementation, right?
I think between these two options; i.e. explicit loading by loadSession and implicit loading by createSession, there should be an another difference we should take care of.

As for loadSession, I assume that application can implement two different scenarios;
- In case of download file based playback, application calls loadSession to avoid unnecessary license acquisition.
- In case of streaming, application calls createSession to acquire license for every playback. In this case, application may expect createSession not to load persisted license regardless of availability of persistent licenses. Unexpected use of persistent license should be avoided especially for the streaming case because it may cause unexpected sequence for the service which may expect to receive license request for every playback

If we implement implicit license loading  by createSession, we can’t implement the latter scenario above because it is impossible to switch whether to load persistent license in createSession at runtime.

This is why I propose to use ‘persistent’ attribute which enables createSession to switch the behavior at runtime.

Thanks

From: Mark Watson [mailto:watsonm@netflix.com]
Sent: Wednesday, March 12, 2014 8:38 AM
To: Maruyama, Shinya
Cc: public-html-media@w3.org<mailto:public-html-media@w3.org>
Subject: Re: [EME] Persistent license

I think the intention was that if a CDM supports persistent licenses and when you do a createSession it finds an already persisted license that is appropriate for this content, then it can use that persisted license. The difference between createSession and loadSession is that createSession specifies what it needs with the initData wheras loadSession specifies what it needs with a sessionId.

...Mark

On Tue, Mar 11, 2014 at 4:21 PM, Maruyama, Shinya <Shinya.Maruyama@jp.sony.com<mailto:Shinya.Maruyama@jp.sony.com>> wrote:
Mark,

What do you think of loading license by createSession with using ‘persistent’ attribute’? Do you think there is still room to discuss whether to support this as another option to load persistent license or even as a substitute for existing loadSession?
I suppose there are some disadvantages on current loadSession.
- Using sessionId requires application to store sessionId beyond the lifetime of the session, which looks a bit weird semantically
- Application need to use some identifier; e.g. KIDs, initData, a content identifier obtained in out-of-band way etc, to retrieve the sessionId after all.

I suppose David’s proposal for ‘persistent’ attribute in https://www.w3.org/Bugs/Public/show_bug.cgi?id=24025#c10 would provide us with solutions for these disadvantages and moreover consistent EME API for the ‘persistent’ license usecase.

Thanks,
Shinya

From: Mark Watson [mailto:watsonm@netflix.com<mailto:watsonm@netflix.com>]
Sent: Wednesday, March 12, 2014 1:39 AM
To: Maruyama, Shinya
Cc: public-html-media@w3.org<mailto:public-html-media@w3.org>
Subject: Re: [EME] Persistent license

Shinya,

Yes, the note regarding session id uniqueness was intended to explain that if the UA supports retrieval of sessions by SessionId (now using loadSession) then it will need to ensure that the session ids have the necessary scope.

We should consider making this normative, since as you say loadSession is not very useful otherwise.

... Mark


Sent from my iPhone

On Mar 11, 2014, at 8:36 AM, "Maruyama, Shinya" <Shinya.Maruyama@jp.sony.com<mailto:Shinya.Maruyama@jp.sony.com>> wrote:
Hi all,

I’m concerned about ‘persistent’ attribute usage mentioned in Bugzilla#24025.

https://www.w3.org/Bugs/Public/show_bug.cgi?id=24025#c10


The attribute seems to be very useful to switch at runtime whether to store acquired license by createSession or load stored license by loadSession. I prefer this option rather than CDM deciding it implicitly as current methods assume. (There should be the case where application wants to avoid storing the license no matter whether the license/drm permits to store it. ‘persistent’ attribute seems to be reasonable to introduce for the reason).

In addition to these usages, I wonder if we could use the attribute to determine whether to load stored license in createSession. That is, persistent=true enables createSession to behave like offline first as application cache. Meaning, createSession with persistent=true tries to use cached license first. If there is no available license then it tries to acquire the license from server.

In the use-case of loading persistent license, I think the usage of createSession above is better than existing loadSession because of a interoperability problem for loadSession(sessionId). The rules of sessionId generation does not ensure that sessionId is unique across the browsing context. It may cause sessionId collision between current sessionId and a sessionId stored in CDM, which may result in unexpected overriding of sessionId or loading wrong license due to unexpected overriding etc. Unless EME clearly specifies that UA supporting loadSession must take care of such a collision, loadSession may behave in browser dependent way (The description in 1.1.4 “Note: Some use cases may require that Session IDs be unique within the origin over time, including across browsing sessions.” may imply the rule but currently this is just a informative).

Thanks,
Shinya Maruyama

Received on Monday, 7 April 2014 02:36:21 UTC