mirror of
https://github.com/servo/servo.git
synced 2025-07-12 18:03:49 +01:00
193 lines
7.5 KiB
JavaScript
193 lines
7.5 KiB
JavaScript
(function() {
|
|
|
|
// This polyfill fixes the following problems with Edge browser
|
|
// (1) To retrieve a persisted usage record, you must use session type 'persistent-release-message' instead of 'persistent-usage-record'
|
|
// (2) To retrieve a persisted usage record, you must call remove() after calling load()
|
|
// (3) On providing a license release acknowledgement, the session does not automatically close as is should
|
|
// (4) Retrieval of the usage record at the end of an active session is not supported
|
|
|
|
if ( navigator.userAgent.toLowerCase().indexOf('edge') > -1 ) {
|
|
|
|
var _mediaKeySystemAccessCreateMediaKeys = MediaKeySystemAccess.prototype.createMediaKeys;
|
|
_mediaKeysCreateSession = MediaKeys.prototype.createSession;
|
|
|
|
// MediaKeySession proxy
|
|
function MediaKeySession( mediaKeys, session )
|
|
{
|
|
EventTarget.call( this );
|
|
|
|
this._mediaKeys = mediaKeys;
|
|
this._session = session;
|
|
this._sessionId = undefined;
|
|
this._removing = false;
|
|
|
|
session.addEventListener( 'message', this.dispatchEvent.bind( this ) );
|
|
session.addEventListener( 'keystatuseschange', this.dispatchEvent.bind( this ) );
|
|
session.closed.then( function() { if ( !this._removing ) this._resolveClosed(); }.bind ( this ) );
|
|
|
|
this._closed = new Promise( function( resolve ) { this._resolveClosed = resolve; }.bind( this ) );
|
|
}
|
|
|
|
MediaKeySession.prototype = Object.create( EventTarget.prototype );
|
|
|
|
Object.defineProperties( MediaKeySession.prototype, {
|
|
sessionId: { get: function() { return this._sessionId ? this._sessionId : this._session.sessionId; } },
|
|
expiration: { get: function() { return this._session.expiration; } },
|
|
closed: { get: function() { return this._closed; } },
|
|
keyStatuses:{ get: function() { return this._session.keyStatuses; } }
|
|
});
|
|
|
|
// load()
|
|
//
|
|
// Use a surrogate 'persistent-release-message' session to obtain the release message
|
|
//
|
|
MediaKeySession.prototype.load = function load( sessionId )
|
|
{
|
|
if ( this.sessionId ) return Promise.reject( new DOMException('InvalidAccessError') );
|
|
|
|
this._surrogate = this._mediaKeys.createSession( 'persistent-release-message' );
|
|
this._surrogate.addEventListener( 'message', this.dispatchEvent.bind( this ) );
|
|
|
|
return this._surrogate.load( sessionId ).then( function( success ) {
|
|
if (!success) return false;
|
|
|
|
this._sessionId = sessionId;
|
|
this._removing = true;
|
|
this._session.close();
|
|
|
|
return this._surrogate.remove().then( function() { return true; } );
|
|
}.bind( this ) );
|
|
};
|
|
|
|
// remove()
|
|
//
|
|
// On an existing session, use a surrogate 'persistent-release-message' session to obtain the release message
|
|
//
|
|
MediaKeySession.prototype.remove = function remove()
|
|
{
|
|
if ( this._sessionId !== undefined ) return Promise.reject( new DOMException('InvalidAccessError') );
|
|
if ( this.sessionId === undefined ) return Promise.reject( new DOMException('InvalidAccessError') );
|
|
|
|
this._surrogate = this._mediaKeys.createSession( 'persistent-release-message' );
|
|
this._surrogate.addEventListener( 'message', this.dispatchEvent.bind( this ) );
|
|
this._removing = true;
|
|
this._sessionId = this._session.sessionId;
|
|
|
|
var self = this;
|
|
|
|
return Promise.all( [ self._session.close(), self._session.closed ] ).then( function() {
|
|
return self._surrogate.load( self._sessionId );
|
|
}).then( function( success ) {
|
|
if ( !success ) {
|
|
throw new DOMException('InvalidAccessError');
|
|
}
|
|
|
|
return self._surrogate.remove();
|
|
}).then( function() { return true; } );
|
|
}
|
|
|
|
// update()
|
|
//
|
|
// For a normal session, pass through, otherwise update the surrogate and close the proxy
|
|
MediaKeySession.prototype.update = function update( message )
|
|
{
|
|
if ( !this._removing ) return this._session.update( message );
|
|
|
|
return this._surrogate.update( message ).then( function() {
|
|
this._sessionId = undefined;
|
|
this._resolveClosed();
|
|
}.bind( this ) );
|
|
};
|
|
|
|
// close() - pass through
|
|
//
|
|
MediaKeySession.prototype.close = function close()
|
|
{
|
|
if ( !this._removing ) return this._session.close();
|
|
this._resolveClosed();
|
|
return Promise.resolve();
|
|
};
|
|
|
|
// generateRequest() - pass through
|
|
//
|
|
MediaKeySession.prototype.generateRequest = function generateRequest( initDataType, initData )
|
|
{
|
|
if ( this.sessionId ) Promise.reject( new DOMException('InvalidAccessError') );
|
|
return this._session.generateRequest( initDataType, initData );
|
|
};
|
|
|
|
// Wrap PlayReady persistent-usage-record sessions in our Proxy
|
|
MediaKeys.prototype.createSession = function createSession( sessionType ) {
|
|
|
|
var session = _mediaKeysCreateSession.call( this, sessionType );
|
|
if ( this._keySystem !== 'com.microsoft.playready' || sessionType !== 'persistent-usage-record' )
|
|
{
|
|
return session;
|
|
}
|
|
|
|
return new MediaKeySession( this, session );
|
|
|
|
};
|
|
|
|
//
|
|
// Annotation polyfills - annotate not otherwise available data
|
|
//
|
|
|
|
// Annotate MediaKeys with the keysystem
|
|
MediaKeySystemAccess.prototype.createMediaKeys = function createMediaKeys()
|
|
{
|
|
return _mediaKeySystemAccessCreateMediaKeys.call( this ).then( function( mediaKeys ) {
|
|
mediaKeys._keySystem = this.keySystem;
|
|
return mediaKeys;
|
|
}.bind( this ) );
|
|
};
|
|
|
|
//
|
|
// Utilities
|
|
//
|
|
|
|
// Allow us to modify the target of Events
|
|
Object.defineProperties( Event.prototype, {
|
|
target: { get: function() { return this._target || this.currentTarget; },
|
|
set: function( newtarget ) { this._target = newtarget; } }
|
|
} );
|
|
|
|
// Make an EventTarget base class
|
|
function EventTarget(){
|
|
this.listeners = {};
|
|
};
|
|
|
|
EventTarget.prototype.listeners = null;
|
|
|
|
EventTarget.prototype.addEventListener = function(type, callback){
|
|
if(!(type in this.listeners)) {
|
|
this.listeners[type] = [];
|
|
}
|
|
this.listeners[type].push(callback);
|
|
};
|
|
|
|
EventTarget.prototype.removeEventListener = function(type, callback){
|
|
if(!(type in this.listeners)) {
|
|
return;
|
|
}
|
|
var stack = this.listeners[type];
|
|
for(var i = 0, l = stack.length; i < l; i++){
|
|
if(stack[i] === callback){
|
|
stack.splice(i, 1);
|
|
return this.removeEventListener(type, callback);
|
|
}
|
|
}
|
|
};
|
|
|
|
EventTarget.prototype.dispatchEvent = function(event){
|
|
if(!(event.type in this.listeners)) {
|
|
return;
|
|
}
|
|
var stack = this.listeners[event.type];
|
|
event.target = this;
|
|
for(var i = 0, l = stack.length; i < l; i++) {
|
|
stack[i].call(this, event);
|
|
}
|
|
};
|
|
}
|
|
})();
|