From fe1f35bf3985a53c6b7f5860ffea81aa0ae0b73e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Velad=20Galv=C3=A1n?= Date: Tue, 31 Dec 2024 14:51:07 +0100 Subject: [PATCH] fix: Fix ClearKey license on old CDMs (#7816) --- lib/drm/drm_engine.js | 45 ++++++++++++++++++++++++++++++++++++++ lib/drm/drm_utils.js | 8 +++++++ test/drm/drm_utils_unit.js | 16 ++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/lib/drm/drm_engine.js b/lib/drm/drm_engine.js index d909ab8a45..cea21c6e28 100644 --- a/lib/drm/drm_engine.js +++ b/lib/drm/drm_engine.js @@ -1525,6 +1525,11 @@ shaka.drm.DrmEngine = class { } // NOTE: allowCrossSiteCredentials can be set in a request filter. + if (shaka.drm.DrmUtils.isClearKeySystem( + this.currentDrmInfo_.keySystem)) { + this.fixClearKeyRequest_(request, this.currentDrmInfo_); + } + if (shaka.drm.DrmUtils.isPlayReadyKeySystem( this.currentDrmInfo_.keySystem)) { this.unpackPlayReadyRequest_(request); @@ -1678,6 +1683,31 @@ shaka.drm.DrmEngine = class { /** @type{string} */(shaka.util.TXml.getTextContents(challenge))); } + /** + * Some old ClearKey CDMs don't include the type in the body request. + * + * @param {shaka.extern.Request} request + * @param {shaka.extern.DrmInfo} drmInfo + * @private + */ + fixClearKeyRequest_(request, drmInfo) { + try { + const body = shaka.util.StringUtils.fromBytesAutoDetect(request.body); + if (body) { + const licenseBody = + /** @type {shaka.drm.DrmEngine.ClearKeyLicenceRequestFormat} */ ( + JSON.parse(body)); + if (!licenseBody.type) { + licenseBody.type = drmInfo.sessionType; + request.body = + shaka.util.StringUtils.toUTF8(JSON.stringify(licenseBody)); + } + } + } catch (e) { + shaka.log.info('Error unpacking ClearKey license', e); + } + } + /** * @param {!Event} event * @private @@ -2729,6 +2759,21 @@ shaka.drm.DrmEngine.SessionMetaData; */ shaka.drm.DrmEngine.PlayerInterface; +/** + * @typedef {{ + * kids: !Array., + * type: string + * }} + * + * @property {!Array.} kids + * An array of key IDs. Each element of the array is the base64url encoding of + * the octet sequence containing the key ID value. + * @property {string} type + * The requested MediaKeySessionType. + * @see https://www.w3.org/TR/encrypted-media/#clear-key-request-format + */ +shaka.drm.DrmEngine.ClearKeyLicenceRequestFormat; + /** * The amount of time, in seconds, we wait to consider a session closed. * This allows us to work around Chrome bug https://crbug.com/1108158. diff --git a/lib/drm/drm_utils.js b/lib/drm/drm_utils.js index 7f6310bae5..df840c3606 100644 --- a/lib/drm/drm_utils.js +++ b/lib/drm/drm_utils.js @@ -113,6 +113,14 @@ shaka.drm.DrmUtils = class { return drmInfo ? drmInfo.keySystem : ''; } + /** + * @param {?string} keySystem + * @return {boolean} + */ + static isClearKeySystem(keySystem) { + return keySystem === 'org.w3.clearkey'; + } + /** * @param {?string} keySystem * @return {boolean} diff --git a/test/drm/drm_utils_unit.js b/test/drm/drm_utils_unit.js index 7ddfb81da3..0df5db051f 100644 --- a/test/drm/drm_utils_unit.js +++ b/test/drm/drm_utils_unit.js @@ -145,6 +145,22 @@ describe('DrmUtils', () => { }); }); // describe('getCommonDrmInfos') + describe('isClearKeySystem', () => { + it('should return true for ClearKey', () => { + expect(shaka.drm.DrmUtils.isClearKeySystem( + 'org.w3.clearkey')).toBe(true); + }); + + it('should return false for non-ClearKey key systems', () => { + expect(shaka.drm.DrmUtils.isClearKeySystem( + 'com.widevine.alpha')).toBe(false); + expect(shaka.drm.DrmUtils.isClearKeySystem( + 'com.microsoft.playready')).toBe(false); + expect(shaka.drm.DrmUtils.isClearKeySystem( + 'com.apple.fps')).toBe(false); + }); + }); + describe('isWidevineKeySystem', () => { it('should return true for Widevine', () => { expect(shaka.drm.DrmUtils.isWidevineKeySystem(