Source: lib/mss/content_protection.js

  1. /*! @license
  2. * Shaka Player
  3. * Copyright 2016 Google LLC
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. goog.provide('shaka.mss.ContentProtection');
  7. goog.require('shaka.drm.PlayReady');
  8. goog.require('shaka.util.ManifestParserUtils');
  9. goog.require('shaka.util.Pssh');
  10. goog.require('shaka.util.TXml');
  11. goog.require('shaka.util.Uint8ArrayUtils');
  12. /**
  13. * @summary A set of functions for parsing and interpreting Protection
  14. * elements.
  15. */
  16. shaka.mss.ContentProtection = class {
  17. /**
  18. * Parses info from the Protection elements.
  19. *
  20. * @param {!Array<!shaka.extern.xml.Node>} elements
  21. * @param {!Object<string, string>} keySystemsBySystemId
  22. * @return {!Array<shaka.extern.DrmInfo>}
  23. */
  24. static parseFromProtection(elements, keySystemsBySystemId) {
  25. const ContentProtection = shaka.mss.ContentProtection;
  26. const TXml = shaka.util.TXml;
  27. /** @type {!Array<!shaka.extern.xml.Node>} */
  28. let protectionHeader = [];
  29. for (const element of elements) {
  30. protectionHeader = protectionHeader.concat(
  31. TXml.findChildren(element, 'ProtectionHeader'));
  32. }
  33. if (!protectionHeader.length) {
  34. return [];
  35. }
  36. return ContentProtection.convertElements_(
  37. protectionHeader, keySystemsBySystemId);
  38. }
  39. /**
  40. * Gets a PlayReady license URL from a protection element
  41. * containing a PlayReady Header Object
  42. *
  43. * @param {!shaka.extern.xml.Node} element
  44. * @return {string}
  45. */
  46. static getPlayReadyLicenseUrl(element) {
  47. return shaka.drm.PlayReady.getLicenseUrl(element);
  48. }
  49. /**
  50. * Gets a PlayReady KID from a protection element
  51. * containing a PlayReady Header Object
  52. *
  53. * @param {!shaka.extern.xml.Node} element
  54. * @return {?string}
  55. * @private
  56. */
  57. static getPlayReadyKID_(element) {
  58. return shaka.drm.PlayReady.getPlayReadyKID(element);
  59. }
  60. /**
  61. * Gets a initData from a protection element.
  62. *
  63. * @param {!shaka.extern.xml.Node} element
  64. * @param {string} systemID
  65. * @param {?string} keyId
  66. * @return {?Array<shaka.extern.InitDataOverride>}
  67. * @private
  68. */
  69. static getInitDataFromPro_(element, systemID, keyId) {
  70. const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;
  71. const data = Uint8ArrayUtils.fromBase64(
  72. /** @type {string} */ (shaka.util.TXml.getTextContents(element)));
  73. const systemId = Uint8ArrayUtils.fromHex(systemID.replace(/-/g, ''));
  74. const keyIds = new Set();
  75. const psshVersion = 0;
  76. const pssh =
  77. shaka.util.Pssh.createPssh(data, systemId, keyIds, psshVersion);
  78. return [
  79. {
  80. initData: pssh,
  81. initDataType: 'cenc',
  82. keyId: keyId,
  83. },
  84. ];
  85. }
  86. /**
  87. * Creates DrmInfo objects from an array of elements.
  88. *
  89. * @param {!Array<!shaka.extern.xml.Node>} elements
  90. * @param {!Object<string, string>} keySystemsBySystemId
  91. * @return {!Array<shaka.extern.DrmInfo>}
  92. * @private
  93. */
  94. static convertElements_(elements, keySystemsBySystemId) {
  95. const ContentProtection = shaka.mss.ContentProtection;
  96. const ManifestParserUtils = shaka.util.ManifestParserUtils;
  97. const licenseUrlParsers = ContentProtection.licenseUrlParsers_;
  98. /** @type {!Array<shaka.extern.DrmInfo>} */
  99. const out = [];
  100. for (let i = 0; i < elements.length; i++) {
  101. const element = elements[i];
  102. const systemID = element.attributes['SystemID'].toLowerCase();
  103. const keySystem = keySystemsBySystemId[systemID];
  104. if (keySystem) {
  105. const KID = ContentProtection.getPlayReadyKID_(element);
  106. const initData = ContentProtection.getInitDataFromPro_(
  107. element, systemID, KID);
  108. const info = ManifestParserUtils.createDrmInfo(
  109. keySystem, /* encryptionScheme= */ 'cenc', initData);
  110. if (KID) {
  111. info.keyIds.add(KID);
  112. }
  113. const licenseParser = licenseUrlParsers.get(keySystem);
  114. if (licenseParser) {
  115. info.licenseServerUri = licenseParser(element);
  116. }
  117. out.push(info);
  118. }
  119. }
  120. return out;
  121. }
  122. };
  123. /**
  124. * A map of key system name to license server url parser.
  125. *
  126. * @const {!Map<string, function(!shaka.extern.xml.Node)>}
  127. * @private
  128. */
  129. shaka.mss.ContentProtection.licenseUrlParsers_ = new Map()
  130. .set('com.microsoft.playready',
  131. shaka.mss.ContentProtection.getPlayReadyLicenseUrl)
  132. .set('com.microsoft.playready.recommendation',
  133. shaka.mss.ContentProtection.getPlayReadyLicenseUrl)
  134. .set('com.microsoft.playready.software',
  135. shaka.mss.ContentProtection.getPlayReadyLicenseUrl)
  136. .set('com.microsoft.playready.hardware',
  137. shaka.mss.ContentProtection.getPlayReadyLicenseUrl);