mirror of
https://github.com/shaka-project/shaka-player.git
synced 2026-06-24 17:35:10 +03:00
3b0a035473
As we already have `DrmUtils`, try to cut few lines from `DrmEngine`.
226 lines
6.4 KiB
JavaScript
226 lines
6.4 KiB
JavaScript
/*! @license
|
|
* Shaka Player
|
|
* Copyright 2016 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
goog.provide('shaka.util.DrmUtils');
|
|
|
|
goog.require('shaka.util.BufferUtils');
|
|
goog.require('shaka.util.Lazy');
|
|
|
|
|
|
shaka.util.DrmUtils = class {
|
|
/**
|
|
* Returns true if the browser has recent EME APIs.
|
|
*
|
|
* @return {boolean}
|
|
*/
|
|
static isBrowserSupported() {
|
|
const basic =
|
|
!!window.MediaKeys &&
|
|
!!window.navigator &&
|
|
!!window.navigator.requestMediaKeySystemAccess &&
|
|
!!window.MediaKeySystemAccess &&
|
|
// eslint-disable-next-line no-restricted-syntax
|
|
!!window.MediaKeySystemAccess.prototype.getConfiguration;
|
|
|
|
return basic;
|
|
}
|
|
|
|
/**
|
|
* Checks if two DrmInfos can be decrypted using the same key system.
|
|
* Clear content is considered compatible with every key system.
|
|
*
|
|
* @param {!Array<!shaka.extern.DrmInfo>} drms1
|
|
* @param {!Array<!shaka.extern.DrmInfo>} drms2
|
|
* @return {boolean}
|
|
*/
|
|
static areDrmCompatible(drms1, drms2) {
|
|
if (!drms1.length || !drms2.length) {
|
|
return true;
|
|
}
|
|
|
|
if (drms1 === drms2) {
|
|
return true;
|
|
}
|
|
|
|
return shaka.util.DrmUtils.getCommonDrmInfos(
|
|
drms1, drms2).length > 0;
|
|
}
|
|
|
|
/**
|
|
* Returns an array of drm infos that are present in both input arrays.
|
|
* If one of the arrays is empty, returns the other one since clear
|
|
* content is considered compatible with every drm info.
|
|
*
|
|
* @param {!Array<!shaka.extern.DrmInfo>} drms1
|
|
* @param {!Array<!shaka.extern.DrmInfo>} drms2
|
|
* @return {!Array<!shaka.extern.DrmInfo>}
|
|
*/
|
|
static getCommonDrmInfos(drms1, drms2) {
|
|
if (!drms1.length) {
|
|
return drms2;
|
|
}
|
|
if (!drms2.length) {
|
|
return drms1;
|
|
}
|
|
|
|
const commonDrms = [];
|
|
|
|
for (const drm1 of drms1) {
|
|
for (const drm2 of drms2) {
|
|
if (drm1.keySystem == drm2.keySystem) {
|
|
const initDataMap = new Map();
|
|
const bothInitDatas = (drm1.initData || [])
|
|
.concat(drm2.initData || []);
|
|
for (const d of bothInitDatas) {
|
|
initDataMap.set(d.keyId, d);
|
|
}
|
|
const initData = Array.from(initDataMap.values());
|
|
|
|
const keyIds = drm1.keyIds && drm2.keyIds ?
|
|
new Set([...drm1.keyIds, ...drm2.keyIds]) :
|
|
drm1.keyIds || drm2.keyIds;
|
|
const mergedDrm = {
|
|
keySystem: drm1.keySystem,
|
|
licenseServerUri: drm1.licenseServerUri || drm2.licenseServerUri,
|
|
distinctiveIdentifierRequired: drm1.distinctiveIdentifierRequired ||
|
|
drm2.distinctiveIdentifierRequired,
|
|
persistentStateRequired: drm1.persistentStateRequired ||
|
|
drm2.persistentStateRequired,
|
|
videoRobustness: drm1.videoRobustness || drm2.videoRobustness,
|
|
audioRobustness: drm1.audioRobustness || drm2.audioRobustness,
|
|
serverCertificate: drm1.serverCertificate || drm2.serverCertificate,
|
|
serverCertificateUri: drm1.serverCertificateUri ||
|
|
drm2.serverCertificateUri,
|
|
initData,
|
|
keyIds,
|
|
};
|
|
commonDrms.push(mergedDrm);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return commonDrms;
|
|
}
|
|
|
|
/**
|
|
* @param {?shaka.extern.DrmInfo} drmInfo
|
|
* @return {string} */
|
|
static keySystem(drmInfo) {
|
|
return drmInfo ? drmInfo.keySystem : '';
|
|
}
|
|
|
|
/**
|
|
* @param {?string} keySystem
|
|
* @return {boolean}
|
|
*/
|
|
static isPlayReadyKeySystem(keySystem) {
|
|
if (keySystem) {
|
|
return !!keySystem.match(/^com\.(microsoft|chromecast)\.playready/);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @param {?string} keySystem
|
|
* @return {boolean}
|
|
*/
|
|
static isFairPlayKeySystem(keySystem) {
|
|
if (keySystem) {
|
|
return !!keySystem.match(/^com\.apple\.fps/);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* A method for generating a key for the MediaKeySystemAccessRequests cache.
|
|
*
|
|
* @param {string} videoCodec
|
|
* @param {string} audioCodec
|
|
* @param {string} keySystem
|
|
* @return {string}
|
|
* @private
|
|
*/
|
|
static generateKeySystemCacheKey_(videoCodec, audioCodec, keySystem) {
|
|
return `${videoCodec}#${audioCodec}#${keySystem}`;
|
|
}
|
|
|
|
/**
|
|
* Check does MediaKeySystemAccess cache contains something for following
|
|
* attributes.
|
|
*
|
|
* @param {string} videoCodec
|
|
* @param {string} audioCodec
|
|
* @param {string} keySystem
|
|
* @return {boolean}
|
|
*/
|
|
static hasMediaKeySystemAccess(videoCodec, audioCodec, keySystem) {
|
|
const DrmUtils = shaka.util.DrmUtils;
|
|
const key = DrmUtils.generateKeySystemCacheKey_(
|
|
videoCodec, audioCodec, keySystem);
|
|
return DrmUtils.memoizedMediaKeySystemAccessRequests_.has(key);
|
|
}
|
|
|
|
/**
|
|
* Get MediaKeySystemAccess object for following attributes.
|
|
*
|
|
* @param {string} videoCodec
|
|
* @param {string} audioCodec
|
|
* @param {string} keySystem
|
|
* @return {?MediaKeySystemAccess}
|
|
*/
|
|
static getMediaKeySystemAccess(videoCodec, audioCodec, keySystem) {
|
|
const DrmUtils = shaka.util.DrmUtils;
|
|
const key = DrmUtils.generateKeySystemCacheKey_(
|
|
videoCodec, audioCodec, keySystem);
|
|
return DrmUtils.memoizedMediaKeySystemAccessRequests_.get(key) || null;
|
|
}
|
|
|
|
/**
|
|
* Store MediaKeySystemAccess object associated with specified attributes.
|
|
*
|
|
* @param {string} videoCodec
|
|
* @param {string} audioCodec
|
|
* @param {string} keySystem
|
|
* @param {!MediaKeySystemAccess} mksa
|
|
*/
|
|
static setMediaKeySystemAccess(videoCodec, audioCodec, keySystem, mksa) {
|
|
const DrmUtils = shaka.util.DrmUtils;
|
|
const key = DrmUtils.generateKeySystemCacheKey_(
|
|
videoCodec, audioCodec, keySystem);
|
|
return DrmUtils.memoizedMediaKeySystemAccessRequests_.set(key, mksa);
|
|
}
|
|
|
|
/**
|
|
* Clears underlying cache.
|
|
*/
|
|
static clearMediaKeySystemAccessMap() {
|
|
const DrmUtils = shaka.util.DrmUtils;
|
|
DrmUtils.memoizedMediaKeySystemAccessRequests_.clear();
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* Contains the suggested "default" key ID used by EME polyfills that do not
|
|
* have a per-key key status. See w3c/encrypted-media#32.
|
|
* @type {!shaka.util.Lazy<!ArrayBuffer>}
|
|
*/
|
|
shaka.util.DrmUtils.DUMMY_KEY_ID = new shaka.util.Lazy(
|
|
() => shaka.util.BufferUtils.toArrayBuffer(new Uint8Array([0])));
|
|
|
|
|
|
/**
|
|
* A cache that stores the MediaKeySystemAccess result of calling
|
|
* `navigator.requestMediaKeySystemAccess` by a key combination of
|
|
* video/audio codec and key system string.
|
|
*
|
|
* @private {!Map<string, !MediaKeySystemAccess>}
|
|
*/
|
|
shaka.util.DrmUtils.memoizedMediaKeySystemAccessRequests_ = new Map();
|