From 08d18a2b389f11fc52e69612cb9e49cd5368fa0e Mon Sep 17 00:00:00 2001 From: Joey Parrish Date: Thu, 19 Dec 2019 14:25:17 -0800 Subject: [PATCH] Add MediaCapabilities support and release v2.0.0 (#11) See https://github.com/w3c/media-capabilities/issues/100 The top-level export name now reflects the fact that there are two polyfills being installed. This is a breaking change, so we bump the version number to 2.0.0. Closes #1 --- .eslintrc.js | 3 + CHANGELOG.md | 7 + README.md | 21 +- closure-compiler-check/mediacapabilities.js | 207 ++++++++++++ demo/index.html | 12 +- demo/load-tests/load-as-es-module.html | 4 +- .../load-raw-source-with-script-tag.html | 4 +- demo/load-tests/load-with-script-tag.html | 4 +- demo/query.js | 62 +++- index.js | 306 +++++++++++++++--- package.json | 4 +- 11 files changed, 564 insertions(+), 70 deletions(-) create mode 100644 closure-compiler-check/mediacapabilities.js diff --git a/.eslintrc.js b/.eslintrc.js index c3c46b7b..59f859b5 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -53,6 +53,9 @@ module.exports = { { // These types are browser-provided, so trust that they exist. 'definedTypes': [ + 'MediaCapabilities', + 'MediaCapabilitiesDecodingInfo', + 'MediaDecodingConfiguration', 'MediaKeySystemConfiguration', 'MediaKeySystemMediaCapability', ], diff --git a/CHANGELOG.md b/CHANGELOG.md index 376fb0c4..9fbe4ba4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 2.0.0 (2019-12-12) + +Features: + - Added support for polyfilling MediaCapabilities, too + - https://github.com/w3c/media-capabilities/issues/100 + + ## 1.0.3 (2019-12-05) Bugfixes: diff --git a/README.md b/README.md index c9e6a76c..e589dd5c 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ -# EME Encryption Scheme Polyfill +# EME & MediaCapabilities Encryption Scheme Polyfill -A polyfill to add support for EncryptionScheme queries in EME. +A polyfill to add support for EncryptionScheme queries in EME and +MediaCapabilities. - https://wicg.github.io/encrypted-media-encryption-scheme/ - https://google.github.io/eme-encryption-scheme-polyfill/demo/ - https://github.com/WICG/encrypted-media-encryption-scheme/issues/13 + - https://github.com/w3c/media-capabilities/issues/100 Because this polyfill can't know what schemes the UA or CDM actually support, it assumes support for the historically-supported schemes of each well-known @@ -15,12 +17,12 @@ the CommonJS module format. It can also be directly included via a script tag. The minified bundle (`dist/eme-encryption-scheme-polyfill.js`) is a standalone module compatible with the CommonJS and AMD module formats, and can also be -directly included via a script tag. It is about 3.1kB uncompressed, and gzips -to about 1.2kB. +directly included via a script tag. It is about 4.4kB uncompressed, and gzips +to about 1.5kB. -To avoid the possibility of extra user prompts, this will shim EME so long as -it exists, without checking support for `encryptionScheme` upfront. The -support check will happen on-demand the first time EME is used. +To avoid the possibility of extra user prompts, this will shim EME & MC so long +as they exist, without checking support for `encryptionScheme` upfront. The +support check will happen on-demand the first time EME/MC are used. ## Usage @@ -34,5 +36,10 @@ npm install eme-encryption-scheme-polyfill ``` ```js +// Install both EME & MC polyfills at once: +EncryptionSchemePolyfills.install(); + +// Install each one separately (unminified source only): EmeEncryptionSchemePolyfill.install(); +McEncryptionSchemePolyfill.install(); ``` diff --git a/closure-compiler-check/mediacapabilities.js b/closure-compiler-check/mediacapabilities.js new file mode 100644 index 00000000..0da21d0e --- /dev/null +++ b/closure-compiler-check/mediacapabilities.js @@ -0,0 +1,207 @@ +/* + * @license + * Copyright 2019 The Closure Compiler authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @fileoverview MediaCapabilities externs. + * Based on {@link https://w3c.github.io/media-capabilities/ MC draft 6 November + * 2019}. + * @externs + */ + +/** + * @typedef {string} + * @see https://w3c.github.io/media-capabilities/#enumdef-hdrmetadatatype + */ +var HdrMetadataType; + +/** + * @typedef {string} + * @see https://w3c.github.io/media-capabilities/#enumdef-colorgamut + */ +var ColorGamut; + +/** + * @typedef {string} + * @see https://w3c.github.io/media-capabilities/#enumdef-transferfunction + */ +var TransferFunction; + +/** + * @typedef {string} + * @see https://w3c.github.io/media-capabilities/#enumdef-mediadecodingtype + */ +var MediaDecodingType; + +/** + * @typedef {string} + * @see https://w3c.github.io/media-capabilities/#enumdef-mediaencodingtype + */ +var MediaEncodingType; + +/** + * @typedef {{ + * contentType: string, + * width: number, + * height: number, + * bitrate: number, + * framerate: number, + * hasAlphaChannel: (boolean|undefined), + * hdrMetadataType: (!HdrMetadataType|undefined), + * colorGamut: (!ColorGamut|undefined), + * transferFunction: (!TransferFunction|undefined) + * }} + * @see https://w3c.github.io/media-capabilities/#dictdef-videoconfiguration + */ +var VideoConfiguration; + +// NOTE: channels definition below is not yet stable in the spec as of Dec 2019. +// "The channels needs to be defined as a double (2.1, 4.1, 5.1, ...), an +// unsigned short (number of channels) or as an enum value. The current +// definition is a placeholder." +/** + * @typedef {{ + * contentType: string, + * channels: (*|undefined), + * bitrate: (number|undefined), + * samplerate: (number|undefined), + * spatialRendering: (boolean|undefined) + * }} + * @see https://w3c.github.io/media-capabilities/#dictdef-audioconfiguration + */ +var AudioConfiguration; + +// NOTE: encryptionScheme is not yet in the MC spec as of Dec 2019, but has +// already landed in EME and should be in MC soon. +// https://github.com/w3c/media-capabilities/issues/100 +/** + * @typedef {{ + * robustness: (string|undefined), + * encryptionScheme: (string|undefined) + * }} + * @see https://w3c.github.io/media-capabilities/#dictdef-keysystemtrackconfiguration + */ +var KeySystemTrackConfiguration; + +/** + * @typedef {{ + * keySystem: string, + * initDataType: (string|undefined), + * distinctiveIdentifier: (string|undefined), + * persistentState: (string|undefined), + * sessionTypes: (!Array|undefined), + * audio: (!KeySystemTrackConfiguration|undefined), + * video: (!KeySystemTrackConfiguration|undefined) + * }} + * @see https://w3c.github.io/media-capabilities/#dictdef-mediacapabilitieskeysystemconfiguration + */ +var MediaCapabilitiesKeySystemConfiguration; + +/** + * @record + * @see https://w3c.github.io/media-capabilities/#dictdef-mediaconfiguration + */ +function MediaConfiguration() {} + +/** @type {!VideoConfiguration|undefined} */ +MediaConfiguration.prototype.video; + +/** @type {!AudioConfiguration|undefined} */ +MediaConfiguration.prototype.audio; + +/** + * @record + * @extends {MediaConfiguration} + * @see https://w3c.github.io/media-capabilities/#dictdef-mediadecodingconfiguration + */ +function MediaDecodingConfiguration() {} + +/** @type {MediaDecodingType} */ +MediaDecodingConfiguration.prototype.type; + +/** @type {!MediaCapabilitiesKeySystemConfiguration|undefined} */ +MediaDecodingConfiguration.prototype.keySystemConfiguration; + +/** + * @record + * @extends {MediaConfiguration} + * @see https://w3c.github.io/media-capabilities/#dictdef-mediaencodingconfiguration + */ +function MediaEncodingConfiguration() {} + +/** @type {MediaEncodingType} */ +MediaEncodingConfiguration.prototype.type; + +/** + * @record + * @see https://w3c.github.io/media-capabilities/#dictdef-mediacapabilitiesinfo + */ +function MediaCapabilitiesInfo() {} + +/** @type {boolean} */ +MediaCapabilitiesInfo.prototype.supported; + +/** @type {boolean} */ +MediaCapabilitiesInfo.prototype.smooth; + +/** @type {boolean} */ +MediaCapabilitiesInfo.prototype.powerEfficient; + +/** + * @record + * @extends {MediaCapabilitiesInfo} + * @see https://w3c.github.io/media-capabilities/#dictdef-mediacapabilitiesdecodinginfo + */ +function MediaCapabilitiesDecodingInfo() {} + +/** @type {?MediaKeySystemAccess} */ +MediaCapabilitiesDecodingInfo.prototype.keySystemAccess; + +/** @type {!MediaDecodingConfiguration} */ +MediaCapabilitiesDecodingInfo.prototype.configuration; + +/** + * @record + * @extends {MediaCapabilitiesInfo} + * @see https://w3c.github.io/media-capabilities/#dictdef-mediacapabilitiesencodinginfo + */ +function MediaCapabilitiesEncodingInfo() {} + +/** @type {!MediaEncodingConfiguration} */ +MediaCapabilitiesEncodingInfo.prototype.configuration; + +/** + * @interface + * @see https://w3c.github.io/media-capabilities/#mediacapabilities + */ +function MediaCapabilities() {} + +/** + * @param {!MediaDecodingConfiguration} configuration + * @return {!Promise} + */ +MediaCapabilities.prototype.decodingInfo = function(configuration) {}; + +/** + * @param {!MediaEncodingConfiguration} configuration + * @return {!Promise} + */ +MediaCapabilities.prototype.encodingInfo = function(configuration) {}; + +/** @const {?MediaCapabilities} */ +Navigator.prototype.mediaCapabilities; + +/** @const {?MediaCapabilities} */ +WorkerNavigator.prototype.mediaCapabilities; diff --git a/demo/index.html b/demo/index.html index bf020023..c5e2a50b 100644 --- a/demo/index.html +++ b/demo/index.html @@ -23,7 +23,9 @@ - + @@ -39,8 +41,8 @@

EME Encryption Scheme Polyfill Demo

Test query

Choose parameters like key system, encryption scheme, and media types, - then click the "run" button to see the results of the query with the - polyfill. + then click one of the "run" button to see the results of the query with + the polyfill.
@@ -85,7 +87,8 @@

Test query

- + +
@@ -93,7 +96,6 @@

Test query

-
diff --git a/demo/load-tests/load-as-es-module.html b/demo/load-tests/load-as-es-module.html index 332909f3..ab79e2b9 100644 --- a/demo/load-tests/load-as-es-module.html +++ b/demo/load-tests/load-as-es-module.html @@ -23,8 +23,8 @@ diff --git a/demo/load-tests/load-raw-source-with-script-tag.html b/demo/load-tests/load-raw-source-with-script-tag.html index 401f3a3e..6dcbe8e6 100644 --- a/demo/load-tests/load-raw-source-with-script-tag.html +++ b/demo/load-tests/load-raw-source-with-script-tag.html @@ -23,8 +23,8 @@ diff --git a/demo/load-tests/load-with-script-tag.html b/demo/load-tests/load-with-script-tag.html index a557c9c9..52476048 100644 --- a/demo/load-tests/load-with-script-tag.html +++ b/demo/load-tests/load-with-script-tag.html @@ -23,8 +23,8 @@ diff --git a/demo/query.js b/demo/query.js index 4b0766bc..393d521b 100644 --- a/demo/query.js +++ b/demo/query.js @@ -55,5 +55,65 @@ document.addEventListener('DOMContentLoaded', () => { } catch (error) { window.results.textContent = formatObjectToString({error: error.message}); } - }); // emeRunButton click listener + }); // emeRun click listener + + window.mcRun.addEventListener('click', async () => { + // Pull contents of query form. + const keySystem = window.keySystem.input.value; + // If encryptionScheme is blank, default to null. + const encryptionScheme = window.encryptionScheme.input.value || null; + const audio = window.audio.input.value; + const video = window.video.input.value; + + const config = { + type: 'media-source', + }; + + if (keySystem) { + config.keySystemConfiguration = { + keySystem, + }; + } + + if (audio) { + config.audio = { + contentType: audio, + }; + + if (keySystem) { + config.keySystemConfiguration.audio = { + encryptionScheme, + }; + } + } + + if (video) { + config.video = { + contentType: video, + width: 640, + height: 480, + bitrate: 1, + framerate: 24, + }; + + if (keySystem) { + config.keySystemConfiguration.video = { + encryptionScheme, + }; + } + } + + try { + const result = await navigator.mediaCapabilities.decodingInfo(config); + results.textContent = formatObjectToString(result); + + const mksa = result.keySystemAccess; + if (mksa) { + results.textContent += '\n' + + formatObjectToString(mksa.getConfiguration()); + } + } catch (error) { + results.textContent = formatObjectToString({error: error.message}); + } + }); // mcRun click listener }); // DOMContentLoaded listener diff --git a/index.js b/index.js index e6201175..f8fadff6 100644 --- a/index.js +++ b/index.js @@ -55,38 +55,6 @@ class EmeEncryptionSchemePolyfill { EmeEncryptionSchemePolyfill.probeRMKSA_; } - /** - * Guess the supported encryption scheme for the key system. - * - * @param {string} keySystem The key system ID. - * @return {?string} A guess at the encryption scheme this key system - * supports. - * @private - */ - static guessSupportedScheme_(keySystem) { - if (keySystem.startsWith('com.widevine')) { - return 'cenc'; - } else if (keySystem.startsWith('com.microsoft')) { - return 'cenc'; - } else if (keySystem.startsWith('com.adobe')) { - return 'cenc'; - } else if (keySystem.startsWith('org.w3')) { - return 'cenc'; - } else if (keySystem.startsWith('com.apple')) { - return 'cbcs-1-9'; - } - - // We don't have this key system in our map! - - // Log a warning. The only way the request will succeed now is if the - // app doesn't specify an encryption scheme in their own configs. - // Use bracket notation to keep this from being stripped from the build. - console['warn']('EmeEncryptionSchemePolyfill: Unknown key system:', - keySystem, 'Please contribute!'); - - return null; - } - /** * A shim for navigator.requestMediaKeySystemAccess to check for * encryptionScheme support. Only used until we know if the browser has @@ -110,20 +78,7 @@ class EmeEncryptionSchemePolyfill { await EmeEncryptionSchemePolyfill.originalRMKSA_.call( this, keySystem, supportedConfigurations); - const configuration = mediaKeySystemAccess.getConfiguration(); - - // It doesn't matter which capability we look at. For this check, they - // should all produce the same result. - const firstVideoCapability = - configuration.videoCapabilities && configuration.videoCapabilities[0]; - const firstAudioCapability = - configuration.audioCapabilities && configuration.audioCapabilities[0]; - const firstCapability = firstVideoCapability || firstAudioCapability; - - // If supported by the browser, the encryptionScheme field must appear in - // the returned configuration, regardless of whether or not it was - // specified in the supportedConfigurations given by the application. - if (firstCapability['encryptionScheme'] !== undefined) { + if (hasEncryptionScheme(mediaKeySystemAccess)) { // The browser supports the encryptionScheme field! // No need for a patch. Revert back to the original implementation. console.debug('EmeEncryptionSchemePolyfill: ' + @@ -170,8 +125,7 @@ class EmeEncryptionSchemePolyfill { console.assert(this == navigator, 'bad "this" for requestMediaKeySystemAccess'); - const supportedScheme = EmeEncryptionSchemePolyfill.guessSupportedScheme_( - keySystem); + const supportedScheme = guessSupportedScheme(keySystem); // Filter the application's configurations based on our guess of what // encryption scheme is supported. @@ -256,6 +210,175 @@ class EmeEncryptionSchemePolyfill { } } +/** + * A polyfill to add support for EncryptionScheme queries in MediaCapabilities. + * + * Because this polyfill can't know what schemes the UA or CDM actually support, + * it assumes support for the historically-supported schemes of each well-known + * key system. + * + * In source form, this is compatible with the Closure Compiler, CommonJS, and + * AMD module formats. It can also be directly included via a script tag. + * + * The minified bundle is a standalone module compatible with the CommonJS and + * AMD module formats, and can also be directly included via a script tag. + * + * @see https://wicg.github.io/encrypted-media-encryption-scheme/ + * @see https://github.com/w3c/encrypted-media/pull/457 + * @export + */ +class McEncryptionSchemePolyfill { + /** + * Installs the polyfill. To avoid the possibility of extra user prompts, + * this will shim MC so long as it exists, without checking support for + * encryptionScheme upfront. The support check will happen on-demand the + * first time MC is used. + * + * @export + */ + static install() { + if (!navigator.mediaCapabilities) { + console.debug('McEncryptionSchemePolyfill: MediaCapabilities not found'); + // No MediaCapabilities. + return; + } + + // Save the original. + McEncryptionSchemePolyfill.originalDecodingInfo_ = + navigator.mediaCapabilities.decodingInfo; + + // Patch in a method which will check for support on the first call. + console.debug('McEncryptionSchemePolyfill: ' + + 'Waiting to detect encryptionScheme support.'); + navigator.mediaCapabilities.decodingInfo = + McEncryptionSchemePolyfill.probeDecodingInfo_; + } + + /** + * A shim for mediaCapabilities.decodingInfo to check for encryptionScheme + * support. Only used until we know if the browser has native support for the + * encryptionScheme field. + * + * @this {MediaCapabilities} + * @param {!MediaDecodingConfiguration} requestedConfiguration The requested + * decoding configuration. + * @return {!Promise.} A Promise to a result + * describing the capabilities of the browser in the request configuration. + * @private + */ + static async probeDecodingInfo_(requestedConfiguration) { + console.assert(this == navigator.mediaCapabilities, + 'bad "this" for decodingInfo'); + + // Call the original version. If the call succeeds, we look at the result + // to decide if the encryptionScheme field is supported or not. + const capabilities = + await McEncryptionSchemePolyfill.originalDecodingInfo_.call( + this, requestedConfiguration); + + if (!requestedConfiguration.keySystemConfiguration) { + // This was not a query regarding encrypted content. The results are + // valid, but won't tell us anything about native support for + // encryptionScheme. Just return the results. + return capabilities; + } + + const mediaKeySystemAccess = capabilities.keySystemAccess; + + if (hasEncryptionScheme(mediaKeySystemAccess)) { + // The browser supports the encryptionScheme field! + // No need for a patch. Revert back to the original implementation. + console.debug('McEncryptionSchemePolyfill: ' + + 'Native encryptionScheme support found.'); + // eslint-disable-next-line require-atomic-updates + navigator.mediaCapabilities.decodingInfo = + McEncryptionSchemePolyfill.originalDecodingInfo_; + // Return the results, which are completely valid. + return capabilities; + } + + // If we land here, the browser does _not_ support the encryptionScheme + // field. So we install another patch to check the encryptionScheme field + // in future calls. + console.debug('McEncryptionSchemePolyfill: ' + + 'No native encryptionScheme support found. '+ + 'Patching encryptionScheme support.'); + // eslint-disable-next-line require-atomic-updates + navigator.mediaCapabilities.decodingInfo = + McEncryptionSchemePolyfill.polyfillDecodingInfo_; + + // The results we have may not be valid. Run the query again through our + // polyfill. + return McEncryptionSchemePolyfill.polyfillDecodingInfo_.call( + this, requestedConfiguration); + } + + /** + * A polyfill for mediaCapabilities.decodingInfo to handle the + * encryptionScheme field in browsers that don't support it. It uses the + * user-agent string to guess what encryption schemes are supported, then + * those guesses are used to reject unsupported schemes. + * + * @this {MediaCapabilities} + * @param {!MediaDecodingConfiguration} requestedConfiguration The requested + * decoding configuration. + * @return {!Promise.} A Promise to a result + * describing the capabilities of the browser in the request configuration. + * @private + */ + static async polyfillDecodingInfo_(requestedConfiguration) { + console.assert(this == navigator.mediaCapabilities, + 'bad "this" for decodingInfo'); + + let supportedScheme = null; + + if (requestedConfiguration.keySystemConfiguration) { + const keySystemConfig = requestedConfiguration.keySystemConfiguration; + + const keySystem = keySystemConfig.keySystem; + + const audioScheme = keySystemConfig.audio && + keySystemConfig.audio.encryptionScheme; + const videoScheme = keySystemConfig.video && + keySystemConfig.video.encryptionScheme; + + supportedScheme = guessSupportedScheme(keySystem); + + const notSupportedResult = { + powerEfficient: false, + smooth: false, + supported: false, + keySystemAccess: null, + configuration: requestedConfiguration, + }; + + if (audioScheme && audioScheme != supportedScheme) { + return notSupportedResult; + } + if (videoScheme && videoScheme != supportedScheme) { + return notSupportedResult; + } + } + + // At this point, either it's unencrypted or we assume the encryption scheme + // is supported. So delegate to the original decodingInfo() method. + const capabilities = + await McEncryptionSchemePolyfill.originalDecodingInfo_.call( + this, requestedConfiguration); + + if (capabilities.keySystemAccess) { + // If the result is supported and encrypted, this will be a + // MediaKeySystemAccess instance. Wrap the MKSA object in ours to provide + // the missing field in the returned configuration. + capabilities.keySystemAccess = + new EmeEncryptionSchemePolyfillMediaKeySystemAccess( + capabilities.keySystemAccess, supportedScheme); + } + + return capabilities; + } +} + /** * A wrapper around MediaKeySystemAccess that adds encryptionScheme * fields to the configuration, to emulate what a browser with native support @@ -315,6 +438,62 @@ class EmeEncryptionSchemePolyfillMediaKeySystemAccess { } } +/** + * Guess the supported encryption scheme for the key system. + * + * @param {string} keySystem The key system ID. + * @return {?string} A guess at the encryption scheme this key system + * supports. + */ +function guessSupportedScheme(keySystem) { + if (keySystem.startsWith('com.widevine')) { + return 'cenc'; + } else if (keySystem.startsWith('com.microsoft')) { + return 'cenc'; + } else if (keySystem.startsWith('com.adobe')) { + return 'cenc'; + } else if (keySystem.startsWith('org.w3')) { + return 'cenc'; + } else if (keySystem.startsWith('com.apple')) { + return 'cbcs-1-9'; + } + + // We don't have this key system in our map! + + // Log a warning. The only way the request will succeed now is if the + // app doesn't specify an encryption scheme in their own configs. + // Use bracket notation to keep this from being stripped from the build. + console['warn']('EmeEncryptionSchemePolyfill: Unknown key system:', + keySystem, 'Please contribute!'); + + return null; +} + +/** + * @param {?MediaKeySystemAccess} mediaKeySystemAccess A native + * MediaKeySystemAccess instance from the browser. + * @return {boolean} True if browser natively supports encryptionScheme. + */ +function hasEncryptionScheme(mediaKeySystemAccess) { + const configuration = mediaKeySystemAccess.getConfiguration(); + + // It doesn't matter which capability we look at. For this check, they + // should all produce the same result. + const firstVideoCapability = + configuration.videoCapabilities && configuration.videoCapabilities[0]; + const firstAudioCapability = + configuration.audioCapabilities && configuration.audioCapabilities[0]; + const firstCapability = firstVideoCapability || firstAudioCapability; + + // If supported by the browser, the encryptionScheme field must appear in + // the returned configuration, regardless of whether or not it was + // specified in the supportedConfigurations given by the application. + if (firstCapability['encryptionScheme'] !== undefined) { + return true; + } + return false; +} + /** * The original requestMediaKeySystemAccess, before we patched it. * @@ -328,10 +507,39 @@ class EmeEncryptionSchemePolyfillMediaKeySystemAccess { */ EmeEncryptionSchemePolyfill.originalRMKSA_; +/** + * The original decodingInfo, before we patched it. + * + * @type { + * function(this:MediaCapabilities, + * !MediaDecodingConfiguration + * ):!Promise. + * } + * @private + */ +McEncryptionSchemePolyfill.originalDecodingInfo_; + +/** + * A single entry point for both polyfills (EME & MC). + * + * @export + */ +class EncryptionSchemePolyfills { + /** + * Installs both polyfills (EME & MC). + * + * @export + */ + static install() { + EmeEncryptionSchemePolyfill.install(); + McEncryptionSchemePolyfill.install(); + } +} + // Support for CommonJS and AMD module formats. /** @suppress {undefinedVars} */ (() => { if (typeof module !== 'undefined' && module.exports) { - module.exports = EmeEncryptionSchemePolyfill; + module.exports = EncryptionSchemePolyfills; } })(); diff --git a/package.json b/package.json index 517a3114..19fe1426 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "eme-encryption-scheme-polyfill", "description": "A polyfill for the encryptionScheme field in EME", - "version": "1.0.3", + "version": "2.0.0", "license": "Apache-2.0", "author": "Google", "homepage": "https://github.com/google/eme-encryption-scheme-polyfill#readme", @@ -17,7 +17,7 @@ "scripts": { "lint": "eslint index.js", "closure-compiler-check": "google-closure-compiler -O ADVANCED --generate_exports --js_output_file /dev/null --jscomp_error '*' closure-compiler-check/* index.js", - "build": "browserify index.js -s EmeEncryptionSchemePolyfill -t babelify -t stripify -p tinyify -p browserify-header -o dist/eme-encryption-scheme-polyfill.js", + "build": "browserify index.js -s EncryptionSchemePolyfills -t babelify -t stripify -p tinyify -p browserify-header -o dist/eme-encryption-scheme-polyfill.js", "prepublishOnly": "npm run-script lint && npm run-script closure-compiler-check && npm run-script build" }, "devDependencies": {