diff --git a/package-lock.json b/package-lock.json
index b81bdde..652f803 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -306,9 +306,9 @@
}
},
"@babel/parser": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.2.3.tgz",
- "integrity": "sha512-0LyEcVlfCoFmci8mXx8A5oIkpkOgyo8dRHtxBnK9RRBwxO2+JZPNsqtVEZQ7mJFPxnXF9lfmU24mHOPI0qnlkA==",
+ "version": "7.16.12",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz",
+ "integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==",
"dev": true
},
"@babel/plugin-proposal-async-generator-functions": {
@@ -1045,6 +1045,22 @@
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
"dev": true
},
+ "@types/linkify-it": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz",
+ "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==",
+ "dev": true
+ },
+ "@types/markdown-it": {
+ "version": "12.2.3",
+ "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz",
+ "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
+ "dev": true,
+ "requires": {
+ "@types/linkify-it": "*",
+ "@types/mdurl": "*"
+ }
+ },
"@types/mdast": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz",
@@ -1054,6 +1070,12 @@
"@types/unist": "*"
}
},
+ "@types/mdurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz",
+ "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==",
+ "dev": true
+ },
"@types/node": {
"version": "11.13.8",
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.8.tgz",
@@ -1940,12 +1962,20 @@
}
},
"catharsis": {
- "version": "0.8.9",
- "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz",
- "integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=",
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz",
+ "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==",
"dev": true,
"requires": {
- "underscore-contrib": "~0.3.0"
+ "lodash": "^4.17.15"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ }
}
},
"chalk": {
@@ -5945,39 +5975,59 @@
}
},
"js2xmlparser": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz",
- "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz",
+ "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==",
"dev": true,
"requires": {
- "xmlcreate": "^1.0.1"
+ "xmlcreate": "^2.0.4"
}
},
"jsdoc": {
- "version": "git+https://github.com/BrandonOCasey/jsdoc.git#a3c385e800d8b64ab166d163494182aa4ef92535",
- "from": "git+https://github.com/BrandonOCasey/jsdoc.git#feat/plugin-from-cli",
- "dev": true,
- "requires": {
- "@babel/parser": "~7.2.3",
- "bluebird": "~3.5.0",
- "catharsis": "~0.8.9",
- "escape-string-regexp": "~1.0.5",
- "js2xmlparser": "~3.0.0",
- "klaw": "~3.0.0",
- "markdown-it": "~8.4.2",
- "markdown-it-anchor": "~5.0.2",
- "marked": "~0.6.0",
- "mkdirp": "~0.5.1",
- "requizzle": "~0.2.1",
- "strip-json-comments": "~2.0.1",
+ "version": "3.6.9",
+ "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.9.tgz",
+ "integrity": "sha512-bVrM2DT2iLmv6jd2IdTRk67tC4iaSDUicD+47y+cNCYlE8dccd4xZnlANG4M+OmGyV389bABSTKKfoPCOofbKw==",
+ "dev": true,
+ "requires": {
+ "@babel/parser": "^7.9.4",
+ "@types/markdown-it": "^12.2.3",
+ "bluebird": "^3.7.2",
+ "catharsis": "^0.9.0",
+ "escape-string-regexp": "^2.0.0",
+ "js2xmlparser": "^4.0.2",
+ "klaw": "^4.0.1",
+ "markdown-it": "^12.3.2",
+ "markdown-it-anchor": "^8.4.1",
+ "marked": "^4.0.10",
+ "mkdirp": "^1.0.4",
+ "requizzle": "^0.2.3",
+ "strip-json-comments": "^3.1.0",
"taffydb": "2.6.2",
- "underscore": "~1.9.1"
+ "underscore": "~1.13.2"
},
"dependencies": {
+ "bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true
+ },
"underscore": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
- "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.2.tgz",
+ "integrity": "sha512-ekY1NhRzq0B08g4bGuX4wd2jZx5GnKz6mKSqFL4nqBlfyMGiG10gDFhDTMEfYmDL6Jy0FUIZp7wiRB+0BP7J2g==",
"dev": true
}
}
@@ -6396,13 +6446,10 @@
}
},
"klaw": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz",
- "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==",
- "dev": true,
- "requires": {
- "graceful-fs": "^4.1.9"
- }
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/klaw/-/klaw-4.0.1.tgz",
+ "integrity": "sha512-pgsE40/SvC7st04AHiISNewaIMUbY5V/K8b21ekiPiFoYs/EYSdsGa+FJArB1d441uq4Q8zZyIxvAzkGNlBdRw==",
+ "dev": true
},
"leven": {
"version": "2.1.0",
@@ -6421,9 +6468,9 @@
}
},
"linkify-it": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.1.0.tgz",
- "integrity": "sha512-4REs8/062kV2DSHxNfq5183zrqXMl7WP0WzABH9IeJI+NLm429FgE1PDecltYfnOoFDFlZGh2T8PfZn0r+GTRg==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
+ "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
"dev": true,
"requires": {
"uc.micro": "^1.0.1"
@@ -6875,28 +6922,42 @@
"dev": true
},
"markdown-it": {
- "version": "8.4.2",
- "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz",
- "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==",
+ "version": "12.3.2",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
+ "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
"dev": true,
"requires": {
- "argparse": "^1.0.7",
- "entities": "~1.1.1",
- "linkify-it": "^2.0.0",
+ "argparse": "^2.0.1",
+ "entities": "~2.1.0",
+ "linkify-it": "^3.0.1",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
+ },
+ "dependencies": {
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "entities": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
+ "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
+ "dev": true
+ }
}
},
"markdown-it-anchor": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.0.2.tgz",
- "integrity": "sha512-AFM/woBI8QDJMS/9+MmsBMT5/AR+ImfOsunQZTZhzcTmna3rIzAzbOh5E0l6mlFM/i9666BpUtkqQ9bS7WApCg==",
+ "version": "8.4.1",
+ "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.4.1.tgz",
+ "integrity": "sha512-sLODeRetZ/61KkKLJElaU3NuU2z7MhXf12Ml1WJMSdwpngeofneCRF+JBbat8HiSqhniOMuTemXMrsI7hA6XyA==",
"dev": true
},
"marked": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/marked/-/marked-0.6.2.tgz",
- "integrity": "sha512-LqxwVH3P/rqKX4EKGz7+c2G9r98WeM/SW34ybhgNGhUQNKtf1GmmSkJ6cDGJ/t6tiyae49qRkpyTw2B9HOrgUA==",
+ "version": "4.0.10",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.10.tgz",
+ "integrity": "sha512-+QvuFj0nGgO970fySghXGmuw+Fd0gD2x3+MqCWLIPf5oxdv1Ka6b2q+z9RP01P/IaKPMEramy+7cNy/Lw8c3hw==",
"dev": true
},
"matched": {
@@ -8911,18 +8972,18 @@
"dev": true
},
"requizzle": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz",
- "integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=",
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz",
+ "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==",
"dev": true,
"requires": {
- "underscore": "~1.6.0"
+ "lodash": "^4.17.14"
},
"dependencies": {
- "underscore": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
- "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=",
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
}
}
@@ -9915,9 +9976,9 @@
"dev": true
},
"strip-json-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true
},
"structured-source": {
@@ -10398,23 +10459,6 @@
"integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=",
"dev": true
},
- "underscore-contrib": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz",
- "integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=",
- "dev": true,
- "requires": {
- "underscore": "1.6.0"
- },
- "dependencies": {
- "underscore": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz",
- "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=",
- "dev": true
- }
- }
- },
"unherit": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.1.tgz",
@@ -10936,9 +10980,9 @@
}
},
"xmlcreate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz",
- "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz",
+ "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==",
"dev": true
},
"xmlhttprequest-ssl": {
diff --git a/package.json b/package.json
index 3076569..55e21a4 100644
--- a/package.json
+++ b/package.json
@@ -1,98 +1,98 @@
{
- "name": "videojs-contrib-eme",
- "version": "4.0.0",
- "description": "Supports Encrypted Media Extensions for playback of encrypted content in Video.js",
- "main": "dist/videojs-contrib-eme.cjs.js",
- "module": "dist/videojs-contrib-eme.es.js",
- "scripts": {
- "prebuild": "npm run clean",
- "build": "npm-run-all -p build:*",
- "build:js": "rollup -c scripts/rollup.config.js",
- "clean": "shx rm -rf ./dist ./test/dist",
- "postclean": "shx mkdir -p ./dist ./test/dist",
- "docs": "npm-run-all docs:*",
- "docs:api": "jsdoc src -g plugins/markdown -r -d docs/api",
- "docs:toc": "doctoc README.md",
- "lint": "vjsstandard",
- "server": "karma start scripts/karma.conf.js --singleRun=false --auto-watch",
- "start": "npm-run-all -p server watch",
- "pretest": "npm-run-all lint build",
- "test": "karma start scripts/karma.conf.js",
- "posttest": "shx cat test/dist/coverage/text.txt",
- "update-changelog": "conventional-changelog -p videojs -i CHANGELOG.md -s",
- "preversion": "npm test",
- "version": "is-prerelease || npm run update-changelog && git add CHANGELOG.md",
- "watch": "npm-run-all -p watch:*",
- "watch:js": "npm run build:js -- -w",
- "prepublishOnly": "npm run build && vjsverify"
- },
- "keywords": [
- "videojs",
- "videojs-plugin"
- ],
- "copyright": "Copyright Brightcove, Inc. ",
- "license": "Apache-2.0",
- "vjsstandard": {
- "ignore": [
- "dist",
- "docs",
- "test/dist"
- ]
- },
- "files": [
- "CONTRIBUTING.md",
- "dist/",
- "docs/",
- "index.html",
- "scripts/",
- "src/",
- "test/"
- ],
- "dependencies": {
- "global": "^4.3.2",
- "video.js": "^6 || ^7"
- },
- "devDependencies": {
- "conventional-changelog-cli": "^2.0.12",
- "conventional-changelog-videojs": "^3.0.0",
- "doctoc": "^1.3.1",
- "husky": "^1.0.0-rc.13",
- "jsdoc": "https://github.com/BrandonOCasey/jsdoc#feat/plugin-from-cli",
- "karma": "^4.0.1",
- "lint-staged": "^7.2.2",
- "not-prerelease": "^1.0.1",
- "npm-merge-driver-install": "^1.0.0",
- "npm-run-all": "^4.1.3",
- "pkg-ok": "^2.2.0",
- "rollup": "^0.65.0",
- "shx": "^0.3.2",
- "sinon": "^6.1.5",
- "videojs-generate-karma-config": "^5.1.0",
- "videojs-generate-rollup-config": "^3.1.0",
- "videojs-generator-verify": "^1.2.0",
- "videojs-standard": "~9.0.1"
- },
- "generator-videojs-plugin": {
- "version": "7.3.2"
- },
- "browserslist": [
- "defaults",
- "ie 11"
- ],
- "author": "brandonocasey ",
- "husky": {
- "hooks": {
- "pre-commit": "lint-staged"
- }
- },
- "lint-staged": {
- "*.js": [
- "vjsstandard --fix",
- "git add"
+ "name": "videojs-contrib-eme",
+ "version": "4.0.0",
+ "description": "Supports Encrypted Media Extensions for playback of encrypted content in Video.js",
+ "main": "dist/videojs-contrib-eme.cjs.js",
+ "module": "dist/videojs-contrib-eme.es.js",
+ "scripts": {
+ "prebuild": "npm run clean",
+ "build": "npm-run-all -p build:*",
+ "build:js": "rollup -c scripts/rollup.config.js",
+ "clean": "shx rm -rf ./dist ./test/dist",
+ "postclean": "shx mkdir -p ./dist ./test/dist",
+ "docs": "npm-run-all docs:*",
+ "docs:api": "jsdoc src -g plugins/markdown -r -d docs/api",
+ "docs:toc": "doctoc README.md",
+ "lint": "vjsstandard",
+ "server": "karma start scripts/karma.conf.js --singleRun=false --auto-watch",
+ "start": "npm-run-all -p server watch",
+ "pretest": "npm-run-all lint build",
+ "test": "karma start scripts/karma.conf.js",
+ "posttest": "shx cat test/dist/coverage/text.txt",
+ "update-changelog": "conventional-changelog -p videojs -i CHANGELOG.md -s",
+ "preversion": "npm test",
+ "version": "is-prerelease || npm run update-changelog && git add CHANGELOG.md",
+ "watch": "npm-run-all -p watch:*",
+ "watch:js": "npm run build:js -- -w",
+ "prepublishOnly": "npm run build && vjsverify"
+ },
+ "keywords": [
+ "videojs",
+ "videojs-plugin"
+ ],
+ "copyright": "Copyright Brightcove, Inc. ",
+ "license": "Apache-2.0",
+ "vjsstandard": {
+ "ignore": [
+ "dist",
+ "docs",
+ "test/dist"
+ ]
+ },
+ "files": [
+ "CONTRIBUTING.md",
+ "dist/",
+ "docs/",
+ "index.html",
+ "scripts/",
+ "src/",
+ "test/"
],
- "README.md": [
- "npm run docs:toc",
- "git add"
- ]
- }
-}
+ "dependencies": {
+ "global": "^4.3.2",
+ "video.js": "^6 || ^7"
+ },
+ "devDependencies": {
+ "conventional-changelog-cli": "^2.0.12",
+ "conventional-changelog-videojs": "^3.0.0",
+ "doctoc": "^1.3.1",
+ "husky": "^1.0.0-rc.13",
+ "jsdoc": "^3.6.9",
+ "karma": "^4.0.1",
+ "lint-staged": "^7.2.2",
+ "not-prerelease": "^1.0.1",
+ "npm-merge-driver-install": "^1.0.0",
+ "npm-run-all": "^4.1.3",
+ "pkg-ok": "^2.2.0",
+ "rollup": "^0.65.0",
+ "shx": "^0.3.2",
+ "sinon": "^6.1.5",
+ "videojs-generate-karma-config": "^5.1.0",
+ "videojs-generate-rollup-config": "^3.1.0",
+ "videojs-generator-verify": "^1.2.0",
+ "videojs-standard": "~9.0.1"
+ },
+ "generator-videojs-plugin": {
+ "version": "7.3.2"
+ },
+ "browserslist": [
+ "defaults",
+ "ie 11"
+ ],
+ "author": "brandonocasey ",
+ "husky": {
+ "hooks": {
+ "pre-commit": "lint-staged"
+ }
+ },
+ "lint-staged": {
+ "*.js": [
+ "vjsstandard --fix",
+ "git add"
+ ],
+ "README.md": [
+ "npm run docs:toc",
+ "git add"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/src/eme.js b/src/eme.js
index 8c70c7a..64e7a9e 100644
--- a/src/eme.js
+++ b/src/eme.js
@@ -1,15 +1,18 @@
-import videojs from 'video.js';
-import { requestPlayreadyLicense } from './playready';
-import window from 'global/window';
-import {uint8ArrayToString, mergeAndRemoveNull} from './utils';
-import {httpResponseHandler} from './http-handler.js';
+import videojs from "video.js";
+import { requestPlayreadyLicense } from "./playready";
+import window from "global/window";
+import { uint8ArrayToString, mergeAndRemoveNull } from "./utils";
+import { httpResponseHandler } from "./http-handler.js";
import {
defaultGetCertificate as defaultFairplayGetCertificate,
defaultGetLicense as defaultFairplayGetLicense,
- defaultGetContentId as defaultFairplayGetContentId
-} from './fairplay';
+ defaultGetContentId as defaultFairplayGetContentId,
+} from "./fairplay";
-const isFairplayKeySystem = (str) => str.startsWith('com.apple.fps');
+const isFairplayKeySystem = (str) => str.startsWith("com.apple.fps");
+const PERSISTENT_LICENSE = "persistent-license";
+const TEMPORARY_LICENSE = "temporary";
+const VJS_EME_STORAGE = "vjs_eme_storage";
/**
* Returns an array of MediaKeySystemConfigurationObjects provided in the keySystem
@@ -29,24 +32,27 @@ export const getSupportedConfigurations = (keySystem, keySystemOptions) => {
const isFairplay = isFairplayKeySystem(keySystem);
const supportedConfiguration = {};
- const initDataTypes = keySystemOptions.initDataTypes ||
+ const initDataTypes =
+ keySystemOptions.initDataTypes ||
// fairplay requires an explicit initDataTypes
- (isFairplay ? ['sinf'] : null);
+ (isFairplay ? ["sinf"] : null);
const audioContentType = keySystemOptions.audioContentType;
const audioRobustness = keySystemOptions.audioRobustness;
- const videoContentType = keySystemOptions.videoContentType ||
+ const videoContentType =
+ keySystemOptions.videoContentType ||
// fairplay requires an explicit videoCapabilities/videoContentType
- (isFairplay ? 'video/mp4' : null);
+ (isFairplay ? "video/mp4" : null);
const videoRobustness = keySystemOptions.videoRobustness;
const persistentState = keySystemOptions.persistentState;
+ const sessionTypes = keySystemOptions.sessionTypes;
if (audioContentType || audioRobustness) {
supportedConfiguration.audioCapabilities = [
Object.assign(
{},
- (audioContentType ? { contentType: audioContentType } : {}),
- (audioRobustness ? { robustness: audioRobustness } : {})
- )
+ audioContentType ? { contentType: audioContentType } : {},
+ audioRobustness ? { robustness: audioRobustness } : {}
+ ),
];
}
@@ -54,9 +60,9 @@ export const getSupportedConfigurations = (keySystem, keySystemOptions) => {
supportedConfiguration.videoCapabilities = [
Object.assign(
{},
- (videoContentType ? { contentType: videoContentType } : {}),
- (videoRobustness ? { robustness: videoRobustness } : {})
- )
+ videoContentType ? { contentType: videoContentType } : {},
+ videoRobustness ? { robustness: videoRobustness } : {}
+ ),
];
}
@@ -64,6 +70,10 @@ export const getSupportedConfigurations = (keySystem, keySystemOptions) => {
supportedConfiguration.persistentState = persistentState;
}
+ if (sessionTypes) {
+ supportedConfiguration.sessionTypes = sessionTypes;
+ }
+
if (initDataTypes) {
supportedConfiguration.initDataTypes = initDataTypes;
}
@@ -78,21 +88,32 @@ export const getSupportedKeySystem = (keySystems) => {
let promise;
Object.keys(keySystems).forEach((keySystem) => {
- const supportedConfigurations = getSupportedConfigurations(keySystem, keySystems[keySystem]);
+ const supportedConfigurations = getSupportedConfigurations(
+ keySystem,
+ keySystems[keySystem]
+ );
if (!promise) {
- promise =
- window.navigator.requestMediaKeySystemAccess(keySystem, supportedConfigurations);
+ promise = window.navigator.requestMediaKeySystemAccess(
+ keySystem,
+ supportedConfigurations
+ );
} else {
promise = promise.catch((e) =>
- window.navigator.requestMediaKeySystemAccess(keySystem, supportedConfigurations));
+ window.navigator.requestMediaKeySystemAccess(
+ keySystem,
+ supportedConfigurations
+ )
+ );
}
});
return promise;
};
-export const makeNewRequest = (requestOptions) => {
+var openedPersistentSessions = [];
+
+export const makeNewRequest = async (requestOptions) => {
const {
mediaKeys,
initDataType,
@@ -101,80 +122,158 @@ export const makeNewRequest = (requestOptions) => {
getLicense,
removeSession,
eventBus,
- contentId
+ contentId,
+ keySystem,
} = requestOptions;
- const keySession = mediaKeys.createSession();
+ let sessionType = TEMPORARY_LICENSE;
+ let sessionTypes = options.keySystems[keySystem].sessionTypes;
+ if (sessionTypes && Array.isArray(sessionTypes)) {
+ sessionType =
+ sessionTypes.find((type) => type === PERSISTENT_LICENSE) || sessionType;
+ }
+
+ const openedSession = openedPersistentSessions.find(
+ (s) => s.src === options.src
+ );
+ if (openedSession) {
+ await openedSession.keySession.close();
+ openedPersistentSessions = openedPersistentSessions.filter(
+ (s) => s.src !== options.src
+ );
+ }
+
+ const keySession = mediaKeys.createSession(sessionType);
- eventBus.trigger('keysessioncreated');
+ eventBus.trigger("keysessioncreated");
return new Promise((resolve, reject) => {
+ keySession.addEventListener(
+ "message",
+ (event) => {
+ // all other types will be handled by keystatuseschange
+ if (
+ event.messageType !== "license-request" &&
+ event.messageType !== "license-renewal"
+ ) {
+ return;
+ }
- keySession.addEventListener('message', (event) => {
- // all other types will be handled by keystatuseschange
- if (event.messageType !== 'license-request' && event.messageType !== 'license-renewal') {
- return;
- }
+ getLicense(options, event.message, contentId)
+ .then((license) => {
+ resolve(keySession.update(license));
+ })
+ .catch((err) => {
+ reject(err);
+ });
+ },
+ false
+ );
- getLicense(options, event.message, contentId)
- .then((license) => {
- resolve(keySession.update(license));
- })
- .catch((err) => {
- reject(err);
- });
- }, false);
-
- keySession.addEventListener('keystatuseschange', (event) => {
- let expired = false;
-
- // based on https://www.w3.org/TR/encrypted-media/#example-using-all-events
- keySession.keyStatuses.forEach((status, keyId) => {
- // Trigger an event so that outside listeners can take action if appropriate.
- // For instance, the `output-restricted` status should result in an
- // error being thrown.
- eventBus.trigger({
- keyId,
- status,
- target: keySession,
- type: 'keystatuschange'
+ keySession.closed.then(
+ function (reason) {
+ console.log("Session", this.sessionId, "closed, reason", reason);
+ }.bind(keySession)
+ );
+
+ keySession.addEventListener(
+ "keystatuseschange",
+ (event) => {
+ let expired = false;
+
+ // based on https://www.w3.org/TR/encrypted-media/#example-using-all-events
+ keySession.keyStatuses.forEach((status, keyId) => {
+ // Trigger an event so that outside listeners can take action if appropriate.
+ // For instance, the `output-restricted` status should result in an
+ // error being thrown.
+ eventBus.trigger({
+ keyId,
+ status,
+ target: keySession,
+ type: "keystatuschange",
+ });
+ switch (status) {
+ case "expired":
+ // If one key is expired in a session, all keys are expired. From
+ // https://www.w3.org/TR/encrypted-media/#dom-mediakeystatus-expired, "All other
+ // keys in the session must have this status."
+ expired = true;
+ break;
+ case "internal-error":
+ const message =
+ 'Key status reported as "internal-error." Leaving the session open since we ' +
+ "don't have enough details to know if this error is fatal.";
+
+ // "This value is not actionable by the application."
+ // https://www.w3.org/TR/encrypted-media/#dom-mediakeystatus-internal-error
+ videojs.log.warn(message, event);
+ break;
+ }
});
- switch (status) {
- case 'expired':
- // If one key is expired in a session, all keys are expired. From
- // https://www.w3.org/TR/encrypted-media/#dom-mediakeystatus-expired, "All other
- // keys in the session must have this status."
- expired = true;
- break;
- case 'internal-error':
- const message =
- 'Key status reported as "internal-error." Leaving the session open since we ' +
- 'don\'t have enough details to know if this error is fatal.';
-
- // "This value is not actionable by the application."
- // https://www.w3.org/TR/encrypted-media/#dom-mediakeystatus-internal-error
- videojs.log.warn(message, event);
- break;
+
+ if (expired) {
+ // Close session and remove it from the session list to ensure that a new
+ // session can be created.
+ //
+ // TODO convert to videojs.log.debug and add back in
+ // https://github.com/videojs/video.js/pull/4780
+ // videojs.log.debug('Session expired, closing the session.');
+ keySession.close().then(() => {
+ removeSession(initData);
+ makeNewRequest(requestOptions);
+ });
}
- });
+ },
+ false
+ );
- if (expired) {
- // Close session and remove it from the session list to ensure that a new
- // session can be created.
- //
- // TODO convert to videojs.log.debug and add back in
- // https://github.com/videojs/video.js/pull/4780
- // videojs.log.debug('Session expired, closing the session.');
- keySession.close().then(() => {
- removeSession(initData);
- makeNewRequest(requestOptions);
+ let sessions = localStorage.getItem(VJS_EME_STORAGE);
+ try {
+ sessions = sessions ? JSON.parse(sessions) : {};
+ } catch (error) {
+ console.log("error during sessions parse, re-init it", error);
+ sessions = {};
+ }
+ if (sessionType === PERSISTENT_LICENSE && sessions[options.src]) {
+ keySession
+ .load(sessions[options.src])
+ .then(function (loaded) {
+ if (!loaded) {
+ console.error(
+ "No stored session with the ID " +
+ sessions[options.src] +
+ " was found."
+ );
+ // The application should remove its record of |sessionId|.
+ return;
+ }
+ openedPersistentSessions.push({ src: options.src, keySession });
+ })
+ .catch((error) => {
+ console.log(
+ `Unable to load or initialize the stored session with the ID ${
+ sessions[options.src]
+ }: ${error}`
+ );
});
- }
- }, false);
+ return;
+ }
- keySession.generateRequest(initDataType, initData).catch(() => {
- reject('Unable to create or initialize key session');
- });
+ keySession
+ .generateRequest(initDataType, initData)
+ .then(
+ function () {
+ if (sessionType === PERSISTENT_LICENSE) {
+ // set session id with src video as key
+ sessions[options.src] = this.sessionId;
+ openedPersistentSessions.push({ src: options.src, keySession });
+ localStorage.setItem(VJS_EME_STORAGE, JSON.stringify(sessions));
+ }
+ }.bind(keySession)
+ )
+ .catch(() => {
+ reject("Unable to create or initialize key session");
+ });
});
};
@@ -213,7 +312,7 @@ export const addSession = ({
getLicense,
contentId,
removeSession,
- eventBus
+ eventBus,
}) => {
const sessionData = {
initDataType,
@@ -222,7 +321,8 @@ export const addSession = ({
getLicense,
removeSession,
eventBus,
- contentId
+ contentId,
+ keySystem: video.keySystem,
};
if (video.mediaKeysObject) {
@@ -257,7 +357,7 @@ export const addSession = ({
export const addPendingSessions = ({
video,
certificate,
- createdMediaKeys
+ createdMediaKeys,
}) => {
// save media keys on the video element to act as a reference for other functions so
// that they don't recreate the keys
@@ -271,16 +371,19 @@ export const addPendingSessions = ({
for (let i = 0; i < video.pendingSessionData.length; i++) {
const data = video.pendingSessionData[i];
- promises.push(makeNewRequest({
- mediaKeys: video.mediaKeysObject,
- initDataType: data.initDataType,
- initData: data.initData,
- options: data.options,
- getLicense: data.getLicense,
- removeSession: data.removeSession,
- eventBus: data.eventBus,
- contentId: data.contentId
- }));
+ promises.push(
+ makeNewRequest({
+ mediaKeys: video.mediaKeysObject,
+ initDataType: data.initDataType,
+ initData: data.initData,
+ options: data.options,
+ getLicense: data.getLicense,
+ removeSession: data.removeSession,
+ eventBus: data.eventBus,
+ contentId: data.contentId,
+ keySystem: video.keySystem,
+ })
+ );
}
video.pendingSessionData = [];
@@ -290,32 +393,37 @@ export const addPendingSessions = ({
return Promise.all(promises);
};
-const defaultPlayreadyGetLicense = (keySystemOptions) => (emeOptions, keyMessage, callback) => {
- requestPlayreadyLicense(keySystemOptions, keyMessage, emeOptions, callback);
-};
+const defaultPlayreadyGetLicense =
+ (keySystemOptions) => (emeOptions, keyMessage, callback) => {
+ requestPlayreadyLicense(keySystemOptions, keyMessage, emeOptions, callback);
+ };
-export const defaultGetLicense = (keySystemOptions) => (emeOptions, keyMessage, callback) => {
- const headers = mergeAndRemoveNull(
- {'Content-type': 'application/octet-stream'},
- emeOptions.emeHeaders,
- keySystemOptions.licenseHeaders
- );
+export const defaultGetLicense =
+ (keySystemOptions) => (emeOptions, keyMessage, callback) => {
+ const headers = mergeAndRemoveNull(
+ { "Content-type": "application/octet-stream" },
+ emeOptions.emeHeaders,
+ keySystemOptions.licenseHeaders
+ );
- videojs.xhr({
- uri: keySystemOptions.url,
- method: 'POST',
- responseType: 'arraybuffer',
- body: keyMessage,
- headers
- }, httpResponseHandler(callback, true));
-};
+ videojs.xhr(
+ {
+ uri: keySystemOptions.url,
+ method: "POST",
+ responseType: "arraybuffer",
+ body: keyMessage,
+ headers,
+ },
+ httpResponseHandler(callback, true)
+ );
+ };
const promisifyGetLicense = (keySystem, getLicenseFn, eventBus) => {
return (emeOptions, keyMessage, contentId) => {
return new Promise((resolve, reject) => {
- const callback = function(err, license) {
+ const callback = function (err, license) {
if (eventBus) {
- eventBus.trigger('licenserequestattempted');
+ eventBus.trigger("licenserequestattempted");
}
if (err) {
reject(err);
@@ -326,7 +434,12 @@ const promisifyGetLicense = (keySystem, getLicenseFn, eventBus) => {
};
if (isFairplayKeySystem(keySystem)) {
- getLicenseFn(emeOptions, contentId, new Uint8Array(keyMessage), callback);
+ getLicenseFn(
+ emeOptions,
+ contentId,
+ new Uint8Array(keyMessage),
+ callback
+ );
} else {
getLicenseFn(emeOptions, keyMessage, callback);
}
@@ -335,7 +448,7 @@ const promisifyGetLicense = (keySystem, getLicenseFn, eventBus) => {
};
const standardizeKeySystemOptions = (keySystem, keySystemOptions) => {
- if (typeof keySystemOptions === 'string') {
+ if (typeof keySystemOptions === "string") {
keySystemOptions = { url: keySystemOptions };
}
@@ -344,17 +457,26 @@ const standardizeKeySystemOptions = (keySystem, keySystemOptions) => {
}
if (!keySystemOptions.url && !keySystemOptions.getLicense) {
- throw new Error(`Missing url/licenseUri or getLicense in ${keySystem} keySystem configuration.`);
+ throw new Error(
+ `Missing url/licenseUri or getLicense in ${keySystem} keySystem configuration.`
+ );
}
const isFairplay = isFairplayKeySystem(keySystem);
- if (isFairplay && keySystemOptions.certificateUri && !keySystemOptions.getCertificate) {
- keySystemOptions.getCertificate = defaultFairplayGetCertificate(keySystemOptions);
+ if (
+ isFairplay &&
+ keySystemOptions.certificateUri &&
+ !keySystemOptions.getCertificate
+ ) {
+ keySystemOptions.getCertificate =
+ defaultFairplayGetCertificate(keySystemOptions);
}
if (isFairplay && !keySystemOptions.getCertificate) {
- throw new Error(`Missing getCertificate or certificateUri in ${keySystem} keySystem configuration.`);
+ throw new Error(
+ `Missing getCertificate or certificateUri in ${keySystem} keySystem configuration.`
+ );
}
if (isFairplay && !keySystemOptions.getContentId) {
@@ -362,8 +484,9 @@ const standardizeKeySystemOptions = (keySystem, keySystemOptions) => {
}
if (keySystemOptions.url && !keySystemOptions.getLicense) {
- if (keySystem === 'com.microsoft.playready') {
- keySystemOptions.getLicense = defaultPlayreadyGetLicense(keySystemOptions);
+ if (keySystem === "com.microsoft.playready") {
+ keySystemOptions.getLicense =
+ defaultPlayreadyGetLicense(keySystemOptions);
} else if (isFairplay) {
keySystemOptions.getLicense = defaultFairplayGetLicense(keySystemOptions);
} else {
@@ -381,7 +504,7 @@ export const standard5July2016 = ({
keySystemAccess,
options,
removeSession,
- eventBus
+ eventBus,
}) => {
let keySystemPromise = Promise.resolve();
const keySystem = keySystemAccess.keySystem;
@@ -397,10 +520,11 @@ export const standard5July2016 = ({
return Promise.reject(e);
}
- const contentId = keySystemOptions.getContentId ?
- keySystemOptions.getContentId(options, uint8ArrayToString(initData)) : null;
+ const contentId = keySystemOptions.getContentId
+ ? keySystemOptions.getContentId(options, uint8ArrayToString(initData))
+ : null;
- if (typeof video.mediaKeysObject === 'undefined') {
+ if (typeof video.mediaKeysObject === "undefined") {
// Prevent entering this path again.
video.mediaKeysObject = null;
@@ -428,28 +552,34 @@ export const standard5July2016 = ({
resolve();
});
- }).then(() => {
- return keySystemAccess.createMediaKeys();
- }).then((createdMediaKeys) => {
- return addPendingSessions({
- video,
- certificate,
- createdMediaKeys
+ })
+ .then(() => {
+ return keySystemAccess.createMediaKeys();
+ })
+ .then((createdMediaKeys) => {
+ return addPendingSessions({
+ video,
+ certificate,
+ createdMediaKeys,
+ });
+ })
+ .catch((err) => {
+ // if we have a specific error message, use it, otherwise show a more
+ // generic one
+ if (err) {
+ return Promise.reject(err);
+ }
+ return Promise.reject(
+ "Failed to create and initialize a MediaKeys object"
+ );
});
- }).catch((err) => {
- // if we have a specific error message, use it, otherwise show a more
- // generic one
- if (err) {
- return Promise.reject(err);
- }
- return Promise.reject('Failed to create and initialize a MediaKeys object');
- });
}
return keySystemPromise.then(() => {
// if key system has not been determined then addSession doesn't need getLicense
- const getLicense = video.keySystem ?
- promisifyGetLicense(keySystem, keySystemOptions.getLicense, eventBus) : null;
+ const getLicense = video.keySystem
+ ? promisifyGetLicense(keySystem, keySystemOptions.getLicense, eventBus)
+ : null;
return addSession({
video,
@@ -459,7 +589,7 @@ export const standard5July2016 = ({
getLicense,
contentId,
removeSession,
- eventBus
+ eventBus,
});
});
};