@l5i/dashjs
Version:
A reference client implementation for the playback of MPEG DASH via Javascript and compliant browsers.
138 lines (137 loc) • 13.2 kB
JavaScript
/**
* The copyright in this software is being made available under the BSD License,
* included below. This software may be subject to other third party and contributor
* rights, including patent rights, and no such rights are granted under this license.
*
* Copyright (c) 2013, Dash Industry Forum.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
* * Neither the name of Dash Industry Forum nor the names of its
* contributors may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/'use strict';Object.defineProperty(exports,'__esModule',{value:true});function _interopRequireDefault(obj){return obj && obj.__esModule?obj:{'default':obj};}var _CommonEncryption=require('./../CommonEncryption');var _CommonEncryption2=_interopRequireDefault(_CommonEncryption);var _drmKeySystemClearKey=require('./../drm/KeySystemClearKey');var _drmKeySystemClearKey2=_interopRequireDefault(_drmKeySystemClearKey);var _drmKeySystemW3CClearKey=require('./../drm/KeySystemW3CClearKey');var _drmKeySystemW3CClearKey2=_interopRequireDefault(_drmKeySystemW3CClearKey);var _drmKeySystemWidevine=require('./../drm/KeySystemWidevine');var _drmKeySystemWidevine2=_interopRequireDefault(_drmKeySystemWidevine);var _drmKeySystemPlayReady=require('./../drm/KeySystemPlayReady');var _drmKeySystemPlayReady2=_interopRequireDefault(_drmKeySystemPlayReady);var _serversDRMToday=require('./../servers/DRMToday');var _serversDRMToday2=_interopRequireDefault(_serversDRMToday);var _serversPlayReady=require('./../servers/PlayReady');var _serversPlayReady2=_interopRequireDefault(_serversPlayReady);var _serversWidevine=require('./../servers/Widevine');var _serversWidevine2=_interopRequireDefault(_serversWidevine);var _serversClearKey=require('./../servers/ClearKey');var _serversClearKey2=_interopRequireDefault(_serversClearKey);var _constantsProtectionConstants=require('../../constants/ProtectionConstants');var _constantsProtectionConstants2=_interopRequireDefault(_constantsProtectionConstants); /**
* @module ProtectionKeyController
* @description Media protection key system functionality that can be modified/overridden by applications
*/function ProtectionKeyController(){var context=this.context;var instance=undefined,debug=undefined,logger=undefined,keySystems=undefined,BASE64=undefined,clearkeyKeySystem=undefined,clearkeyW3CKeySystem=undefined;function setConfig(config){if(!config)return;if(config.debug){debug = config.debug;logger = debug.getLogger(instance);}if(config.BASE64){BASE64 = config.BASE64;}}function initialize(){keySystems = [];var keySystem=undefined; // PlayReady
keySystem = (0,_drmKeySystemPlayReady2['default'])(context).getInstance({BASE64:BASE64});keySystems.push(keySystem); // Widevine
keySystem = (0,_drmKeySystemWidevine2['default'])(context).getInstance({BASE64:BASE64});keySystems.push(keySystem); // ClearKey
keySystem = (0,_drmKeySystemClearKey2['default'])(context).getInstance({BASE64:BASE64});keySystems.push(keySystem);clearkeyKeySystem = keySystem; // W3C ClearKey
keySystem = (0,_drmKeySystemW3CClearKey2['default'])(context).getInstance({BASE64:BASE64,debug:debug});keySystems.push(keySystem);clearkeyW3CKeySystem = keySystem;} /**
* Returns a prioritized list of key systems supported
* by this player (not necessarily those supported by the
* user agent)
*
* @returns {Array.<KeySystem>} a prioritized
* list of key systems
* @memberof module:ProtectionKeyController
* @instance
*/function getKeySystems(){return keySystems;} /**
* Returns the key system associated with the given key system string
* name (i.e. 'org.w3.clearkey')
*
* @param {string} systemString the system string
* @returns {KeySystem|null} the key system
* or null if no supported key system is associated with the given key
* system string
* @memberof module:ProtectionKeyController
* @instance
*/function getKeySystemBySystemString(systemString){for(var i=0;i < keySystems.length;i++) {if(keySystems[i].systemString === systemString){return keySystems[i];}}return null;} /**
* Determines whether the given key system is ClearKey. This is
* necessary because the EME spec defines ClearKey and its method
* for providing keys to the key session; and this method has changed
* between the various API versions. Our EME-specific ProtectionModels
* must know if the system is ClearKey so that it can format the keys
* according to the particular spec version.
*
* @param {Object} keySystem the key
* @returns {boolean} true if this is the ClearKey key system, false
* otherwise
* @memberof module:ProtectionKeyController
* @instance
*/function isClearKey(keySystem){return keySystem === clearkeyKeySystem || keySystem === clearkeyW3CKeySystem;} /**
* Check equality of initData array buffers.
*
* @param {ArrayBuffer} initData1 - first initData
* @param {ArrayBuffer} initData2 - second initData
* @returns {boolean} true if the initData arrays are equal in size and
* contents, false otherwise
* @memberof module:ProtectionKeyController
* @instance
*/function initDataEquals(initData1,initData2){if(initData1.byteLength === initData2.byteLength){var data1=new Uint8Array(initData1);var data2=new Uint8Array(initData2);for(var j=0;j < data1.length;j++) {if(data1[j] !== data2[j]){return false;}}return true;}return false;} /**
* Returns a set of supported key systems and CENC initialization data
* from the given array of ContentProtection elements. Only
* key systems that are supported by this player will be returned.
* Key systems are returned in priority order (highest first).
*
* @param {Array.<Object>} cps - array of content protection elements parsed
* from the manifest
* @returns {Array.<Object>} array of objects indicating which supported key
* systems were found. Empty array is returned if no
* supported key systems were found
* @memberof module:ProtectionKeyController
* @instance
*/function getSupportedKeySystemsFromContentProtection(cps){var cp=undefined,ks=undefined,ksIdx=undefined,cpIdx=undefined;var supportedKS=[];if(cps){for(ksIdx = 0;ksIdx < keySystems.length;++ksIdx) {ks = keySystems[ksIdx];for(cpIdx = 0;cpIdx < cps.length;++cpIdx) {cp = cps[cpIdx];if(cp.schemeIdUri.toLowerCase() === ks.schemeIdURI){ // Look for DRM-specific ContentProtection
var initData=ks.getInitData(cp);if(!!initData){supportedKS.push({ks:keySystems[ksIdx],initData:initData,cdmData:ks.getCDMData(),sessionId:ks.getSessionId(cp)});}else if(this.isClearKey(ks)){supportedKS.push({ks:ks,initData:null});}}}}}return supportedKS;} /**
* Returns key systems supported by this player for the given PSSH
* initializationData. Only key systems supported by this player
* that have protection data present will be returned. Key systems are returned in priority order
* (highest priority first)
*
* @param {ArrayBuffer} initData Concatenated PSSH data for all DRMs
* supported by the content
* @param {ProtectionData} protDataSet user specified protection data - license server url etc
* supported by the content
* @returns {Array.<Object>} array of objects indicating which supported key
* systems were found. Empty array is returned if no
* supported key systems were found
* @memberof module:ProtectionKeyController
* @instance
*/function getSupportedKeySystems(initData,protDataSet){var supportedKS=[];var pssh=_CommonEncryption2['default'].parsePSSHList(initData);var ks=undefined,keySystemString=undefined,shouldNotFilterOutKeySystem=undefined;for(var ksIdx=0;ksIdx < keySystems.length;++ksIdx) {ks = keySystems[ksIdx];keySystemString = ks.systemString;shouldNotFilterOutKeySystem = protDataSet?keySystemString in protDataSet:true;if(ks.uuid in pssh && shouldNotFilterOutKeySystem){supportedKS.push({ks:ks,initData:pssh[ks.uuid],cdmData:ks.getCDMData(),sessionId:ks.getSessionId()});}}return supportedKS;} /**
* Returns the license server implementation data that should be used for this request.
*
* @param {KeySystem} keySystem the key system
* associated with this license request
* @param {ProtectionData} protData protection data to use for the
* request
* @param {string} [messageType="license-request"] the message type associated with this
* request. Supported message types can be found
* {@link https://w3c.github.io/encrypted-media/#idl-def-MediaKeyMessageType|here}.
* @returns {LicenseServer|null} the license server
* implementation that should be used for this request or null if the player should not
* pass messages of the given type to a license server
* @memberof module:ProtectionKeyController
* @instance
*
*/function getLicenseServer(keySystem,protData,messageType){ // Our default server implementations do not do anything with "license-release" or
// "individualization-request" messages, so we just send a success event
if(messageType === 'license-release' || messageType === 'individualization-request'){return null;}var licenseServerData=null;if(protData && protData.hasOwnProperty('drmtoday')){licenseServerData = (0,_serversDRMToday2['default'])(context).getInstance({BASE64:BASE64});}else if(keySystem.systemString === _constantsProtectionConstants2['default'].WIDEVINE_KEYSTEM_STRING){licenseServerData = (0,_serversWidevine2['default'])(context).getInstance();}else if(keySystem.systemString === _constantsProtectionConstants2['default'].PLAYREADY_KEYSTEM_STRING){licenseServerData = (0,_serversPlayReady2['default'])(context).getInstance();}else if(keySystem.systemString === _constantsProtectionConstants2['default'].CLEARKEY_KEYSTEM_STRING){licenseServerData = (0,_serversClearKey2['default'])(context).getInstance();}return licenseServerData;} /**
* Allows application-specific retrieval of ClearKey keys.
*
* @param {KeySystem} clearkeyKeySystem They exact ClearKey System to be used
* @param {ProtectionData} protData protection data to use for the
* request
* @param {ArrayBuffer} message the key message from the CDM
* @return {ClearKeyKeySet|null} the clear keys associated with
* the request or null if no keys can be returned by this function
* @memberof module:ProtectionKeyController
* @instance
*/function processClearKeyLicenseRequest(clearkeyKeySystem,protData,message){try{return clearkeyKeySystem.getClearKeysFromProtectionData(protData,message);}catch(error) {logger.error('Failed to retrieve clearkeys from ProtectionData');return null;}}function setProtectionData(protectionDataSet){var getProtectionData=function getProtectionData(keySystemString){var protData=null;if(protectionDataSet){protData = keySystemString in protectionDataSet?protectionDataSet[keySystemString]:null;}return protData;};for(var i=0;i < keySystems.length;i++) {var keySystem=keySystems[i];if(keySystem.hasOwnProperty('init')){keySystem.init(getProtectionData(keySystem.systemString));}}}instance = {initialize:initialize,setProtectionData:setProtectionData,isClearKey:isClearKey,initDataEquals:initDataEquals,getKeySystems:getKeySystems,getKeySystemBySystemString:getKeySystemBySystemString,getSupportedKeySystemsFromContentProtection:getSupportedKeySystemsFromContentProtection,getSupportedKeySystems:getSupportedKeySystems,getLicenseServer:getLicenseServer,processClearKeyLicenseRequest:processClearKeyLicenseRequest,setConfig:setConfig};return instance;}ProtectionKeyController.__dashjs_factory_name = 'ProtectionKeyController';exports['default'] = dashjs.FactoryMaker.getSingletonFactory(ProtectionKeyController); /* jshint ignore:line */module.exports = exports['default'];
//# sourceMappingURL=ProtectionKeyController.js.map