OLD | NEW |
(Empty) | |
| 1 (function() { |
| 2 |
| 3 // This polyfill fixes the following problems with Edge browser |
| 4 // (1) To retrieve a persisted usage record, you must use session type 'pers
istent-release-message' instead of 'persistent-usage-record' |
| 5 // (2) To retrieve a persisted usage record, you must call remove() after ca
lling load() |
| 6 // (3) On providing a license release acknowledgement, the session does not
automatically close as is should |
| 7 // (4) Retrieval of the usage record at the end of an active session is not
supported |
| 8 |
| 9 if ( navigator.userAgent.toLowerCase().indexOf('edge') > -1 ) { |
| 10 |
| 11 var _mediaKeySystemAccessCreateMediaKeys = MediaKeySystemAccess.prototyp
e.createMediaKeys; |
| 12 _mediaKeysCreateSession = MediaKeys.prototype.createSession; |
| 13 |
| 14 // MediaKeySession proxy |
| 15 function MediaKeySession( mediaKeys, session ) |
| 16 { |
| 17 EventTarget.call( this ); |
| 18 |
| 19 this._mediaKeys = mediaKeys; |
| 20 this._session = session; |
| 21 this._sessionId = undefined; |
| 22 this._removing = false; |
| 23 |
| 24 session.addEventListener( 'message', this.dispatchEvent.bind( this )
); |
| 25 session.addEventListener( 'keystatuseschange', this.dispatchEvent.bi
nd( this ) ); |
| 26 session.closed.then( function() { if ( !this._removing ) this._resol
veClosed(); }.bind ( this ) ); |
| 27 |
| 28 this._closed = new Promise( function( resolve ) { this._resolveClose
d = resolve; }.bind( this ) ); |
| 29 } |
| 30 |
| 31 MediaKeySession.prototype = Object.create( EventTarget.prototype ); |
| 32 |
| 33 Object.defineProperties( MediaKeySession.prototype, { |
| 34 sessionId: { get: function() { return this._sessionId ? this._sessi
onId : this._session.sessionId; } }, |
| 35 expiration: { get: function() { return this._session.expiration; } }
, |
| 36 closed: { get: function() { return this._closed; } }, |
| 37 keyStatuses:{ get: function() { return this._session.keyStatuses; }
} |
| 38 }); |
| 39 |
| 40 // load() |
| 41 // |
| 42 // Use a surrogate 'persistent-release-message' session to obtain the re
lease message |
| 43 // |
| 44 MediaKeySession.prototype.load = function load( sessionId ) |
| 45 { |
| 46 if ( this.sessionId ) return Promise.reject( new DOMException('Inval
idAccessError') ); |
| 47 |
| 48 this._surrogate = this._mediaKeys.createSession( 'persistent-release
-message' ); |
| 49 this._surrogate.addEventListener( 'message', this.dispatchEvent.bind
( this ) ); |
| 50 |
| 51 return this._surrogate.load( sessionId ).then( function( success ) { |
| 52 if (!success) return false; |
| 53 |
| 54 this._sessionId = sessionId; |
| 55 this._removing = true; |
| 56 this._session.close(); |
| 57 |
| 58 return this._surrogate.remove().then( function() { return true;
} ); |
| 59 }.bind( this ) ); |
| 60 }; |
| 61 |
| 62 // remove() |
| 63 // |
| 64 // On an existing session, use a surrogate 'persistent-release-message'
session to obtain the release message |
| 65 // |
| 66 MediaKeySession.prototype.remove = function remove() |
| 67 { |
| 68 if ( this._sessionId !== undefined ) return Promise.reject( new DOME
xception('InvalidAccessError') ); |
| 69 if ( this.sessionId === undefined ) return Promise.reject( new DOMEx
ception('InvalidAccessError') ); |
| 70 |
| 71 this._surrogate = this._mediaKeys.createSession( 'persistent-release
-message' ); |
| 72 this._surrogate.addEventListener( 'message', this.dispatchEvent.bind
( this ) ); |
| 73 this._removing = true; |
| 74 this._sessionId = this._session.sessionId; |
| 75 |
| 76 var self = this; |
| 77 |
| 78 return Promise.all( [ self._session.close(), self._session.closed ]
).then( function() { |
| 79 return self._surrogate.load( self._sessionId ); |
| 80 }).then( function( success ) { |
| 81 if ( !success ) { |
| 82 throw new DOMException('InvalidAccessError'); |
| 83 } |
| 84 |
| 85 return self._surrogate.remove(); |
| 86 }).then( function() { return true; } ); |
| 87 } |
| 88 |
| 89 // update() |
| 90 // |
| 91 // For a normal session, pass through, otherwise update the surrogate an
d close the proxy |
| 92 MediaKeySession.prototype.update = function update( message ) |
| 93 { |
| 94 if ( !this._removing ) return this._session.update( message ); |
| 95 |
| 96 return this._surrogate.update( message ).then( function() { |
| 97 this._sessionId = undefined; |
| 98 this._resolveClosed(); |
| 99 }.bind( this ) ); |
| 100 }; |
| 101 |
| 102 // close() - pass through |
| 103 // |
| 104 MediaKeySession.prototype.close = function close() |
| 105 { |
| 106 if ( !this._removing ) return this._session.close(); |
| 107 this._resolveClosed(); |
| 108 return Promise.resolve(); |
| 109 }; |
| 110 |
| 111 // generateRequest() - pass through |
| 112 // |
| 113 MediaKeySession.prototype.generateRequest = function generateRequest( in
itDataType, initData ) |
| 114 { |
| 115 if ( this.sessionId ) Promise.reject( new DOMException('InvalidAcces
sError') ); |
| 116 return this._session.generateRequest( initDataType, initData ); |
| 117 }; |
| 118 |
| 119 // Wrap PlayReady persistent-usage-record sessions in our Proxy |
| 120 MediaKeys.prototype.createSession = function createSession( sessionType
) { |
| 121 |
| 122 var session = _mediaKeysCreateSession.call( this, sessionType ); |
| 123 if ( this._keySystem !== 'com.microsoft.playready' || sessionType !=
= 'persistent-usage-record' ) |
| 124 { |
| 125 return session; |
| 126 } |
| 127 |
| 128 return new MediaKeySession( this, session ); |
| 129 |
| 130 }; |
| 131 |
| 132 // |
| 133 // Annotation polyfills - annotate not otherwise available data |
| 134 // |
| 135 |
| 136 // Annotate MediaKeys with the keysystem |
| 137 MediaKeySystemAccess.prototype.createMediaKeys = function createMediaKey
s() |
| 138 { |
| 139 return _mediaKeySystemAccessCreateMediaKeys.call( this ).then( funct
ion( mediaKeys ) { |
| 140 mediaKeys._keySystem = this.keySystem; |
| 141 return mediaKeys; |
| 142 }.bind( this ) ); |
| 143 }; |
| 144 |
| 145 // |
| 146 // Utilities |
| 147 // |
| 148 |
| 149 // Allow us to modify the target of Events |
| 150 Object.defineProperties( Event.prototype, { |
| 151 target: { get: function() { return this._target || this.currentTar
get; }, |
| 152 set: function( newtarget ) { this._target = newtarget; }
} |
| 153 } ); |
| 154 |
| 155 // Make an EventTarget base class |
| 156 function EventTarget(){ |
| 157 this.listeners = {}; |
| 158 }; |
| 159 |
| 160 EventTarget.prototype.listeners = null; |
| 161 |
| 162 EventTarget.prototype.addEventListener = function(type, callback){ |
| 163 if(!(type in this.listeners)) { |
| 164 this.listeners[type] = []; |
| 165 } |
| 166 this.listeners[type].push(callback); |
| 167 }; |
| 168 |
| 169 EventTarget.prototype.removeEventListener = function(type, callback){ |
| 170 if(!(type in this.listeners)) { |
| 171 return; |
| 172 } |
| 173 var stack = this.listeners[type]; |
| 174 for(var i = 0, l = stack.length; i < l; i++){ |
| 175 if(stack[i] === callback){ |
| 176 stack.splice(i, 1); |
| 177 return this.removeEventListener(type, callback); |
| 178 } |
| 179 } |
| 180 }; |
| 181 |
| 182 EventTarget.prototype.dispatchEvent = function(event){ |
| 183 if(!(event.type in this.listeners)) { |
| 184 return; |
| 185 } |
| 186 var stack = this.listeners[event.type]; |
| 187 event.target = this; |
| 188 for(var i = 0, l = stack.length; i < l; i++) { |
| 189 stack[i].call(this, event); |
| 190 } |
| 191 }; |
| 192 } |
| 193 })(); |
OLD | NEW |