Skip to content

Commit

Permalink
Fix non-default namespace names in DASH.
Browse files Browse the repository at this point in the history
XML allows namespace names to be any string.  So instead of looking
for the literal name 'cenc:pssh', we should be looking for the 'pssh'
name in the correct namespace.

Backported to v2.3.x

Closes #1438

Change-Id: I724db3b7f0e60b4233b0fc40b1ed57698c6ce9ce
  • Loading branch information
TheModMaker authored and joeyparrish committed May 22, 2018
1 parent ac40eec commit 444127f
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 17 deletions.
12 changes: 10 additions & 2 deletions lib/dash/content_protection.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ shaka.dash.ContentProtection.MP4Protection_ =
'urn:mpeg:dash:mp4protection:2011';


/**
* @const {string}
* @private
*/
shaka.dash.ContentProtection.CencNamespaceUri = 'urn:mpeg:cenc:2013';


/**
* Parses info from the ContentProtection elements at the AdaptationSet level.
*
Expand Down Expand Up @@ -302,12 +309,13 @@ shaka.dash.ContentProtection.parseElements_ = function(elems) {
* @return {?shaka.dash.ContentProtection.Element}
*/
function(elem) {
const NS = shaka.dash.ContentProtection.CencNamespaceUri;
/** @type {?string} */
var schemeUri = elem.getAttribute('schemeIdUri');
/** @type {?string} */
var keyId = elem.getAttribute('cenc:default_KID');
let keyId = shaka.util.XmlUtils.getAttributeNS(elem, NS, 'default_KID');
/** @type {!Array.<string>} */
var psshs = shaka.util.XmlUtils.findChildren(elem, 'cenc:pssh')
let psshs = shaka.util.XmlUtils.findChildrenNS(elem, NS, 'pssh')
.map(shaka.util.XmlUtils.getContents);

if (!schemeUri) {
Expand Down
43 changes: 28 additions & 15 deletions lib/dash/mpd_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,14 @@ shaka.dash.MpdUtils.SegmentInfo;


/**
* Fills a SegmentTemplate URI template. This function does not validate the
* @const {string}
* @private
*/
shaka.dash.MpdUtils.XlinkNamespaceUri = 'http://www.w3.org/1999/xlink';


/**
* Fills a SegmentTemplate URI template. This function does not validate the
* resulting URI.
*
* @param {string} uriTemplate
Expand Down Expand Up @@ -468,19 +475,22 @@ shaka.dash.MpdUtils.parseXml = function(data, expectedRootElemName) {
shaka.dash.MpdUtils.handleXlinkInElement_ =
function(element, retryParameters, failGracefully, baseUri,
networkingEngine, linkDepth) {
var MpdUtils = shaka.dash.MpdUtils;
var Error = shaka.util.Error;
var ManifestParserUtils = shaka.util.ManifestParserUtils;
const MpdUtils = shaka.dash.MpdUtils;
const XmlUtils = shaka.util.XmlUtils;
const Error = shaka.util.Error;
const ManifestParserUtils = shaka.util.ManifestParserUtils;
const NS = MpdUtils.XlinkNamespaceUri;

var xlinkHref = element.getAttribute('xlink:href');
var xlinkActuate = element.getAttribute('xlink:actuate') || 'onRequest';
let xlinkHref = XmlUtils.getAttributeNS(element, NS, 'href');
let xlinkActuate =
XmlUtils.getAttributeNS(element, NS, 'actuate') || 'onRequest';

// Remove the xlink properties, so it won't download again
// when re-processed.
for (var i = 0; i < element.attributes.length; i++) {
var attribute = element.attributes[i].nodeName;
if (attribute.indexOf('xlink:') != -1) {
element.removeAttribute(attribute);
for (let i = 0; i < element.attributes.length; i++) {
let attribute = element.attributes[i];
if (attribute.namespaceURI == NS) {
element.removeAttributeNS(attribute.namespaceURI, attribute.localName);
i -= 1;
}
}
Expand Down Expand Up @@ -561,11 +571,14 @@ shaka.dash.MpdUtils.handleXlinkInElement_ =
shaka.dash.MpdUtils.processXlinks =
function(element, retryParameters, failGracefully, baseUri,
networkingEngine, opt_linkDepth) {
var MpdUtils = shaka.dash.MpdUtils;
const MpdUtils = shaka.dash.MpdUtils;
const XmlUtils = shaka.util.XmlUtils;
const NS = MpdUtils.XlinkNamespaceUri;

opt_linkDepth = opt_linkDepth || 0;

if (element.getAttribute('xlink:href')) {
var handled = MpdUtils.handleXlinkInElement_(
if (XmlUtils.getAttributeNS(element, NS, 'href')) {
let handled = MpdUtils.handleXlinkInElement_(
element, retryParameters, failGracefully, baseUri,
networkingEngine, opt_linkDepth);
if (failGracefully) {
Expand All @@ -586,8 +599,8 @@ shaka.dash.MpdUtils.processXlinks =
for (var i = 0; i < element.childNodes.length; i++) {
var child = element.childNodes[i];
if (child instanceof Element) {
var resolveToZeroString = 'urn:mpeg:dash:resolve-to-zero:2013';
if (child.getAttribute('xlink:href') == resolveToZeroString) {
const resolveToZeroString = 'urn:mpeg:dash:resolve-to-zero:2013';
if (XmlUtils.getAttributeNS(child, NS, 'href') == resolveToZeroString) {
// This is a 'resolve to zero' code; it means the element should
// be removed, as specified by the mpeg-dash rules for xlink.
element.removeChild(child);
Expand Down
29 changes: 29 additions & 0 deletions lib/util/xml_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,35 @@ shaka.util.XmlUtils.findChildren = function(elem, name) {
};


/**
* Finds namespace-qualified child XML elements.
* @param {!Node} elem The parent XML element.
* @param {string} ns The child XML element's namespace URI.
* @param {string} name The child XML element's local name.
* @return {!Array.<!Element>} The child XML elements.
*/
shaka.util.XmlUtils.findChildrenNS = function(elem, ns, name) {
return Array.prototype.filter.call(elem.childNodes, function(child) {
return child instanceof Element && child.localName == name &&
child.namespaceURI == ns;
});
};


/**
* Gets a namespace-qualified attribute.
* @param {!Element} elem The element to get from.
* @param {string} ns The namespace URI.
* @param {string} name The local name of the attribute.
* @return {?string} The attribute's value, or null if not present.
*/
shaka.util.XmlUtils.getAttributeNS = function(elem, ns, name) {
// Some browsers return the empty string when the attribute is missing,
// so check if it exists first. See: https://mzl.la/2L7F0UK
return elem.hasAttributeNS(ns, name) ? elem.getAttributeNS(ns, name) : null;
};


/**
* Gets the text contents of a node.
* @param {!Node} elem The XML element.
Expand Down
22 changes: 22 additions & 0 deletions test/dash/dash_parser_content_protection_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,28 @@ describe('DashParser ContentProtection', function() {
testDashParser(done, source, expected);
});

it('handles non-default namespace names', function(done) {
let source = [
'<MPD xmlns="urn:mpeg:DASH:schema:MPD:2011"',
' xmlns:foo="urn:mpeg:cenc:2013">',
' <Period duration="PT30S">',
' <SegmentTemplate media="s.mp4" duration="2" />',
' <AdaptationSet mimeType="video/mp4" codecs="avc1.4d401f">',
' <ContentProtection',
' schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">',
' <foo:pssh>b25lIGhlYWRlciB0byBydWxlIHRoZW0gYWxs</foo:pssh>',
' </ContentProtection>',
' <Representation bandwidth="50" width="576" height="432" />',
' <Representation bandwidth="100" width="576" height="432" />',
' </AdaptationSet>',
' </Period>',
'</MPD>'
].join('\n');
let expected = buildExpectedManifest([buildDrmInfo(
'com.widevine.alpha', [], ['b25lIGhlYWRlciB0byBydWxlIHRoZW0gYWxs'])]);
testDashParser(done, source, expected);
});

it('fails for no schemes common', function(done) {
var source = buildManifestText([
// AdaptationSet lines
Expand Down

0 comments on commit 444127f

Please sign in to comment.