Index: third_party/WebKit/LayoutTests/imported/wpt/encrypted-media/polyfill/edge-persistent-usage-record.js |
diff --git a/third_party/WebKit/LayoutTests/imported/wpt/encrypted-media/polyfill/edge-persistent-usage-record.js b/third_party/WebKit/LayoutTests/imported/wpt/encrypted-media/polyfill/edge-persistent-usage-record.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7f86f0c05895a2f82ec4ac80252cf4eb4a33d5e2 |
--- /dev/null |
+++ b/third_party/WebKit/LayoutTests/imported/wpt/encrypted-media/polyfill/edge-persistent-usage-record.js |
@@ -0,0 +1,193 @@ |
+(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); |
+ } |
+ }; |
+ } |
+})(); |