From 61613cf0ee8bdbcbf7bfee209bba4fe052f8857c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Velad=20Galv=C3=A1n?= Date: Wed, 11 Jan 2023 21:04:16 +0100 Subject: [PATCH] feat: Config to require a minimum HDCP version (#4883) https://github.com/WICG/hdcp-detection/blob/main/explainer.md Co-authored-by: Joey Parrish --- demo/common/message_ids.js | 1 + demo/config.js | 4 +++- demo/locales/en.json | 1 + demo/locales/source.json | 4 ++++ externs/mediakeys.js | 18 ++++++++++++++++++ externs/shaka/player.js | 7 ++++++- lib/media/drm_engine.js | 21 +++++++++++++++++++++ lib/polyfill/patchedmediakeys_apple.js | 5 +++++ lib/polyfill/patchedmediakeys_nop.js | 5 +++++ lib/polyfill/patchedmediakeys_webkit.js | 5 +++++ lib/util/error.js | 11 +++++++++++ lib/util/player_configuration.js | 1 + 12 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 externs/mediakeys.js diff --git a/demo/common/message_ids.js b/demo/common/message_ids.js index 6ee5e5fe7f..187e13de96 100644 --- a/demo/common/message_ids.js +++ b/demo/common/message_ids.js @@ -232,6 +232,7 @@ shakaDemo.MessageIds = { MEDIA_SOURCE_SECTION_HEADER: 'DEMO_MEDIA_SOURCE_SECTION_HEADER', MIN_BANDWIDTH: 'DEMO_MIN_BANDWIDTH', MIN_BYTES: 'DEMO_MIN_BYTES', + MIN_HDCP_VERSION: 'DEMO_MIN_HDCP_VERSION', MIN_FRAMERATE: 'DEMO_MIN_FRAMERATE', MIN_HEIGHT: 'DEMO_MIN_HEIGHT', MIN_PIXELS: 'DEMO_MIN_PIXELS', diff --git a/demo/config.js b/demo/config.js index 0baca4b6eb..a5f6fb2426 100644 --- a/demo/config.js +++ b/demo/config.js @@ -135,7 +135,9 @@ shakaDemo.Config = class { /* canBeZero= */ false, /* canBeUnset= */ true) .addBoolInput_(MessageIds.PARSE_INBAND_PSSH_ENABLED, - 'drm.parseInbandPsshEnabled'); + 'drm.parseInbandPsshEnabled') + .addTextInput_(MessageIds.MIN_HDCP_VERSION, + 'drm.minHdcpVersion'); const advanced = shakaDemoMain.getConfiguration().drm.advanced || {}; const addDRMAdvancedField = (name, valueName, suggestions) => { // All advanced fields of a given type are set at once. diff --git a/demo/locales/en.json b/demo/locales/en.json index fe028bd096..8a90fa8499 100644 --- a/demo/locales/en.json +++ b/demo/locales/en.json @@ -157,6 +157,7 @@ "DEMO_MIME_TYPE": "MIME Type", "DEMO_MIN_BANDWIDTH": "Min Bandwidth", "DEMO_MIN_BYTES": "Min Bytes", + "DEMO_MIN_HDCP_VERSION": "Min HDCP version", "DEMO_MIN_FRAMERATE": "Min Framerate", "DEMO_MIN_HEIGHT": "Min Height", "DEMO_MIN_PIXELS": "Min Pixels", diff --git a/demo/locales/source.json b/demo/locales/source.json index 2a228c4220..9abcd780d5 100644 --- a/demo/locales/source.json +++ b/demo/locales/source.json @@ -631,6 +631,10 @@ "description": "The name of a configuration value.", "message": "Min Bytes" }, + "DEMO_MIN_HDCP_VERSION": { + "description": "The name of a configuration value.", + "message": "Min HDCP version" + }, "DEMO_MIN_FRAMERATE": { "description": "The name of a configuration value.", "message": "Min Framerate" diff --git a/externs/mediakeys.js b/externs/mediakeys.js new file mode 100644 index 0000000000..8d3b5df1d6 --- /dev/null +++ b/externs/mediakeys.js @@ -0,0 +1,18 @@ +/*! @license + * Shaka Player + * Copyright 2016 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Externs for MediaKeys which were missing in the + * Closure compiler. + * + * @externs + */ + +/** + * @param {Object} policy + * @return {!Promise.} + */ +MediaKeys.prototype.getStatusForPolicy = function(policy) {}; diff --git a/externs/shaka/player.js b/externs/shaka/player.js index dbb718065d..a7f41e501c 100644 --- a/externs/shaka/player.js +++ b/externs/shaka/player.js @@ -695,7 +695,8 @@ shaka.extern.AdvancedDrmConfiguration; * updateExpirationTime: number, * preferredKeySystems: !Array., * keySystemsMapping: !Object., - * parseInbandPsshEnabled: boolean + * parseInbandPsshEnabled: boolean, + * minHdcpVersion: string * }} * * @property {shaka.extern.RetryParameters} retryParameters @@ -743,6 +744,10 @@ shaka.extern.AdvancedDrmConfiguration; * When true parse DRM init data from pssh boxes in media and init segments * and ignore 'encrypted' events. * This is required when using in-band key rotation on Xbox One. + * @property {string} minHdcpVersion + * By default (''), do not check the HDCP version.
+ * Indicates the minimum version of HDCP to start the playback of encrypted + * streams. May be ignored if not supported by the device. * * @exportDoc */ diff --git a/lib/media/drm_engine.js b/lib/media/drm_engine.js index 6c21be5942..05971e08ac 100644 --- a/lib/media/drm_engine.js +++ b/lib/media/drm_engine.js @@ -924,6 +924,27 @@ shaka.media.DrmEngine = class { this.currentDrmInfo_.keySystem); this.mediaKeys_ = mediaKeys; + if (this.config_.minHdcpVersion != '' && + 'getStatusForPolicy' in this.mediaKeys_) { + try { + const status = await this.mediaKeys_.getStatusForPolicy({ + minHdcpVersion: this.config_.minHdcpVersion, + }); + if (status != 'usable') { + throw new shaka.util.Error( + shaka.util.Error.Severity.CRITICAL, + shaka.util.Error.Category.DRM, + shaka.util.Error.Code.MIN_HDCP_VERSION_NOT_MATCH); + } + this.destroyer_.ensureNotDestroyed(); + } catch (e) { + throw new shaka.util.Error( + shaka.util.Error.Severity.CRITICAL, + shaka.util.Error.Category.DRM, + shaka.util.Error.Code.ERROR_CHECKING_HDCP_VERSION, + e.message); + } + } this.initialized_ = true; await this.setServerCertificate(); diff --git a/lib/polyfill/patchedmediakeys_apple.js b/lib/polyfill/patchedmediakeys_apple.js index fc47d6ff5e..f0387a248f 100644 --- a/lib/polyfill/patchedmediakeys_apple.js +++ b/lib/polyfill/patchedmediakeys_apple.js @@ -457,6 +457,11 @@ shaka.polyfill.PatchedMediaKeysApple.MediaKeys = class { return Promise.reject(exception); } } + + /** @override */ + getStatusForPolicy(policy) { + return Promise.resolve('usable'); + } }; diff --git a/lib/polyfill/patchedmediakeys_nop.js b/lib/polyfill/patchedmediakeys_nop.js index 5ba9266c50..26957e60b6 100644 --- a/lib/polyfill/patchedmediakeys_nop.js +++ b/lib/polyfill/patchedmediakeys_nop.js @@ -108,6 +108,11 @@ shaka.polyfill.PatchedMediaKeysNop.MediaKeys = class { /** @override */ setServerCertificate() {} + + /** @override */ + getStatusForPolicy(policy) { + return Promise.resolve('usable'); + } }; diff --git a/lib/polyfill/patchedmediakeys_webkit.js b/lib/polyfill/patchedmediakeys_webkit.js index 4ec47e8ce2..904d0ff560 100644 --- a/lib/polyfill/patchedmediakeys_webkit.js +++ b/lib/polyfill/patchedmediakeys_webkit.js @@ -417,6 +417,11 @@ shaka.polyfill.PatchedMediaKeysWebkit.MediaKeys = class { return Promise.resolve(false); } + /** @override */ + getStatusForPolicy(policy) { + return Promise.resolve('usable'); + } + /** * @param {!MediaKeyEvent} event * @suppress {constantProperty} We reassign what would be const on a real diff --git a/lib/util/error.js b/lib/util/error.js index 19152361b5..243f5ab156 100644 --- a/lib/util/error.js +++ b/lib/util/error.js @@ -858,6 +858,17 @@ shaka.util.Error.Code = { */ 'SERVER_CERTIFICATE_REQUEST_FAILED': 6017, + /** + * The HDCP version does not meet the requirements. + */ + 'MIN_HDCP_VERSION_NOT_MATCH': 6018, + + /** + * Error when checking HDCP version. + *
error.data[0] is an error message string from the browser. + */ + 'ERROR_CHECKING_HDCP_VERSION': 6019, + /** * The call to Player.load() was interrupted by a call to Player.unload() diff --git a/lib/util/player_configuration.js b/lib/util/player_configuration.js index 2c8821da05..5c630f4a78 100644 --- a/lib/util/player_configuration.js +++ b/lib/util/player_configuration.js @@ -87,6 +87,7 @@ shaka.util.PlayerConfiguration = class { // change in the PSSH in media segments. We need to parse PSSH from media // segments to detect key changes. parseInbandPsshEnabled: shaka.util.Platform.isXboxOne(), + minHdcpVersion: '', }; const manifest = {