(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); } }; } })();