Skip to content

Commit

Permalink
Fix PlayReady DRM in Edge browser
Browse files Browse the repository at this point in the history
  • Loading branch information
Jernej Fijačko committed Aug 16, 2023
1 parent a983d0f commit 580659a
Showing 1 changed file with 52 additions and 0 deletions.
52 changes: 52 additions & 0 deletions src/controller/eme-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,52 @@ class EMEController implements ComponentAPI {
);
}

private unpackPlayReadyKeyMessage(
xhr: XMLHttpRequest,
licenseChallenge: Uint8Array
): Uint8Array {
// On Edge, the raw license message is UTF-16-encoded XML. We need
// to unpack the Challenge element (base64-encoded string containing the
// actual license request) and any HttpHeader elements (sent as request
// headers).
// For PlayReady CDMs, we need to dig the Challenge out of the XML.
const xmlString = String.fromCharCode.apply(
null,
new Uint16Array(licenseChallenge.buffer)
);
if (!xmlString.includes('PlayReadyKeyMessage')) {
// This does not appear to be a wrapped message as on Edge. Some
// clients do not need this unwrapping, so we will assume this is one of
// them. Note that "xml" at this point probably looks like random
// garbage, since we interpreted UTF-8 as UTF-16.
xhr.setRequestHeader('Content-Type', 'text/xml; charset=utf-8');
return licenseChallenge;
}
const keyMessageXml = new DOMParser().parseFromString(
xmlString,
'application/xml'
);
// Set request headers.
const headers = keyMessageXml.querySelectorAll('HttpHeader');
if (headers.length > 0) {
let header: Element;
for (let i = 0, len = headers.length; i < len; i++) {
header = headers[i];
const name = header.querySelector('name')?.textContent;
const value = header.querySelector('value')?.textContent;
if (name && value) {
xhr.setRequestHeader(name, value);
}
}
}
const challengeElement = keyMessageXml.querySelector('Challenge');
const challengeText = challengeElement?.textContent;
if (!challengeText) {
throw new Error(`Cannot find <Challenge> in key message`);
}
return strToUtf8array(atob(challengeText));
}

private setupLicenseXHR(
xhr: XMLHttpRequest,
url: string,
Expand Down Expand Up @@ -1117,6 +1163,12 @@ class EMEController implements ComponentAPI {

this.setupLicenseXHR(xhr, url, keySessionContext, licenseChallenge).then(
({ xhr, licenseChallenge }) => {
if (keySessionContext.keySystem == KeySystems.PLAYREADY) {
licenseChallenge = this.unpackPlayReadyKeyMessage(
xhr,
licenseChallenge
);
}
xhr.send(licenseChallenge);
}
);
Expand Down

0 comments on commit 580659a

Please sign in to comment.