Skip to content

Commit

Permalink
fix: Prevent exception when PlayReady CDM returns UTF-8 unwrapped mes…
Browse files Browse the repository at this point in the history
…sage (#3926)
  • Loading branch information
vodlogic committed Apr 20, 2022
1 parent ad1ba6c commit 4caf828
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 5 deletions.
10 changes: 8 additions & 2 deletions src/core/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ import Events from './events/Events';
* useSuggestedPresentationDelay: true
* },
* protection: {
* keepProtectionMediaKeys: false
* keepProtectionMediaKeys: false,
* ignoreEmeEncryptedEvent: false,
* detectPlayreadyMessageFormat: true,
* },
* buffer: {
* enableSeekDecorrelationFix: true,
Expand Down Expand Up @@ -513,6 +515,9 @@ import Events from './events/Events';
* If true, the ProtectionController and then created MediaKeys and MediaKeySessions will be preserved during the MediaPlayer lifetime.
* @property {boolean} ignoreEmeEncryptedEvent
* If set to true the player will ignore "encrypted" and "needkey" events thrown by the EME.
*
* @property {boolean} detectPlayreadyMessageFormat
* If set to true the player will use the raw unwrapped message from the Playready CDM
*/

/**
Expand Down Expand Up @@ -775,7 +780,8 @@ function Settings() {
},
protection: {
keepProtectionMediaKeys: false,
ignoreEmeEncryptedEvent: false
ignoreEmeEncryptedEvent: false,
detectPlayreadyMessageFormat: true,
},
buffer: {
enableSeekDecorrelationFix: false,
Expand Down
2 changes: 1 addition & 1 deletion src/streaming/protection/Protection.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ function Protection() {
let controller = null;

const protectionKeyController = ProtectionKeyController(context).getInstance();
protectionKeyController.setConfig({ debug: config.debug, BASE64: config.BASE64 });
protectionKeyController.setConfig({ debug: config.debug, BASE64: config.BASE64, settings: config.settings });
protectionKeyController.initialize();

let protectionModel = _getProtectionModel(config);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ function ProtectionKeyController() {
logger,
keySystems,
BASE64,
settings,
clearkeyKeySystem,
clearkeyW3CKeySystem;

Expand All @@ -67,6 +68,10 @@ function ProtectionKeyController() {
if (config.BASE64) {
BASE64 = config.BASE64;
}

if(config.settings) {
settings = config.settings
}
}

function initialize() {
Expand All @@ -75,7 +80,7 @@ function ProtectionKeyController() {
let keySystem;

// PlayReady
keySystem = KeySystemPlayReady(context).getInstance({BASE64: BASE64});
keySystem = KeySystemPlayReady(context).getInstance({BASE64: BASE64, settings: settings});
keySystems.push(keySystem);

// Widevine
Expand Down
18 changes: 18 additions & 0 deletions src/streaming/protection/drm/KeySystemPlayReady.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function KeySystemPlayReady(config) {
let instance;
let messageFormat = 'utf-16';
const BASE64 = config.BASE64;
const settings = config.settings;

function checkConfig() {
if (!BASE64 || !BASE64.hasOwnProperty('decodeArray') || !BASE64.hasOwnProperty('decodeArray') ) {
Expand All @@ -61,6 +62,15 @@ function KeySystemPlayReady(config) {
xmlDoc;
const headers = {};
const parser = new DOMParser();

if (settings && settings.get().streaming.protection.detectPlayreadyMessageFormat) {
// If message format configured/defaulted to utf-16 AND number of bytes is odd, assume 'unwrapped' raw CDM message.
if (messageFormat === 'utf-16' && message && message.byteLength % 2 === 1) {
headers['Content-Type'] = 'text/xml; charset=utf-8';
return headers;
}
}

const dataview = (messageFormat === 'utf-16') ? new Uint16Array(message) : new Uint8Array(message);

msg = String.fromCharCode.apply(null, dataview);
Expand Down Expand Up @@ -89,6 +99,14 @@ function KeySystemPlayReady(config) {
function getLicenseRequestFromMessage(message) {
let licenseRequest = null;
const parser = new DOMParser();

if (settings && settings.get().streaming.protection.detectPlayreadyMessageFormat) {
// If message format configured/defaulted to utf-16 AND number of bytes is odd, assume 'unwrapped' raw CDM message.
if (messageFormat === 'utf-16' && message && message.byteLength % 2 === 1) {
return message;
}
}

const dataview = (messageFormat === 'utf-16') ? new Uint16Array(message) : new Uint8Array(message);

checkConfig();
Expand Down
7 changes: 6 additions & 1 deletion test/unit/streaming.protection.drm.KeySystemPlayReady.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import KeySystemPlayReady from '../../src/streaming/protection/drm/KeySystemPlayReady.js';
import BASE64 from '../../externals/base64';
import Settings from "../../src/core/Settings";

const expect = require('chai').expect;
const jsdom = require('jsdom').JSDOM;

describe('KeySystemPlayready', function () {


let context = {};
let settings = Settings(context).getInstance();
let keySystem,
DOMParser;
let cdmData = null;



const protData = {
cdmData: '2lfuDn3JoEo0dM324cA5tSv1gNNw65mgysBqNJqtxGUk7ShUOE03N6LK0cryu2roCQtDghmF7cC6xyt1WTA86CmrUNFRjo1tcxQtTVEW9Xw68pH7/yU2GbtK4zbctx49sffi4fYy8fGEUB5079CesBONxoKli5j2ADM8CWz93a5mYegZWraOq3EH0nvwvRXZ'
};
Expand Down Expand Up @@ -50,7 +55,7 @@ describe('KeySystemPlayready', function () {

describe('Well initialized', () => {
beforeEach(function () {
keySystem = KeySystemPlayReady(context).getInstance({BASE64: BASE64});
keySystem = KeySystemPlayReady(context).getInstance({BASE64: BASE64, settings: settings});
if (typeof DOMParser === 'undefined') {
global.DOMParser = new jsdom().window.DOMParser;
}
Expand Down

0 comments on commit 4caf828

Please sign in to comment.