shaka-player 4.6.3 → 4.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (608) hide show
  1. package/README.md +1 -0
  2. package/dist/controls.css +1 -1
  3. package/dist/controls.css.map +1 -1
  4. package/dist/deps.js +13 -9
  5. package/dist/locales.js +33 -33
  6. package/dist/shaka-player.compiled.d.ts +47 -4
  7. package/dist/shaka-player.compiled.debug.d.ts +47 -4
  8. package/dist/shaka-player.compiled.debug.externs.js +50 -2
  9. package/dist/shaka-player.compiled.debug.js +408 -376
  10. package/dist/shaka-player.compiled.debug.map +4 -4
  11. package/dist/shaka-player.compiled.externs.js +50 -2
  12. package/dist/shaka-player.compiled.js +1134 -1118
  13. package/dist/shaka-player.compiled.map +4 -4
  14. package/dist/shaka-player.ui.d.ts +69 -5
  15. package/dist/shaka-player.ui.debug.d.ts +69 -5
  16. package/dist/shaka-player.ui.debug.externs.js +82 -2
  17. package/dist/shaka-player.ui.debug.js +457 -420
  18. package/dist/shaka-player.ui.debug.map +4 -4
  19. package/dist/shaka-player.ui.externs.js +82 -2
  20. package/dist/shaka-player.ui.js +1305 -1289
  21. package/dist/shaka-player.ui.map +4 -4
  22. package/externs/mediasession.js +7 -0
  23. package/externs/shaka/abr_manager.js +8 -0
  24. package/externs/shaka/manifest.js +3 -3
  25. package/externs/shaka/player.js +59 -4
  26. package/lib/abr/simple_abr_manager.js +41 -15
  27. package/lib/ads/client_side_ad_manager.js +4 -0
  28. package/lib/ads/media_tailor_ad_manager.js +5 -0
  29. package/lib/ads/server_side_ad_manager.js +4 -0
  30. package/lib/cea/cea708_service.js +1 -1
  31. package/lib/cea/cea708_window.js +95 -7
  32. package/lib/dash/dash_parser.js +55 -11
  33. package/lib/hls/hls_parser.js +17 -5
  34. package/lib/media/adaptation_set_criteria.js +76 -10
  35. package/lib/media/drm_engine.js +0 -3
  36. package/lib/media/media_source_engine.js +42 -18
  37. package/lib/media/segment_reference.js +12 -0
  38. package/lib/media/streaming_engine.js +58 -5
  39. package/lib/media/video_wrapper.js +4 -3
  40. package/lib/player.js +95 -11
  41. package/lib/text/simple_text_displayer.js +8 -7
  42. package/lib/text/text_utils.js +39 -13
  43. package/lib/text/ui_text_displayer.js +20 -11
  44. package/lib/text/web_vtt_generator.js +1 -1
  45. package/lib/util/cmsd_manager.js +269 -0
  46. package/lib/util/content_steering_manager.js +5 -1
  47. package/lib/util/mime_utils.js +6 -2
  48. package/lib/util/periods.js +108 -39
  49. package/lib/util/player_configuration.js +19 -5
  50. package/lib/util/stream_utils.js +82 -13
  51. package/package.json +1 -1
  52. package/ui/audio_language_selection.js +3 -0
  53. package/ui/controls.js +60 -0
  54. package/ui/externs/ui.js +12 -1
  55. package/ui/hidden_fast_forward_button.js +32 -0
  56. package/ui/hidden_rewind_button.js +32 -0
  57. package/ui/hidden_seek_button.js +121 -0
  58. package/ui/less/buttons.less +50 -0
  59. package/ui/less/containers.less +18 -0
  60. package/ui/resolution_selection.js +2 -0
  61. package/ui/ui.js +2 -0
  62. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -75
  63. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -26
  64. package/.github/ISSUE_TEMPLATE/question.md +0 -26
  65. package/.github/config.yml +0 -1
  66. package/.github/workflows/appspot.yaml +0 -39
  67. package/.github/workflows/build-and-test.yaml +0 -222
  68. package/.github/workflows/compute-incremental-coverage.py +0 -265
  69. package/.github/workflows/custom-actions/prep-for-appspot/action.yaml +0 -56
  70. package/.github/workflows/custom-actions/set-commit-status/action.yaml +0 -37
  71. package/.github/workflows/deflake.yaml +0 -31
  72. package/.github/workflows/demo-version-index.yaml +0 -43
  73. package/.github/workflows/nightly-demo.yaml +0 -42
  74. package/.github/workflows/release-please.yaml +0 -193
  75. package/.github/workflows/report-incremental-coverage.yaml +0 -39
  76. package/.github/workflows/safari-homedir-launcher.sh +0 -18
  77. package/.github/workflows/selenium-lab-tests.yaml +0 -370
  78. package/.github/workflows/shaka-bot-commands/command-help.sh +0 -27
  79. package/.github/workflows/shaka-bot-commands/command-test.sh +0 -56
  80. package/.github/workflows/shaka-bot-commands/lib.sh +0 -83
  81. package/.github/workflows/shaka-bot-commands/main.sh +0 -51
  82. package/.github/workflows/sync-labels.yaml +0 -33
  83. package/.github/workflows/talk-to-shaka-bot.yaml +0 -29
  84. package/.github/workflows/update-issues.yaml +0 -31
  85. package/.github/workflows/update-screenshots.yaml +0 -142
  86. package/.github/workflows/validate-pr-title.yaml +0 -27
  87. package/CHANGELOG.md +0 -5764
  88. package/CODE_OF_CONDUCT.md +0 -93
  89. package/CONTRIBUTING.md +0 -76
  90. package/demo/TengwarTelcontar.woff2 +0 -0
  91. package/demo/app_logo_144.png +0 -0
  92. package/demo/app_logo_192.png +0 -0
  93. package/demo/app_logo_256.png +0 -0
  94. package/demo/app_logo_384.png +0 -0
  95. package/demo/app_logo_512.png +0 -0
  96. package/demo/app_manifest.json +0 -29
  97. package/demo/asset_card.js +0 -410
  98. package/demo/autoTemplate.txt +0 -61
  99. package/demo/cast_receiver/idle1.jpg +0 -0
  100. package/demo/cast_receiver/idle2.jpg +0 -0
  101. package/demo/cast_receiver/idle3.jpg +0 -0
  102. package/demo/cast_receiver/index.html +0 -75
  103. package/demo/cast_receiver/receiver_app.css +0 -111
  104. package/demo/cast_receiver/receiver_app.js +0 -158
  105. package/demo/close_button.js +0 -60
  106. package/demo/common/asset.js +0 -511
  107. package/demo/common/assets.js +0 -1635
  108. package/demo/config.js +0 -859
  109. package/demo/custom.js +0 -907
  110. package/demo/customWarning.txt +0 -8
  111. package/demo/demo.less +0 -591
  112. package/demo/demo_uncompiled.js +0 -11
  113. package/demo/demo_utils.js +0 -113
  114. package/demo/favicon.ico +0 -0
  115. package/demo/front.js +0 -156
  116. package/demo/icons/README.md +0 -4
  117. package/demo/icons/baseline-audiotrack-24px.svg +0 -1
  118. package/demo/icons/baseline-closed_caption-24px.svg +0 -1
  119. package/demo/icons/baseline-fast_forward-24px.svg +0 -1
  120. package/demo/icons/baseline-language-24px.svg +0 -1
  121. package/demo/icons/baseline-live_tv-24px.svg +0 -1
  122. package/demo/icons/baseline-subtitles-24px.svg +0 -1
  123. package/demo/icons/baseline-surround_sound-24px.svg +0 -1
  124. package/demo/icons/custom_ad.svg +0 -1
  125. package/demo/icons/custom_box_with_text.svg +0 -1
  126. package/demo/icons/custom_clear_key.svg +0 -1
  127. package/demo/icons/custom_high_definition.svg +0 -1
  128. package/demo/icons/custom_playready.svg +0 -1
  129. package/demo/icons/custom_ultra_high_definition.svg +0 -1
  130. package/demo/icons/custom_widevine.svg +0 -1
  131. package/demo/index.html +0 -173
  132. package/demo/input.js +0 -270
  133. package/demo/input_container.js +0 -218
  134. package/demo/load.js +0 -156
  135. package/demo/main.js +0 -1854
  136. package/demo/search.js +0 -452
  137. package/demo/service_worker.js +0 -355
  138. package/demo/shaka_logo_trans.png +0 -0
  139. package/demo/tooltip.js +0 -29
  140. package/demo/visualizer.js +0 -335
  141. package/demo/visualizer_button.js +0 -84
  142. package/dist/demo.compiled.debug.js +0 -340
  143. package/dist/demo.compiled.debug.map +0 -8
  144. package/dist/demo.compiled.js +0 -340
  145. package/dist/demo.compiled.map +0 -8
  146. package/dist/demo.css +0 -6
  147. package/dist/demo.css.map +0 -1
  148. package/dist/receiver.compiled.debug.js +0 -187
  149. package/dist/receiver.compiled.debug.map +0 -8
  150. package/dist/receiver.compiled.js +0 -187
  151. package/dist/receiver.compiled.map +0 -8
  152. package/docs/announcement-list-join-group.png +0 -0
  153. package/docs/api-mainpage.md +0 -28
  154. package/docs/design/REDESIGN.md +0 -283
  155. package/docs/design/architecture.md +0 -13
  156. package/docs/design/bg-fetch-after.gv +0 -29
  157. package/docs/design/bg-fetch-after.gv.png +0 -0
  158. package/docs/design/bg-fetch-before.gv +0 -18
  159. package/docs/design/bg-fetch-before.gv.png +0 -0
  160. package/docs/design/bg-fetch.md +0 -134
  161. package/docs/design/cast.gv +0 -35
  162. package/docs/design/cast.gv.png +0 -0
  163. package/docs/design/chromecast.md +0 -151
  164. package/docs/design/codec_preferences.md +0 -158
  165. package/docs/design/dash-audio-channels.md +0 -123
  166. package/docs/design/dash-manifests.md +0 -248
  167. package/docs/design/dash-timeline.svg +0 -4
  168. package/docs/design/dataflow.gv +0 -66
  169. package/docs/design/dataflow.gv.png +0 -0
  170. package/docs/design/export.md +0 -70
  171. package/docs/design/fuzzy-locale-matching.md +0 -40
  172. package/docs/design/gap-jumping.md +0 -151
  173. package/docs/design/lcevc-architecture.png +0 -0
  174. package/docs/design/lcevc-demo.png +0 -0
  175. package/docs/design/lcevc-integration.md +0 -72
  176. package/docs/design/locale_compatibility.svg +0 -1
  177. package/docs/design/locales_tree.svg +0 -1
  178. package/docs/design/localization-design-principles.md +0 -158
  179. package/docs/design/newdemo.gv +0 -83
  180. package/docs/design/newdemo.gv.png +0 -0
  181. package/docs/design/offline.gv +0 -43
  182. package/docs/design/offline.gv.png +0 -0
  183. package/docs/design/offline.md +0 -153
  184. package/docs/design/ownership.gv +0 -76
  185. package/docs/design/ownership.gv.png +0 -0
  186. package/docs/design/preload.md +0 -299
  187. package/docs/design/preload.png +0 -0
  188. package/docs/design/talking-about-languages.md +0 -46
  189. package/docs/design/timeline.svg +0 -152
  190. package/docs/design/ui.md +0 -31
  191. package/docs/design/ui_player_relationships.svg +0 -1
  192. package/docs/jsdoc-plugin.js +0 -74
  193. package/docs/jsdoc-template/README.md +0 -1
  194. package/docs/jsdoc-template/publish.js +0 -879
  195. package/docs/jsdoc-template/static/fonts/OpenSans-Bold-webfont.eot +0 -0
  196. package/docs/jsdoc-template/static/fonts/OpenSans-Bold-webfont.svg +0 -1830
  197. package/docs/jsdoc-template/static/fonts/OpenSans-Bold-webfont.woff +0 -0
  198. package/docs/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  199. package/docs/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.svg +0 -1830
  200. package/docs/jsdoc-template/static/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  201. package/docs/jsdoc-template/static/fonts/OpenSans-Italic-webfont.eot +0 -0
  202. package/docs/jsdoc-template/static/fonts/OpenSans-Italic-webfont.svg +0 -1830
  203. package/docs/jsdoc-template/static/fonts/OpenSans-Italic-webfont.woff +0 -0
  204. package/docs/jsdoc-template/static/fonts/OpenSans-Light-webfont.eot +0 -0
  205. package/docs/jsdoc-template/static/fonts/OpenSans-Light-webfont.svg +0 -1831
  206. package/docs/jsdoc-template/static/fonts/OpenSans-Light-webfont.woff +0 -0
  207. package/docs/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  208. package/docs/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.svg +0 -1835
  209. package/docs/jsdoc-template/static/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  210. package/docs/jsdoc-template/static/fonts/OpenSans-Regular-webfont.eot +0 -0
  211. package/docs/jsdoc-template/static/fonts/OpenSans-Regular-webfont.svg +0 -1831
  212. package/docs/jsdoc-template/static/fonts/OpenSans-Regular-webfont.woff +0 -0
  213. package/docs/jsdoc-template/static/scripts/linenumber.js +0 -44
  214. package/docs/jsdoc-template/static/scripts/show-widget.js +0 -55
  215. package/docs/jsdoc-template/static/styles/jsdoc-default.css +0 -438
  216. package/docs/jsdoc-template/tmpl/augments.tmpl +0 -10
  217. package/docs/jsdoc-template/tmpl/container.tmpl +0 -205
  218. package/docs/jsdoc-template/tmpl/details.tmpl +0 -152
  219. package/docs/jsdoc-template/tmpl/example.tmpl +0 -2
  220. package/docs/jsdoc-template/tmpl/examples.tmpl +0 -13
  221. package/docs/jsdoc-template/tmpl/exceptions.tmpl +0 -32
  222. package/docs/jsdoc-template/tmpl/layout.tmpl +0 -50
  223. package/docs/jsdoc-template/tmpl/mainpage.tmpl +0 -14
  224. package/docs/jsdoc-template/tmpl/members.tmpl +0 -47
  225. package/docs/jsdoc-template/tmpl/method.tmpl +0 -140
  226. package/docs/jsdoc-template/tmpl/modifies.tmpl +0 -14
  227. package/docs/jsdoc-template/tmpl/params.tmpl +0 -131
  228. package/docs/jsdoc-template/tmpl/properties.tmpl +0 -125
  229. package/docs/jsdoc-template/tmpl/returns.tmpl +0 -19
  230. package/docs/jsdoc-template/tmpl/source.tmpl +0 -8
  231. package/docs/jsdoc-template/tmpl/tutorial.tmpl +0 -21
  232. package/docs/jsdoc-template/tmpl/type.tmpl +0 -7
  233. package/docs/jsdoc.conf.json +0 -38
  234. package/docs/shaka-player-logo.png +0 -0
  235. package/docs/style.md +0 -174
  236. package/docs/tutorials/a11y.md +0 -64
  237. package/docs/tutorials/ad_monetization.md +0 -292
  238. package/docs/tutorials/application-level-redirects.md +0 -94
  239. package/docs/tutorials/architecture.md +0 -32
  240. package/docs/tutorials/basic-usage.md +0 -89
  241. package/docs/tutorials/blob-url.md +0 -15
  242. package/docs/tutorials/config.md +0 -148
  243. package/docs/tutorials/debugging.md +0 -189
  244. package/docs/tutorials/drm-config.md +0 -274
  245. package/docs/tutorials/errors.md +0 -95
  246. package/docs/tutorials/fairplay.md +0 -242
  247. package/docs/tutorials/faq.md +0 -252
  248. package/docs/tutorials/index.json +0 -29
  249. package/docs/tutorials/lcevc.md +0 -118
  250. package/docs/tutorials/license-server-auth.md +0 -248
  251. package/docs/tutorials/license-wrapping.md +0 -168
  252. package/docs/tutorials/manifest-parser.md +0 -365
  253. package/docs/tutorials/network-and-buffering-config.md +0 -119
  254. package/docs/tutorials/offline.md +0 -683
  255. package/docs/tutorials/plugins.md +0 -184
  256. package/docs/tutorials/selenium-grid-config.md +0 -174
  257. package/docs/tutorials/service-worker.md +0 -106
  258. package/docs/tutorials/ui-customization.md +0 -288
  259. package/docs/tutorials/ui.md +0 -230
  260. package/docs/tutorials/upgrade-manifest.md +0 -281
  261. package/docs/tutorials/upgrade.md +0 -104
  262. package/docs/tutorials/welcome.md +0 -108
  263. package/docs/tutorials/widevine-service-certs.md +0 -45
  264. package/karma.conf.js +0 -879
  265. package/maintained-branches.md +0 -15
  266. package/roadmap.md +0 -186
  267. package/test/abr/simple_abr_manager_unit.js +0 -398
  268. package/test/ads/ad_manager_unit.js +0 -260
  269. package/test/assumptions/uint8_array_unit.js +0 -22
  270. package/test/cast/cast_proxy_unit.js +0 -736
  271. package/test/cast/cast_receiver_integration.js +0 -488
  272. package/test/cast/cast_receiver_unit.js +0 -1183
  273. package/test/cast/cast_sender_unit.js +0 -973
  274. package/test/cast/cast_utils_unit.js +0 -311
  275. package/test/cea/cea608_memory_unit.js +0 -411
  276. package/test/cea/cea708_service_unit.js +0 -674
  277. package/test/cea/cea708_window_unit.js +0 -373
  278. package/test/cea/cea_decoder_unit.js +0 -615
  279. package/test/cea/dtvcc_packet_builder_unit.js +0 -158
  280. package/test/cea/dtvcc_packet_unit.js +0 -60
  281. package/test/cea/mp4_cea_parser_unit.js +0 -127
  282. package/test/codec_switching/codec_switching_integration.js +0 -182
  283. package/test/dash/dash_parser_content_protection_unit.js +0 -998
  284. package/test/dash/dash_parser_integration.js +0 -74
  285. package/test/dash/dash_parser_live_unit.js +0 -1542
  286. package/test/dash/dash_parser_manifest_unit.js +0 -3121
  287. package/test/dash/dash_parser_segment_base_unit.js +0 -421
  288. package/test/dash/dash_parser_segment_list_unit.js +0 -380
  289. package/test/dash/dash_parser_segment_template_unit.js +0 -910
  290. package/test/dash/mpd_utils_unit.js +0 -794
  291. package/test/demo/demo_unit.js +0 -108
  292. package/test/deprecate/enforcer_unit.js +0 -74
  293. package/test/deprecate/version_unit.js +0 -57
  294. package/test/hls/hls_live_unit.js +0 -1330
  295. package/test/hls/hls_parser_unit.js +0 -5276
  296. package/test/hls/manifest_text_parser_unit.js +0 -545
  297. package/test/media/adaptation_set_criteria_unit.js +0 -806
  298. package/test/media/adaptation_set_unit.js +0 -229
  299. package/test/media/buffering_observer_unit.js +0 -143
  300. package/test/media/closed_caption_parser_unit.js +0 -18
  301. package/test/media/content_workarounds_unit.js +0 -43
  302. package/test/media/drm_engine_integration.js +0 -356
  303. package/test/media/drm_engine_unit.js +0 -2778
  304. package/test/media/media_source_engine_integration.js +0 -691
  305. package/test/media/media_source_engine_unit.js +0 -1512
  306. package/test/media/mp4_segment_index_parser_unit.js +0 -80
  307. package/test/media/play_rate_controller_unit.js +0 -69
  308. package/test/media/playhead_unit.js +0 -1394
  309. package/test/media/presentation_timeline_unit.js +0 -477
  310. package/test/media/quality_observer_unit.js +0 -138
  311. package/test/media/region_observer_unit.js +0 -374
  312. package/test/media/region_timeline_unit.js +0 -139
  313. package/test/media/segment_index_unit.js +0 -1080
  314. package/test/media/segment_prefetch_unit.js +0 -243
  315. package/test/media/segment_reference_unit.js +0 -63
  316. package/test/media/stall_detector_unit.js +0 -184
  317. package/test/media/streaming_engine_integration.js +0 -632
  318. package/test/media/streaming_engine_unit.js +0 -4211
  319. package/test/media/time_ranges_utils_unit.js +0 -123
  320. package/test/media/webm_segment_index_parser_unit.js +0 -90
  321. package/test/mss/mss_parser_content_protection_unit.js +0 -49
  322. package/test/mss/mss_parser_unit.js +0 -474
  323. package/test/mss/mss_player_integration.js +0 -124
  324. package/test/net/data_uri_plugin_unit.js +0 -105
  325. package/test/net/http_plugin_unit.js +0 -439
  326. package/test/net/networking_engine_unit.js +0 -1236
  327. package/test/net/networking_utils_unit.js +0 -37
  328. package/test/offline/download_progress_estimator_unit.js +0 -90
  329. package/test/offline/indexeddb_storage_unit.js +0 -192
  330. package/test/offline/manifest_convert_unit.js +0 -622
  331. package/test/offline/offline_integration.js +0 -168
  332. package/test/offline/offline_manifest_parser_unit.js +0 -231
  333. package/test/offline/offline_scheme_unit.js +0 -154
  334. package/test/offline/offline_uri_unit.js +0 -59
  335. package/test/offline/storage_compatibility_unit.js +0 -344
  336. package/test/offline/storage_integration.js +0 -1858
  337. package/test/player_external.js +0 -237
  338. package/test/player_integration.js +0 -1371
  339. package/test/player_load_graph_integration.js +0 -865
  340. package/test/player_src_equals_external.js +0 -154
  341. package/test/player_src_equals_integration.js +0 -527
  342. package/test/player_unit.js +0 -4434
  343. package/test/polyfill/media_capabilities_unit.js +0 -277
  344. package/test/polyfill/patchedmediakeys_apple_unit.js +0 -130
  345. package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
  346. package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
  347. package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
  348. package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
  349. package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
  350. package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
  351. package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
  352. package/test/test/assets/3675/dash_0.mpd +0 -30
  353. package/test/test/assets/3675/dash_1.mpd +0 -30
  354. package/test/test/assets/3675/dash_2.mpd +0 -30
  355. package/test/test/assets/3675/dash_3.mpd +0 -30
  356. package/test/test/assets/3675/dash_4.mpd +0 -30
  357. package/test/test/assets/3675/dash_5.mpd +0 -26
  358. package/test/test/assets/3675/init-stream0.m4s +0 -0
  359. package/test/test/assets/audio-xhe-aac.mp4 +0 -0
  360. package/test/test/assets/audio.ts +0 -0
  361. package/test/test/assets/captions-test.ts +0 -0
  362. package/test/test/assets/cea-init.mp4 +0 -0
  363. package/test/test/assets/cea-segment.mp4 +0 -0
  364. package/test/test/assets/chapters.srt +0 -11
  365. package/test/test/assets/chapters.vtt +0 -10
  366. package/test/test/assets/chapters2.vtt +0 -10
  367. package/test/test/assets/dash-aes-128/Fragments(video=0,format=mpd-time-csf) +0 -0
  368. package/test/test/assets/dash-aes-128/Fragments(video=20000000,format=mpd-time-csf) +0 -0
  369. package/test/test/assets/dash-aes-128/Fragments(video=40000000,format=mpd-time-csf) +0 -0
  370. package/test/test/assets/dash-aes-128/Fragments(video=60000000,format=mpd-time-csf) +0 -0
  371. package/test/test/assets/dash-aes-128/Fragments(video=i,format=mpd-time-csf) +0 -0
  372. package/test/test/assets/dash-aes-128/dash.mpd +0 -18
  373. package/test/test/assets/dash-aes-128/license +0 -1
  374. package/test/test/assets/dash-multi-codec/audio_en_2c_128k_aac.mp4 +0 -0
  375. package/test/test/assets/dash-multi-codec/audio_es_2c_64k_opus.webm +0 -0
  376. package/test/test/assets/dash-multi-codec/dash.mpd +0 -32
  377. package/test/test/assets/dash-multi-codec/video_144p_108k_h264.mp4 +0 -0
  378. package/test/test/assets/db-dump-v1.json +0 -1
  379. package/test/test/assets/db-dump-v2-broken.json +0 -1
  380. package/test/test/assets/db-dump-v2-clean.json +0 -1
  381. package/test/test/assets/db-dump-v3.json +0 -1
  382. package/test/test/assets/db-dump-v4-broken.json +0 -1
  383. package/test/test/assets/db-dump-v5.json +0 -1
  384. package/test/test/assets/empty_caption_video_init.mp4 +0 -0
  385. package/test/test/assets/empty_caption_video_segment.mp4 +0 -0
  386. package/test/test/assets/encrypted-sintel-audio-init.mp4 +0 -0
  387. package/test/test/assets/encrypted-sintel-audio-segment.mp4 +0 -0
  388. package/test/test/assets/encrypted-sintel-video-init.mp4 +0 -0
  389. package/test/test/assets/encrypted-sintel-video-segment.mp4 +0 -0
  390. package/test/test/assets/green-pixel.mp4 +0 -0
  391. package/test/test/assets/green-pixel.txt +0 -15
  392. package/test/test/assets/h265-cea-init.mp4 +0 -0
  393. package/test/test/assets/h265-cea-segment.mp4 +0 -0
  394. package/test/test/assets/hls-raw-aac/fileSequence0.aac +0 -0
  395. package/test/test/assets/hls-raw-aac/fileSequence1.aac +0 -0
  396. package/test/test/assets/hls-raw-aac/fileSequence2.aac +0 -0
  397. package/test/test/assets/hls-raw-aac/fileSequence3.aac +0 -0
  398. package/test/test/assets/hls-raw-aac/manifest.m3u8 +0 -4
  399. package/test/test/assets/hls-raw-aac/stream.m4a.m3u8 +0 -14
  400. package/test/test/assets/hls-raw-ac3/fileSequence0.ac3 +0 -0
  401. package/test/test/assets/hls-raw-ac3/fileSequence1.ac3 +0 -0
  402. package/test/test/assets/hls-raw-ac3/fileSequence2.ac3 +0 -0
  403. package/test/test/assets/hls-raw-ac3/fileSequence3.ac3 +0 -0
  404. package/test/test/assets/hls-raw-ac3/fileSequence4.ac3 +0 -0
  405. package/test/test/assets/hls-raw-ac3/fileSequence5.ac3 +0 -0
  406. package/test/test/assets/hls-raw-ac3/fileSequence6.ac3 +0 -0
  407. package/test/test/assets/hls-raw-ac3/fileSequence7.ac3 +0 -0
  408. package/test/test/assets/hls-raw-ac3/prog_index.m3u8 +0 -31
  409. package/test/test/assets/hls-raw-ec3/fileSequence0.ec3 +0 -0
  410. package/test/test/assets/hls-raw-ec3/fileSequence1.ec3 +0 -0
  411. package/test/test/assets/hls-raw-ec3/fileSequence2.ec3 +0 -0
  412. package/test/test/assets/hls-raw-ec3/fileSequence3.ec3 +0 -0
  413. package/test/test/assets/hls-raw-ec3/fileSequence4.ec3 +0 -0
  414. package/test/test/assets/hls-raw-ec3/fileSequence5.ec3 +0 -0
  415. package/test/test/assets/hls-raw-ec3/fileSequence6.ec3 +0 -0
  416. package/test/test/assets/hls-raw-ec3/fileSequence7.ec3 +0 -0
  417. package/test/test/assets/hls-raw-ec3/prog_index.m3u8 +0 -31
  418. package/test/test/assets/hls-raw-mp3/chunklist_w905519204.m3u8 +0 -13
  419. package/test/test/assets/hls-raw-mp3/media_w905519204_0.mp3 +0 -0
  420. package/test/test/assets/hls-raw-mp3/media_w905519204_1.mp3 +0 -0
  421. package/test/test/assets/hls-raw-mp3/media_w905519204_2.mp3 +0 -0
  422. package/test/test/assets/hls-raw-mp3/media_w905519204_3.mp3 +0 -0
  423. package/test/test/assets/hls-raw-mp3/playlist.m3u8 +0 -4
  424. package/test/test/assets/hls-ts-aac/playlist.m3u8 +0 -23
  425. package/test/test/assets/hls-ts-aac/segment_0.ts +0 -0
  426. package/test/test/assets/hls-ts-aac/segment_1.ts +0 -0
  427. package/test/test/assets/hls-ts-aac/segment_2.ts +0 -0
  428. package/test/test/assets/hls-ts-aac/segment_3.ts +0 -0
  429. package/test/test/assets/hls-ts-aac/segment_4.ts +0 -0
  430. package/test/test/assets/hls-ts-aac/segment_5.ts +0 -0
  431. package/test/test/assets/hls-ts-aac/segment_6.ts +0 -0
  432. package/test/test/assets/hls-ts-aac/segment_7.ts +0 -0
  433. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0000.ts +0 -0
  434. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0001.ts +0 -0
  435. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0002.ts +0 -0
  436. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0003.ts +0 -0
  437. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0004.ts +0 -0
  438. package/test/test/assets/hls-ts-ac3/ChID_voices_6ch_640kbps_dd_sub_0005.ts +0 -0
  439. package/test/test/assets/hls-ts-ac3/prog_index.m3u8 +0 -19
  440. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0000.ts +0 -0
  441. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0001.ts +0 -0
  442. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0002.ts +0 -0
  443. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0003.ts +0 -0
  444. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0004.ts +0 -0
  445. package/test/test/assets/hls-ts-ec3/ChID_voices_6ch_256kbps_ddp_sub_0005.ts +0 -0
  446. package/test/test/assets/hls-ts-ec3/prog_index.m3u8 +0 -19
  447. package/test/test/assets/hls-ts-h264/fileSequence0.ts +0 -0
  448. package/test/test/assets/hls-ts-h264/fileSequence1.ts +0 -0
  449. package/test/test/assets/hls-ts-h264/fileSequence2.ts +0 -0
  450. package/test/test/assets/hls-ts-h264/fileSequence3.ts +0 -0
  451. package/test/test/assets/hls-ts-h264/fileSequence4.ts +0 -0
  452. package/test/test/assets/hls-ts-h264/fileSequence5.ts +0 -0
  453. package/test/test/assets/hls-ts-h264/prog_index.m3u8 +0 -25
  454. package/test/test/assets/hls-ts-h265/0.ts +0 -0
  455. package/test/test/assets/hls-ts-h265/hevc.m3u8 +0 -6
  456. package/test/test/assets/hls-ts-h265/index.m3u8 +0 -7
  457. package/test/test/assets/hls-ts-mp3/manifest.m3u8 +0 -13
  458. package/test/test/assets/hls-ts-mp3/media_w239891843_0.ts +0 -0
  459. package/test/test/assets/hls-ts-mp3/media_w239891843_1.ts +0 -0
  460. package/test/test/assets/hls-ts-mp3/media_w239891843_2.ts +0 -0
  461. package/test/test/assets/hls-ts-mp3/media_w239891843_3.ts +0 -0
  462. package/test/test/assets/hls-ts-muxed-aac-h264/chunk.m3u8 +0 -17
  463. package/test/test/assets/hls-ts-muxed-aac-h264/n_0_0_0.ts +0 -0
  464. package/test/test/assets/hls-ts-muxed-aac-h264/n_1_0_0.ts +0 -0
  465. package/test/test/assets/hls-ts-muxed-aac-h264/n_2_0_0.ts +0 -0
  466. package/test/test/assets/hls-ts-muxed-aac-h264/n_3_0_0.ts +0 -0
  467. package/test/test/assets/hls-ts-muxed-aac-h264/n_4_0_0.ts +0 -0
  468. package/test/test/assets/hls-ts-muxed-aac-h264/n_5_0_0.ts +0 -0
  469. package/test/test/assets/hls-ts-muxed-aac-h264/playlist.m3u8 +0 -4
  470. package/test/test/assets/hls-ts-muxed-aac-h265/0.ts +0 -0
  471. package/test/test/assets/hls-ts-muxed-aac-h265/1.ts +0 -0
  472. package/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8 +0 -9
  473. package/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8 +0 -24
  474. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00000.ts +0 -0
  475. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00001.ts +0 -0
  476. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00002.ts +0 -0
  477. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00003.ts +0 -0
  478. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00004.ts +0 -0
  479. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00005.ts +0 -0
  480. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts +0 -0
  481. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts +0 -0
  482. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts +0 -0
  483. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts +0 -0
  484. package/test/test/assets/hls-ts-muxed-ec3-h264/prog_index.m3u8 +0 -14
  485. package/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8 +0 -23
  486. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-1-v1-a1.ts +0 -0
  487. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-2-v1-a1.ts +0 -0
  488. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-3-v1-a1.ts +0 -0
  489. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-4-v1-a1.ts +0 -0
  490. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-5-v1-a1.ts +0 -0
  491. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-6-v1-a1.ts +0 -0
  492. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-7-v1-a1.ts +0 -0
  493. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-8-v1-a1.ts +0 -0
  494. package/test/test/assets/id3-metadata.aac +0 -0
  495. package/test/test/assets/id3-metadata.ts +0 -0
  496. package/test/test/assets/index-segment.mp4 +0 -0
  497. package/test/test/assets/index-segment.webm +0 -0
  498. package/test/test/assets/init-segment.webm +0 -0
  499. package/test/test/assets/large_file.mpd +0 -4930
  500. package/test/test/assets/multidrm-audio-init.mp4 +0 -0
  501. package/test/test/assets/multidrm-audio-segment.mp4 +0 -0
  502. package/test/test/assets/multidrm-video-init.mp4 +0 -0
  503. package/test/test/assets/multidrm-video-segment.mp4 +0 -0
  504. package/test/test/assets/multiple-trun-init.mp4 +0 -0
  505. package/test/test/assets/multiple-trun-segment.mp4 +0 -0
  506. package/test/test/assets/sintel-audio-init.mp4 +0 -0
  507. package/test/test/assets/sintel-audio-segment.mp4 +0 -0
  508. package/test/test/assets/sintel-video-init.mp4 +0 -0
  509. package/test/test/assets/sintel-video-segment.mp4 +0 -0
  510. package/test/test/assets/small.mp4 +0 -0
  511. package/test/test/assets/text-clip-alt.vtt +0 -63
  512. package/test/test/assets/text-clip.vtt +0 -63
  513. package/test/test/assets/thumbnails-sprites.vtt +0 -10
  514. package/test/test/assets/thumbnails.vtt +0 -10
  515. package/test/test/assets/ttml-init.mp4 +0 -0
  516. package/test/test/assets/ttml-segment-multiplemdat.mp4 +0 -0
  517. package/test/test/assets/ttml-segment.mp4 +0 -0
  518. package/test/test/assets/video.ts +0 -0
  519. package/test/test/assets/vtt-init.mp4 +0 -0
  520. package/test/test/assets/vtt-segment-multi-payload.mp4 +0 -0
  521. package/test/test/assets/vtt-segment-no-duration.mp4 +0 -0
  522. package/test/test/assets/vtt-segment-settings.mp4 +0 -0
  523. package/test/test/assets/vtt-segment.mp4 +0 -0
  524. package/test/test/boot.js +0 -495
  525. package/test/test/externs/filters.js +0 -44
  526. package/test/test/externs/fontfaceonload.js +0 -29
  527. package/test/test/externs/jasmine.js +0 -670
  528. package/test/test/externs/karma.js +0 -26
  529. package/test/test/externs/require.js +0 -21
  530. package/test/test/externs/sprintf.js +0 -18
  531. package/test/test/namespace.js +0 -10
  532. package/test/test/util/canned_idb.js +0 -379
  533. package/test/test/util/cea_utils.js +0 -60
  534. package/test/test/util/dash_parser_util.js +0 -329
  535. package/test/test/util/fake_ad.js +0 -321
  536. package/test/test/util/fake_ad_manager.js +0 -122
  537. package/test/test/util/fake_demo_main.js +0 -144
  538. package/test/test/util/fake_drm_engine.js +0 -103
  539. package/test/test/util/fake_media_source_engine.js +0 -464
  540. package/test/test/util/fake_networking_engine.js +0 -381
  541. package/test/test/util/fake_segment_prefetch.js +0 -84
  542. package/test/test/util/fake_text_displayer.js +0 -60
  543. package/test/test/util/id3_generator.js +0 -100
  544. package/test/test/util/indexeddb_utils.js +0 -124
  545. package/test/test/util/jasmine_fetch.js +0 -382
  546. package/test/test/util/layout_tests.js +0 -434
  547. package/test/test/util/loader.js +0 -88
  548. package/test/test/util/manifest_generator.js +0 -705
  549. package/test/test/util/manifest_parser_util.js +0 -101
  550. package/test/test/util/mss_parser_util.js +0 -119
  551. package/test/test/util/offline_utils.js +0 -105
  552. package/test/test/util/simple_fakes.js +0 -535
  553. package/test/test/util/stream_generator.js +0 -676
  554. package/test/test/util/streaming_engine_util.js +0 -506
  555. package/test/test/util/test_scheme.js +0 -778
  556. package/test/test/util/ttml_utils.js +0 -77
  557. package/test/test/util/ui_utils.js +0 -183
  558. package/test/test/util/util.js +0 -374
  559. package/test/test/util/waiter.js +0 -406
  560. package/test/text/cue_integration.js +0 -51
  561. package/test/text/lrc_text_parser_unit.js +0 -98
  562. package/test/text/mp4_ttml_parser_unit.js +0 -171
  563. package/test/text/mp4_vtt_parser_unit.js +0 -195
  564. package/test/text/sbv_text_parser_unit.js +0 -81
  565. package/test/text/simple_text_displayer_unit.js +0 -468
  566. package/test/text/srt_text_parser_unit.js +0 -163
  567. package/test/text/ssa_text_parser_unit.js +0 -382
  568. package/test/text/text_displayer_layout_unit.js +0 -323
  569. package/test/text/text_engine_unit.js +0 -500
  570. package/test/text/text_track_integration.js +0 -186
  571. package/test/text/ttml_text_parser_unit.js +0 -2176
  572. package/test/text/ui_text_displayer_unit.js +0 -608
  573. package/test/text/vtt_text_parser_unit.js +0 -1363
  574. package/test/text/web_vtt_generator_unit.js +0 -144
  575. package/test/text/web_vtt_layout_integration.js +0 -524
  576. package/test/transmuxer/transmuxer_engine_integration.js +0 -69
  577. package/test/transmuxer/transmuxer_integration.js +0 -443
  578. package/test/ui/ad_ui_unit.js +0 -369
  579. package/test/ui/localization_unit.js +0 -508
  580. package/test/ui/ui_customization_unit.js +0 -208
  581. package/test/ui/ui_integration.js +0 -669
  582. package/test/ui/ui_unit.js +0 -902
  583. package/test/util/abortable_operation_unit.js +0 -624
  584. package/test/util/array_utils_unit.js +0 -58
  585. package/test/util/buffer_utils_unit.js +0 -185
  586. package/test/util/cmcd_manager_unit.js +0 -440
  587. package/test/util/content_steering_manager_unit.js +0 -427
  588. package/test/util/data_view_reader_unit.js +0 -254
  589. package/test/util/ebml_parser_unit.js +0 -297
  590. package/test/util/event_manager_unit.js +0 -185
  591. package/test/util/fake_event_target_unit.js +0 -123
  592. package/test/util/id3_utils_unit.js +0 -168
  593. package/test/util/iterables_unit.js +0 -68
  594. package/test/util/language_utils_unit.js +0 -240
  595. package/test/util/manifest_parser_utils_unit.js +0 -55
  596. package/test/util/mime_utils_unit.js +0 -64
  597. package/test/util/mp4_box_parsers_unit.js +0 -246
  598. package/test/util/mp4_parser_unit.js +0 -373
  599. package/test/util/multi_map_unit.js +0 -94
  600. package/test/util/object_utils_unit.js +0 -79
  601. package/test/util/periods_unit.js +0 -1623
  602. package/test/util/pssh_unit.js +0 -226
  603. package/test/util/state_history_unit.js +0 -101
  604. package/test/util/stream_utils_unit.js +0 -1068
  605. package/test/util/string_utils_unit.js +0 -166
  606. package/test/util/text_parser_unit.js +0 -165
  607. package/test/util/ts_parser_unit.js +0 -77
  608. package/test/util/xml_utils_unit.js +0 -444
@@ -1,1858 +0,0 @@
1
- /*! @license
2
- * Shaka Player
3
- * Copyright 2016 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- /** @return {boolean} */
8
- function storageSupport() {
9
- return shaka.offline.Storage.support();
10
- }
11
-
12
- /** @return {!Promise.<boolean>} */
13
- async function drmStorageSupport() {
14
- if (!shaka.offline.Storage.support()) {
15
- return false;
16
- }
17
-
18
- const support = await shaka.Player.probeSupport();
19
- const widevineSupport = support.drm['com.widevine.alpha'];
20
- return !!(widevineSupport && widevineSupport.persistentState);
21
- }
22
-
23
- filterDescribe('Storage', storageSupport, () => {
24
- const Util = shaka.test.Util;
25
-
26
- const englishUS = 'en-us';
27
- const frenchCanadian = 'fr-ca';
28
- const fakeMimeType = 'application/test';
29
-
30
- const manifestWithPerStreamBandwidthUri =
31
- 'fake:manifest-with-per-stream-bandwidth';
32
- const manifestWithoutPerStreamBandwidthUri =
33
- 'fake:manifest-without-per-stream-bandwidth';
34
- const manifestWithNonZeroStartUri = 'fake:manifest-with-non-zero-start';
35
- const manifestWithLiveTimelineUri = 'fake:manifest-with-live-timeline';
36
- const manifestWithAlternateSegmentsUri = 'fake:manifest-with-alt-segments';
37
- const manifestWithVideoInitSegmentsUri =
38
- 'fake:manifest-with-video-init-segments';
39
-
40
- const initSegmentUri = 'fake:init-segment';
41
- const segment1Uri = 'fake:segment-1';
42
- const segment2Uri = 'fake:segment-2';
43
- const segment3Uri = 'fake:segment-3';
44
- const segment4Uri = 'fake:segment-4';
45
-
46
- const alternateInitSegmentUri = 'fake:alt-init-segment';
47
- const alternateSegment1Uri = 'fake:alt-segment-1';
48
- const alternateSegment2Uri = 'fake:alt-segment-2';
49
- const alternateSegment3Uri = 'fake:alt-segment-3';
50
- const alternateSegment4Uri = 'fake:alt-segment-4';
51
-
52
- const noMetadata = {};
53
-
54
- const kbps = (k) => k * 1000;
55
-
56
- beforeEach(async () => {
57
- // Make sure we start with a clean slate between each run.
58
- await eraseStorage();
59
-
60
- shaka.media.ManifestParser.registerParserByMime(
61
- fakeMimeType, () => new FakeManifestParser());
62
- });
63
-
64
- afterEach(async () => {
65
- shaka.media.ManifestParser.unregisterParserByMime(fakeMimeType);
66
- // Make sure we don't leave anything behind.
67
- await eraseStorage();
68
- });
69
-
70
- describe('storage delete all', () => {
71
- /** @type {!shaka.Player} */
72
- let player;
73
-
74
- beforeEach(() => {
75
- // Use a real Player since Storage only uses the configuration and
76
- // networking engine. This allows us to use Player.configure in these
77
- // tests.
78
- player = new shaka.Player();
79
- });
80
-
81
- afterEach(async () => {
82
- await player.destroy();
83
- });
84
-
85
- it('removes all content from storage', async () => {
86
- const testSchemeMimeType = 'application/x-test-manifest';
87
- const manifestUri = 'test:sintel';
88
-
89
- // Store a piece of content.
90
- await withStorage((storage) => {
91
- return storage.store(
92
- manifestUri, noMetadata, testSchemeMimeType).promise;
93
- });
94
-
95
- // Make sure that the content can be found.
96
- await withStorage(async (storage) => {
97
- const content = await storage.list();
98
- expect(content).toBeTruthy();
99
- expect(content.length).toBe(1);
100
- });
101
-
102
- // Ask storage to erase everything.
103
- await shaka.offline.Storage.deleteAll();
104
-
105
- // Make sure that all content that was previously found is no gone.
106
- await withStorage(async (storage) => {
107
- const content = await storage.list();
108
- expect(content).toBeTruthy();
109
- expect(content.length).toBe(0);
110
- });
111
- });
112
-
113
- /**
114
- * @param {function(!shaka.offline.Storage)|
115
- * function(!shaka.offline.Storage):!Promise} action
116
- * @return {!Promise}
117
- */
118
- async function withStorage(action) {
119
- /** @type {!shaka.offline.Storage} */
120
- const storage = new shaka.offline.Storage(player);
121
-
122
- try {
123
- await action(storage);
124
- } finally {
125
- await storage.destroy();
126
- }
127
- }
128
- });
129
-
130
- filterDescribe('persistent license', drmStorageSupport, () => {
131
- /** @type {!shaka.Player} */
132
- let player;
133
- /** @type {!shaka.offline.Storage} */
134
- let storage;
135
-
136
- beforeEach(() => {
137
- // Use a real Player since Storage only uses the configuration and
138
- // networking engine. This allows us to use Player.configure in these
139
- // tests.
140
- player = new shaka.Player();
141
- storage = new shaka.offline.Storage(player);
142
- });
143
-
144
- afterEach(async () => {
145
- await storage.destroy();
146
- await player.destroy();
147
- });
148
-
149
- // TODO: Make a test to ensure that setting delayLicenseRequestUntilPlayed
150
- // to true doesn't break storage, once we have working tests for storing DRM
151
- // content.
152
- // See issue #2218.
153
-
154
- // Quarantined due to http://crbug.com/1019298 where a load cannot happen
155
- // immediately after a remove. This can sometimes be fixed with a delay,
156
- // but it is extremely flaky, so these are disabled until the bug is fixed.
157
- quarantinedIt('removes persistent license', async () => {
158
- const testSchemeMimeType = 'application/x-test-manifest';
159
-
160
- // PART 1 - Download and store content that has a persistent license
161
- // associated with it.
162
- const stored = await storage.store(
163
- 'test:sintel-enc', noMetadata, testSchemeMimeType).promise;
164
- goog.asserts.assert(stored.offlineUri != null, 'URI should not be null!');
165
-
166
- /** @type {shaka.offline.OfflineUri} */
167
- const uri = shaka.offline.OfflineUri.parse(stored.offlineUri);
168
- goog.asserts.assert(uri, 'Stored offline uri should be non-null');
169
-
170
- const manifest = await getStoredManifest(uri);
171
- expect(manifest.offlineSessionIds).toBeTruthy();
172
- expect(manifest.offlineSessionIds.length).toBeTruthy();
173
-
174
- // PART 2 - Check that the licences are stored.
175
- await withDrm(player, manifest, (drm) => {
176
- return Promise.all(manifest.offlineSessionIds.map(async (session) => {
177
- const foundSession = await loadOfflineSession(drm, session);
178
- expect(foundSession).toBeTruthy();
179
- }));
180
- });
181
-
182
- // PART 3 - Remove the manifest from storage. This should remove all
183
- // the sessions.
184
- await storage.remove(uri.toString());
185
-
186
- // PART 4 - Check that the licenses were removed.
187
- const p = withDrm(player, manifest, (drm) => {
188
- return Promise.all(manifest.offlineSessionIds.map(async (session) => {
189
- const notFoundSession = await loadOfflineSession(drm, session);
190
- expect(notFoundSession).toBeFalsy();
191
- }));
192
- });
193
- const expected = Util.jasmineError(new shaka.util.Error(
194
- shaka.util.Error.Severity.CRITICAL,
195
- shaka.util.Error.Category.DRM,
196
- shaka.util.Error.Code.OFFLINE_SESSION_REMOVED));
197
- await expectAsync(p).toBeRejectedWith(expected);
198
- });
199
-
200
- quarantinedIt('defers removing licenses on error', async () => {
201
- const testSchemeMimeType = 'application/x-test-manifest';
202
-
203
- // PART 1 - Download and store content that has a persistent license
204
- // associated with it.
205
- const stored = await storage.store(
206
- 'test:sintel-enc', noMetadata, testSchemeMimeType).promise;
207
- goog.asserts.assert(stored.offlineUri != null, 'URI should not be null!');
208
-
209
- /** @type {shaka.offline.OfflineUri} */
210
- const uri = shaka.offline.OfflineUri.parse(stored.offlineUri);
211
- goog.asserts.assert(uri, 'Stored offline uri should be non-null');
212
- const manifest = await getStoredManifest(uri);
213
-
214
- // PART 2 - Add an error so the release license message fails.
215
- storage.getNetworkingEngine().registerRequestFilter(
216
- (type, request) => {
217
- if (type == shaka.net.NetworkingEngine.RequestType.LICENSE) {
218
- throw new Error('Error should be ignored');
219
- }
220
- });
221
-
222
- // PART 3 - Remove the manifest from storage. This should ignore the
223
- // error with the EME session. It should also store the session for
224
- // later removal.
225
- await storage.remove(uri.toString());
226
-
227
- // PART 4 - Verify the media was deleted but the session still exists.
228
- const storedContents = await storage.list();
229
- expect(storedContents).toEqual([]);
230
-
231
- await withDrm(player, manifest, (drm) => {
232
- return Promise.all(manifest.offlineSessionIds.map(async (session) => {
233
- const foundSession = await loadOfflineSession(drm, session);
234
- expect(foundSession).toBeTruthy();
235
- }));
236
- });
237
-
238
- // PART 5 - Disable the error and remove the EME session.
239
- storage.getNetworkingEngine().clearAllRequestFilters();
240
- const didRemoveAll = await storage.removeEmeSessions();
241
- expect(didRemoveAll).toBe(true);
242
-
243
- // PART 6 - Check that the licenses were removed.
244
- const p = withDrm(player, manifest, (drm) => {
245
- return Promise.all(manifest.offlineSessionIds.map(async (session) => {
246
- const notFoundSession = await loadOfflineSession(drm, session);
247
- expect(notFoundSession).toBeFalsy();
248
- }));
249
- });
250
- const expected = Util.jasmineError(new shaka.util.Error(
251
- shaka.util.Error.Severity.CRITICAL,
252
- shaka.util.Error.Category.DRM,
253
- shaka.util.Error.Code.OFFLINE_SESSION_REMOVED));
254
- await expectAsync(p).toBeRejectedWith(expected);
255
- });
256
- });
257
-
258
- describe('default track selection callback', () => {
259
- const PlayerConfiguration = shaka.util.PlayerConfiguration;
260
-
261
- it('selects the largest SD video with middle quality audio', () => {
262
- const tracks = [
263
- variantTrack(0, 360, englishUS, kbps(1.0)),
264
- variantTrack(1, 480, englishUS, kbps(2.0)),
265
- variantTrack(2, 480, englishUS, kbps(2.1)),
266
- variantTrack(3, 480, englishUS, kbps(2.2)),
267
- variantTrack(4, 720, englishUS, kbps(3.0)),
268
- variantTrack(5, 1080, englishUS, kbps(4.0)),
269
- ];
270
-
271
- const selected =
272
- PlayerConfiguration.defaultTrackSelect(tracks, englishUS, 'SDR');
273
- expect(selected).toBeTruthy();
274
- expect(selected.length).toBe(1);
275
- expect(selected[0]).toBeTruthy();
276
- expect(selected[0].language).toBe(englishUS);
277
- expect(selected[0].height).toBe(480);
278
- expect(selected[0].bandwidth).toBe(kbps(2.1));
279
- });
280
-
281
- it('selects all text tracks', () => {
282
- const tracks = [
283
- textTrack(0, englishUS),
284
- textTrack(1, frenchCanadian),
285
- ];
286
-
287
- const selected =
288
- PlayerConfiguration.defaultTrackSelect(tracks, englishUS, 'SDR');
289
- expect(selected).toBeTruthy();
290
- expect(selected.length).toBe(2);
291
- for (const track of tracks) {
292
- expect(selected).toContain(track);
293
- }
294
- });
295
-
296
- describe('language matching', () => {
297
- it('finds exact match', () => {
298
- const tracks = [
299
- variantTrack(0, 480, 'eng-us', kbps(1)),
300
- variantTrack(1, 480, 'fr-ca', kbps(1)),
301
- variantTrack(2, 480, 'eng-ca', kbps(1)),
302
- ];
303
-
304
- const selected =
305
- PlayerConfiguration.defaultTrackSelect(tracks, 'eng-us', 'SDR');
306
- expect(selected).toBeTruthy();
307
- expect(selected.length).toBe(1);
308
- expect(selected[0]).toBeTruthy();
309
- expect(selected[0].language).toBe('eng-us');
310
- });
311
-
312
- it('finds exact match with only base', () => {
313
- const tracks = [
314
- variantTrack(0, 480, 'eng-us', kbps(1)),
315
- variantTrack(1, 480, 'fr-ca', kbps(1)),
316
- variantTrack(2, 480, 'eng-ca', kbps(1)),
317
- variantTrack(3, 480, 'eng', kbps(1)),
318
- ];
319
-
320
- const selected =
321
- PlayerConfiguration.defaultTrackSelect(tracks, 'eng', 'SDR');
322
- expect(selected).toBeTruthy();
323
- expect(selected.length).toBe(1);
324
- expect(selected[0]).toBeTruthy();
325
- expect(selected[0].language).toBe('eng');
326
- });
327
-
328
- it('finds base match when exact match is not found', () => {
329
- const tracks = [
330
- variantTrack(0, 480, 'eng-us', kbps(1)),
331
- variantTrack(1, 480, 'fr-ca', kbps(1)),
332
- variantTrack(2, 480, 'eng-ca', kbps(1)),
333
- ];
334
-
335
- const selected =
336
- PlayerConfiguration.defaultTrackSelect(tracks, 'fr', 'SDR');
337
- expect(selected).toBeTruthy();
338
- expect(selected.length).toBe(1);
339
- expect(selected[0]).toBeTruthy();
340
- expect(selected[0].language).toBe('fr-ca');
341
- });
342
-
343
- it('finds common base when exact match is not found', () => {
344
- const tracks = [
345
- variantTrack(0, 480, 'eng-us', kbps(1)),
346
- variantTrack(1, 480, 'fr-ca', kbps(1)),
347
- variantTrack(2, 480, 'eng-ca', kbps(1)),
348
- ];
349
-
350
- const selected =
351
- PlayerConfiguration.defaultTrackSelect(tracks, 'fr-uk', 'SDR');
352
- expect(selected).toBeTruthy();
353
- expect(selected.length).toBe(1);
354
- expect(selected[0]).toBeTruthy();
355
- expect(selected[0].language).toBe('fr-ca');
356
- });
357
-
358
- it('finds primary track when no match is found', () => {
359
- const tracks = [
360
- variantTrack(0, 480, 'eng-us', kbps(1)),
361
- variantTrack(1, 480, 'fr-ca', kbps(1)),
362
- variantTrack(2, 480, 'eng-ca', kbps(1)),
363
- ];
364
-
365
- tracks[0].primary = true;
366
-
367
- const selected =
368
- PlayerConfiguration.defaultTrackSelect(tracks, 'de', 'SDR');
369
- expect(selected).toBeTruthy();
370
- expect(selected.length).toBe(1);
371
- expect(selected[0]).toBeTruthy();
372
- expect(selected[0].language).toBe('eng-us');
373
- });
374
- }); // describe('language matching')
375
- }); // describe('default track selection callback')
376
-
377
-
378
- describe('no support', () => {
379
- const expectedError = Util.jasmineError(new shaka.util.Error(
380
- shaka.util.Error.Severity.CRITICAL,
381
- shaka.util.Error.Category.STORAGE,
382
- shaka.util.Error.Code.STORAGE_NOT_SUPPORTED));
383
-
384
- /** @type {!shaka.Player} */
385
- let player;
386
- /** @type {!shaka.offline.Storage} */
387
- let storage;
388
-
389
- // CAUTION: Do not put overrideSupport() or clearSupport() in
390
- // beforEach/afterEach. They change what is supported at a static level.
391
- // When the test is run, a shim will call the support check and the test
392
- // will be skipped if overrideSupport() has been called already. A shim of
393
- // afterEach will call the same check and skip afterEach's body, too, and
394
- // the clean up will never happen. So the calls to overrideSupport() and
395
- // clearSupport() must be in each test using try/finally.
396
-
397
- beforeEach(() => {
398
- player = new shaka.Player();
399
- storage = new shaka.offline.Storage(player);
400
- // NOTE: See above "CAUTION" comment about overrideSupport/clearSupport.
401
- });
402
-
403
- afterEach(async () => {
404
- await storage.destroy();
405
- await player.destroy();
406
- // NOTE: See above "CAUTION" comment about overrideSupport/clearSupport.
407
- });
408
-
409
- it('throws error using list', async () => {
410
- try {
411
- shaka.offline.StorageMuxer.overrideSupport(new Map());
412
-
413
- await expectAsync(storage.list()).toBeRejectedWith(expectedError);
414
- } finally {
415
- shaka.offline.StorageMuxer.clearOverride();
416
- }
417
- });
418
-
419
- it('throws error using store', async () => {
420
- try {
421
- shaka.offline.StorageMuxer.overrideSupport(new Map());
422
-
423
- const store = storage.store('any-uri', noMetadata, fakeMimeType);
424
- await expectAsync(store.promise).toBeRejectedWith(expectedError);
425
- } finally {
426
- shaka.offline.StorageMuxer.clearOverride();
427
- }
428
- });
429
-
430
- it('throws error using remove', async () => {
431
- try {
432
- shaka.offline.StorageMuxer.overrideSupport(new Map());
433
-
434
- const remove = storage.remove('any-uri');
435
- await expectAsync(remove).toBeRejectedWith(expectedError);
436
- } finally {
437
- shaka.offline.StorageMuxer.clearOverride();
438
- }
439
- });
440
- });
441
-
442
- // Test that progress will be reported as we expect when manifests have
443
- // stream-level bandwidth information and when manifests only have
444
- // variant-level bandwidth information.
445
- //
446
- // Since we build our promise chains to allow each stream to be downloaded
447
- // in parallel (implementation detail) progress can be non-deterministic
448
- // as we see different promise resolution orders between browsers (and
449
- // runs). So to control this, we force resolution order for our network
450
- // requests in these tests.
451
- //
452
- // To allow us to control the network order, our manifests for these tests
453
- // could not repeat/reuse segments uris.
454
- describe('reports progress on store', () => {
455
- const audioSegment1Uri = 'fake:audio-segment-1';
456
- const audioSegment2Uri = 'fake:audio-segment-2';
457
- const audioSegment3Uri = 'fake:audio-segment-3';
458
- const audioSegment4Uri = 'fake:audio-segment-4';
459
-
460
- const videoSegment1Uri = 'fake:video-segment-1';
461
- const videoSegment2Uri = 'fake:video-segment-2';
462
- const videoSegment3Uri = 'fake:video-segment-3';
463
- const videoSegment4Uri = 'fake:video-segment-4';
464
-
465
- /** @type {!shaka.offline.Storage} */
466
- let storage;
467
-
468
- /** @type {!Object.<string, function():!Promise.<ArrayBuffer>>} */
469
- let fakeResponses = {};
470
-
471
- let compiledShaka;
472
-
473
- beforeAll(async () => {
474
- compiledShaka =
475
- await shaka.test.Loader.loadShaka(getClientArg('uncompiled'));
476
-
477
- compiledShaka.net.NetworkingEngine.registerScheme(
478
- 'fake', (uri, req, type, progress) => {
479
- if (fakeResponses[uri]) {
480
- const operation = async () => {
481
- const data = await fakeResponses[uri]();
482
- return {
483
- uri,
484
- data,
485
- headers: {},
486
- };
487
- };
488
- return shaka.util.AbortableOperation.notAbortable(operation());
489
- } else {
490
- return shaka.util.AbortableOperation.failed(
491
- new shaka.util.Error(
492
- shaka.util.Error.Severity.RECOVERABLE,
493
- shaka.util.Error.Category.NETWORK,
494
- shaka.util.Error.Code.HTTP_ERROR));
495
- }
496
- });
497
- });
498
-
499
- beforeEach(async () => {
500
- await shaka.test.TestScheme.createManifests(compiledShaka, '_compiled');
501
-
502
- storage = new compiledShaka.offline.Storage();
503
-
504
- // Since we are using specific manifest with only one video and one audio
505
- // we can return all the tracks.
506
- storage.configure({
507
- offline: {
508
- trackSelectionCallback: (tracks) => { return tracks; },
509
- },
510
- });
511
-
512
- // Use these promises to ensure that the data from networking
513
- // engine arrives in the correct order.
514
- const delays = {};
515
- delays[audioSegment1Uri] = new shaka.util.PublicPromise();
516
- delays[audioSegment2Uri] = new shaka.util.PublicPromise();
517
- delays[audioSegment3Uri] = new shaka.util.PublicPromise();
518
- delays[audioSegment4Uri] = new shaka.util.PublicPromise();
519
- delays[videoSegment1Uri] = new shaka.util.PublicPromise();
520
- delays[videoSegment2Uri] = new shaka.util.PublicPromise();
521
- delays[videoSegment3Uri] = new shaka.util.PublicPromise();
522
- delays[videoSegment4Uri] = new shaka.util.PublicPromise();
523
-
524
- /**
525
- * Since the promise chains will be built so that each stream can be
526
- * downloaded in parallel, we can force the network requests to
527
- * resolve in lock-step (audio seg 0, video seg 0, audio seg 1,
528
- * video seg 1, ...).
529
- *
530
- * @param {string} segment A URI
531
- * @param {?string} dependingOn Another URI, or null
532
- */
533
- function setResponseFor(segment, dependingOn) {
534
- fakeResponses[segment] = async () => {
535
- if (dependingOn) {
536
- await delays[dependingOn];
537
- }
538
-
539
- // Tell anyone waiting on |segment| that they are clear to execute
540
- // now.
541
- delays[segment].resolve();
542
- return new ArrayBuffer(16);
543
- };
544
- }
545
- fakeResponses = {};
546
- setResponseFor(audioSegment1Uri, null);
547
- setResponseFor(audioSegment2Uri, videoSegment1Uri);
548
- setResponseFor(audioSegment3Uri, videoSegment2Uri);
549
- setResponseFor(audioSegment4Uri, videoSegment3Uri);
550
- setResponseFor(videoSegment1Uri, audioSegment1Uri);
551
- setResponseFor(videoSegment2Uri, audioSegment2Uri);
552
- setResponseFor(videoSegment3Uri, audioSegment3Uri);
553
- setResponseFor(videoSegment4Uri, audioSegment4Uri);
554
- });
555
-
556
- afterEach(async () => {
557
- await storage.destroy();
558
- });
559
-
560
- afterAll(() => {
561
- compiledShaka.net.NetworkingEngine.unregisterScheme('fake');
562
- });
563
-
564
- it('uses stream bandwidth', async () => {
565
- /**
566
- * These numbers are the overall progress based on the segment sizes
567
- * per stream. We assume a specific download order for the content
568
- * based on the order of the streams and segments.
569
- *
570
- * Since the audio stream has smaller segments, its contribution to
571
- * the overall progress is much smaller than the video stream segments.
572
- *
573
- * @type {!Array.<number>}
574
- */
575
- const progressSteps = [
576
- 0.057, 0.250, 0.307, 0.500, 0.557, 0.750, 0.807, 1.000,
577
- ];
578
- const manifest = makeWithStreamBandwidth();
579
- await runProgressTest(manifest, progressSteps);
580
- });
581
-
582
- it('uses variant bandwidth when stream bandwidth is unavailable',
583
- async () => {
584
- /**
585
- * These numbers are the overall progress based on the segment sizes
586
- * per stream. We assume a specific download order for the content
587
- * based on the order of the streams and segments.
588
- *
589
- * Since we do not have per-stream bandwidth, the amount each
590
- * influences the overall progress is based on the stream type,
591
- * storage's default bandwidth assumptions, and the variant's
592
- * bandwidth.
593
- *
594
- * In this example we see a larger difference between the audio and
595
- * video contributions to progress.
596
- *
597
- * @type {!Array.<number>}
598
- */
599
- const progressSteps = [
600
- 0.241, 0.250, 0.491, 0.500, 0.741, 0.750, 0.991, 1.000,
601
- ];
602
- const manifest = makeWithVariantBandwidth();
603
- await runProgressTest(manifest, progressSteps);
604
- });
605
-
606
- /**
607
- * Download |manifest| and make sure that the reported progress matches
608
- * |expectedProgressSteps|.
609
- *
610
- * @param {shaka.extern.Manifest} manifest
611
- * @param {!Array.<number>} expectedProgressSteps
612
- */
613
- async function runProgressTest(manifest, expectedProgressSteps) {
614
- /**
615
- * Create a copy of the array so that we are not modifying the original
616
- * while we are tracking progress.
617
- *
618
- * @type {!Array.<number>}
619
- */
620
- const remainingProgress = expectedProgressSteps.slice();
621
-
622
- const progressCallback = (content, progress) => {
623
- expect(progress).toBeCloseTo(remainingProgress.shift());
624
- };
625
-
626
- storage.configure({
627
- offline: {
628
- progressCallback: progressCallback,
629
- },
630
- });
631
- compiledShaka.media.ManifestParser.registerParserByMime(
632
- fakeMimeType, () => new shaka.test.FakeManifestParser(manifest));
633
-
634
- // Store a manifest with bandwidth only for the variant (no per
635
- // stream bandwidth). This should result in a less accurate
636
- // progression of progress values as default values will be used.
637
- await storage.store('uri-wont-matter', noMetadata, fakeMimeType).promise;
638
-
639
- // We should have hit all the progress steps.
640
- expect(remainingProgress.length).toBe(0);
641
- }
642
-
643
- /**
644
- * Build a custom manifest for testing progress. Each segment will be
645
- * unique so that there will only be one request per segment uri (we
646
- * often reuse segments in our tests).
647
- *
648
- * This manifest will have the variant-level bandwidth value and per-stream
649
- * bandwidth values.
650
- *
651
- * @return {shaka.extern.Manifest}
652
- */
653
- function makeWithStreamBandwidth() {
654
- const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
655
- manifest.presentationTimeline.setDuration(20);
656
- manifest.addVariant(0, (variant) => {
657
- variant.language = englishUS;
658
- variant.bandwidth = kbps(13);
659
- variant.addVideo(1, (stream) => {
660
- stream.bandwidth = kbps(10);
661
- stream.size(100, 200);
662
- });
663
- variant.addAudio(2, (stream) => {
664
- stream.language = englishUS;
665
- stream.bandwidth = kbps(3);
666
- });
667
- });
668
- }, compiledShaka);
669
-
670
- const audio = manifest.variants[0].audio;
671
- goog.asserts.assert(audio, 'Created manifest with audio, where is it?');
672
- overrideSegmentIndex(audio, [
673
- makeReference(audioSegment1Uri, 0, 1, compiledShaka),
674
- makeReference(audioSegment2Uri, 1, 2, compiledShaka),
675
- makeReference(audioSegment3Uri, 2, 3, compiledShaka),
676
- makeReference(audioSegment4Uri, 3, 4, compiledShaka),
677
- ]);
678
-
679
- const video = manifest.variants[0].video;
680
- goog.asserts.assert(video, 'Created manifest with video, where is it?');
681
- overrideSegmentIndex(video, [
682
- makeReference(videoSegment1Uri, 0, 1, compiledShaka),
683
- makeReference(videoSegment2Uri, 1, 2, compiledShaka),
684
- makeReference(videoSegment3Uri, 2, 3, compiledShaka),
685
- makeReference(videoSegment4Uri, 3, 4, compiledShaka),
686
- ]);
687
-
688
- return manifest;
689
- }
690
-
691
- /**
692
- * Build a custom manifest for testing progress. Each segment will be
693
- * unique so that there will only be one request per segment uri (we
694
- * often reuse segments in our tests).
695
- *
696
- * This manifest will only have the variant-level bandwidth value.
697
- *
698
- * @return {shaka.extern.Manifest}
699
- */
700
- function makeWithVariantBandwidth() {
701
- // Start with the manifest that had per-stream bandwidths. Then remove
702
- // the per-stream values.
703
- const manifest = makeWithStreamBandwidth();
704
- goog.asserts.assert(
705
- manifest.variants.length == 1,
706
- 'Expecting manifest to only have one variant');
707
-
708
- const variant = manifest.variants[0];
709
- goog.asserts.assert(
710
- variant.audio,
711
- 'Expecting manifest to have audio stream');
712
- goog.asserts.assert(
713
- variant.video,
714
- 'Expecting manigest to have video stream');
715
-
716
- // Remove the per stream bandwidth information.
717
- variant.audio.bandwidth = undefined;
718
- variant.video.bandwidth = undefined;
719
-
720
- return manifest;
721
- }
722
- });
723
-
724
- describe('basic function', () => {
725
- /**
726
- * Keep a reference to the networking engine so that we can interrupt
727
- * networking calls.
728
- *
729
- * @type {!shaka.test.FakeNetworkingEngine}
730
- */
731
- let netEngine;
732
- /** @type {!shaka.Player} */
733
- let player;
734
- /** @type {!shaka.offline.Storage} */
735
- let storage;
736
- /** @type {!shaka.util.EventManager} */
737
- let eventManager;
738
- /** @type {!HTMLVideoElement} */
739
- const videoElement = /** @type {!HTMLVideoElement} */(
740
- document.createElement('video'));
741
-
742
- beforeEach(async () => {
743
- netEngine = makeNetworkEngine();
744
-
745
- // Use a real Player since Storage only uses the configuration and
746
- // networking engine. This allows us to use Player.configure in these
747
- // tests.
748
- player = new shaka.Player(null, ((player) => {
749
- player.createNetworkingEngine = () => netEngine;
750
- }));
751
- await player.attach(videoElement);
752
-
753
- storage = new shaka.offline.Storage(player);
754
-
755
- eventManager = new shaka.util.EventManager();
756
- });
757
-
758
- afterEach(async () => {
759
- eventManager.release();
760
- await storage.destroy();
761
- await player.destroy();
762
- });
763
-
764
- it('stores and lists content', async () => {
765
- /** @type {!Array.<string>} */
766
- const manifestUris = [
767
- manifestWithPerStreamBandwidthUri,
768
- manifestWithoutPerStreamBandwidthUri,
769
- manifestWithNonZeroStartUri,
770
- ];
771
-
772
- // NOTE: We're working around an apparent compiler bug here, with Closure
773
- // version v20180402. "Violation: Using properties of unknown types is
774
- // not allowed; add an explicit type to the variable. The property "next"
775
- // on type "Iterator<?>".
776
- for (let i = 0; i < manifestUris.length; ++i) {
777
- const uri = manifestUris[i];
778
- // eslint-disable-next-line no-await-in-loop
779
- await storage.store(uri, noMetadata, fakeMimeType).promise;
780
- }
781
-
782
- const content = await storage.list();
783
- const originalUris = content.map((c) => c.originalManifestUri);
784
- expect(originalUris.length).toBe(manifestUris.length);
785
-
786
- // NOTE: We're working around an apparent compiler bug here. See comment
787
- // above.
788
- for (let i = 0; i < manifestUris.length; ++i) {
789
- const uri = manifestUris[i];
790
- expect(originalUris).toContain(uri);
791
- }
792
- });
793
-
794
- it('snapshots config when store is called', async () => {
795
- /** @type {!jasmine.Spy} */
796
- const selectTracksOne =
797
- jasmine.createSpy('selectTracksOne').and.callFake((tracks) => tracks);
798
- /** @type {!jasmine.Spy} */
799
- const selectTracksTwo =
800
- jasmine.createSpy('selectTracksTwo').and.callFake((tracks) => tracks);
801
- /** @type {!jasmine.Spy} */
802
- const selectTracksBad =
803
- jasmine.createSpy('selectTracksBad').and.callFake((tracks) => []);
804
-
805
- storage.configure('offline.trackSelectionCallback', selectTracksOne);
806
- const storeOne = storage.store(
807
- manifestWithPerStreamBandwidthUri, noMetadata, fakeMimeType);
808
- storage.configure('offline.trackSelectionCallback', selectTracksTwo);
809
- const storeTwo = storage.store(
810
- manifestWithPerStreamBandwidthUri, noMetadata, fakeMimeType);
811
- storage.configure('offline.trackSelectionCallback', selectTracksBad);
812
- await Promise.all([storeOne.promise, storeTwo.promise]);
813
-
814
- expect(selectTracksOne).toHaveBeenCalled();
815
- expect(selectTracksTwo).toHaveBeenCalled();
816
- expect(selectTracksBad).not.toHaveBeenCalled();
817
- });
818
-
819
- it('only stores chosen tracks', async () => {
820
- // Change storage to only store one track so that it will be easy
821
- // for us to ensure that only the one track was stored.
822
- const selectTracks = (tracks) => {
823
- const selected = tracks.filter((t) => t.language == frenchCanadian);
824
- expect(selected.length).toBe(1);
825
- return selected;
826
- };
827
- storage.configure({
828
- offline: {
829
- trackSelectionCallback: selectTracks,
830
- },
831
- });
832
-
833
- const stored = await storage.store(
834
- manifestWithPerStreamBandwidthUri, noMetadata, fakeMimeType).promise;
835
- goog.asserts.assert(stored.offlineUri != null, 'URI should not be null!');
836
- expect(stored.tracks.length).toBe(1);
837
- expect(stored.tracks[0].language).toBe(frenchCanadian);
838
-
839
- // Pull the manifest out of storage so that we can ensure that it only
840
- // has one variant.
841
- /** @type {shaka.offline.OfflineUri} */
842
- const uri = shaka.offline.OfflineUri.parse(stored.offlineUri);
843
-
844
- /** @type {!shaka.offline.StorageMuxer} */
845
- const muxer = new shaka.offline.StorageMuxer();
846
-
847
- try {
848
- await muxer.init();
849
- const cell = await muxer.getCell(uri.mechanism(), uri.cell());
850
- const manifests = await cell.getManifests([uri.key()]);
851
- expect(manifests.length).toBe(1);
852
-
853
- const manifest = manifests[0];
854
- // There should be 2 streams, an audio and a video stream.
855
- expect(manifest.streams.length).toBe(2);
856
-
857
- const audio = manifest.streams.filter(
858
- (s) => s.type == 'audio')[0];
859
- expect(audio.language).toBe(frenchCanadian);
860
- } finally {
861
- await muxer.destroy();
862
- }
863
- });
864
-
865
- it('can choose tracks asynchronously', async () => {
866
- storage.configure({
867
- offline: {
868
- trackSelectionCallback: async (tracks) => {
869
- await Util.delay(0.1);
870
- const selected = tracks.filter((t) => t.language == frenchCanadian);
871
- expect(selected.length).toBe(1);
872
- return selected;
873
- },
874
- },
875
- });
876
-
877
- const stored = await storage.store(
878
- manifestWithPerStreamBandwidthUri, noMetadata, fakeMimeType).promise;
879
- expect(stored.tracks.length).toBe(1);
880
- expect(stored.tracks[0].language).toBe(frenchCanadian);
881
- });
882
-
883
- it('stores drm info without license', async () => {
884
- const drmInfo = makeDrmInfo();
885
- const session1 = 'session-1';
886
- const session2 = 'session-2';
887
- const expiration = 1000;
888
-
889
- // TODO(vaage): Is there a way we can set the session ids without needing
890
- // to overload an internal call in storage.
891
- const drm = new shaka.test.FakeDrmEngine();
892
- drm.setDrmInfo(drmInfo);
893
- drm.setSessionIds([session1, session2]);
894
- drm.getExpiration.and.returnValue(expiration);
895
-
896
- overrideDrmAndManifest(
897
- storage,
898
- drm,
899
- makeManifestWithPerStreamBandwidth());
900
-
901
- const stored = await storage.store(
902
- manifestWithPerStreamBandwidthUri, noMetadata, fakeMimeType).promise;
903
- goog.asserts.assert(stored.offlineUri != null, 'URI should not be null!');
904
-
905
- /** @type {shaka.offline.OfflineUri} */
906
- const uri = shaka.offline.OfflineUri.parse(stored.offlineUri);
907
- expect(uri).toBeTruthy();
908
-
909
- /** @type {!shaka.offline.StorageMuxer} */
910
- const muxer = new shaka.offline.StorageMuxer();
911
-
912
- try {
913
- await muxer.init();
914
- const cell = await muxer.getCell(uri.mechanism(), uri.cell());
915
- const manifests = await cell.getManifests([uri.key()]);
916
- const manifest = manifests[0];
917
- expect(manifest).toBeTruthy();
918
-
919
- expect(manifest.drmInfo).toEqual(drmInfo);
920
-
921
- expect(manifest.expiration).toBe(expiration);
922
-
923
- expect(manifest.sessionIds).toBeTruthy();
924
- expect(manifest.sessionIds.length).toBe(2);
925
- expect(manifest.sessionIds).toContain(session1);
926
- expect(manifest.sessionIds).toContain(session2);
927
- } finally {
928
- await muxer.destroy();
929
- }
930
- });
931
-
932
- it('can extract DRM info from segments', async () => {
933
- const pssh1 =
934
- '00000028' + // atom size
935
- '70737368' + // atom type='pssh'
936
- '00000000' + // v0, flags=0
937
- 'edef8ba979d64acea3c827dcd51d21ed' + // system id (Widevine)
938
- '00000008' + // data size
939
- '0102030405060708'; // data
940
- const psshData1 = shaka.util.Uint8ArrayUtils.fromHex(pssh1);
941
- const pssh2 =
942
- '00000028' + // atom size
943
- '70737368' + // atom type='pssh'
944
- '00000000' + // v0, flags=0
945
- 'edef8ba979d64acea3c827dcd51d21ed' + // system id (Widevine)
946
- '00000008' + // data size
947
- '1337420123456789'; // data
948
- const psshData2 = shaka.util.Uint8ArrayUtils.fromHex(pssh2);
949
- netEngine.setResponseValue(initSegmentUri,
950
- shaka.util.BufferUtils.toArrayBuffer(psshData1));
951
- netEngine.setResponseValue(alternateInitSegmentUri,
952
- shaka.util.BufferUtils.toArrayBuffer(psshData2));
953
-
954
- const drm = new shaka.test.FakeDrmEngine();
955
- const drmInfo = makeDrmInfo();
956
- drmInfo.keySystem = 'com.widevine.alpha';
957
- drm.setDrmInfo(drmInfo);
958
- overrideDrmAndManifest(
959
- storage,
960
- drm,
961
- makeManifestWithVideoInitSegments());
962
-
963
- const stored = await storage.store(
964
- manifestWithVideoInitSegmentsUri, noMetadata, fakeMimeType).promise;
965
- goog.asserts.assert(stored.offlineUri != null, 'URI should not be null!');
966
-
967
- // The manifest chooses the alternate stream, so expect only the alt init
968
- // segment.
969
- expect(drm.newInitData).toHaveBeenCalledWith('cenc', psshData2);
970
- });
971
-
972
- it('can store multiple assets at once', async () => {
973
- // Block the network so that we won't finish the first store command.
974
- /** @type {!shaka.util.PublicPromise} */
975
- const hangingPromise = netEngine.delayNextRequest();
976
- /** @type {!shaka.extern.IAbortableOperation} */
977
- const storeOperation = storage.store(
978
- manifestWithPerStreamBandwidthUri, noMetadata, fakeMimeType);
979
-
980
- // Critical: This manifest should have different segment URIs than the one
981
- // above, or else the blocked network request would be shared between the
982
- // two storage operations.
983
- const secondStorePromise = storage.store(
984
- manifestWithAlternateSegmentsUri, noMetadata, fakeMimeType);
985
- await secondStorePromise.promise;
986
-
987
- // Unblock the original store and wait for it to complete.
988
- hangingPromise.resolve();
989
- await storeOperation.promise;
990
- });
991
-
992
- // Make sure that when we configure storage to NOT store persistent
993
- // licenses that we don't store the sessions.
994
- it('stores drm info with no license', async () => {
995
- const drmInfo = makeDrmInfo();
996
- const session1 = 'session-1';
997
- const session2 = 'session-2';
998
-
999
- // TODO(vaage): Is there a way we can set the session ids without
1000
- // needing to overload an internal call in storage.
1001
- const drm = new shaka.test.FakeDrmEngine();
1002
- drm.setDrmInfo(drmInfo);
1003
- drm.setSessionIds([session1, session2]);
1004
-
1005
- overrideDrmAndManifest(
1006
- storage,
1007
- drm,
1008
- makeManifestWithPerStreamBandwidth());
1009
- storage.configure('offline.usePersistentLicense', false);
1010
-
1011
- const stored = await storage.store(
1012
- manifestWithPerStreamBandwidthUri, noMetadata, fakeMimeType).promise;
1013
- goog.asserts.assert(stored.offlineUri != null, 'URI should not be null!');
1014
-
1015
- /** @type {shaka.offline.OfflineUri} */
1016
- const uri = shaka.offline.OfflineUri.parse(stored.offlineUri);
1017
- expect(uri).toBeTruthy();
1018
-
1019
- /** @type {!shaka.offline.StorageMuxer} */
1020
- const muxer = new shaka.offline.StorageMuxer();
1021
-
1022
- try {
1023
- await muxer.init();
1024
- const cell = await muxer.getCell(uri.mechanism(), uri.cell());
1025
- const manifests = await cell.getManifests([uri.key()]);
1026
- const manifest = manifests[0];
1027
- expect(manifest).toBeTruthy();
1028
-
1029
- expect(manifest.drmInfo).toEqual(drmInfo);
1030
-
1031
- // When there is no expiration, the expiration is set to Infinity.
1032
- expect(manifest.expiration).toBe(Infinity);
1033
-
1034
- expect(manifest.sessionIds).toBeTruthy();
1035
- expect(manifest.sessionIds.length).toBe(0);
1036
- } finally {
1037
- await muxer.destroy();
1038
- }
1039
- });
1040
-
1041
- /**
1042
- * In some situations, indexedDB.open() can just hang, and call neither the
1043
- * 'success' nor the 'error' callbacks.
1044
- * I'm not sure what causes it, but it seems to happen consistently between
1045
- * reloads when it does so it might be a browser-based issue.
1046
- * In that case, we should time out with an error, instead of also hanging.
1047
- */
1048
- it('throws an error if indexedDB open times out', async () => {
1049
- const oldOpen = window.indexedDB.open;
1050
- window.indexedDB.open = () => {
1051
- // Just return a dummy object.
1052
- return /** @type {!IDBOpenDBRequest} */ ({
1053
- onsuccess: (event) => {},
1054
- onerror: (error) => {},
1055
- });
1056
- };
1057
-
1058
- /** @type {!shaka.offline.StorageMuxer} */
1059
- const muxer = new shaka.offline.StorageMuxer();
1060
- const expectedError = shaka.test.Util.jasmineError(new shaka.util.Error(
1061
- shaka.util.Error.Severity.CRITICAL,
1062
- shaka.util.Error.Category.STORAGE,
1063
- shaka.util.Error.Code.INDEXED_DB_INIT_TIMED_OUT));
1064
-
1065
- await expectAsync(muxer.init())
1066
- .toBeRejectedWith(expectedError);
1067
-
1068
- window.indexedDB.open = oldOpen;
1069
- });
1070
-
1071
- it('throws an error if the content is a live stream', async () => {
1072
- const expected = Util.jasmineError(new shaka.util.Error(
1073
- shaka.util.Error.Severity.CRITICAL,
1074
- shaka.util.Error.Category.STORAGE,
1075
- shaka.util.Error.Code.CANNOT_STORE_LIVE_OFFLINE,
1076
- manifestWithLiveTimelineUri));
1077
- const storeOperation =
1078
- storage.store(manifestWithLiveTimelineUri, noMetadata, fakeMimeType);
1079
- await expectAsync(storeOperation.promise).toBeRejectedWith(expected);
1080
- });
1081
-
1082
- it('throws an error if destroyed mid-store', async () => {
1083
- const manifest = makeManifestWithPerStreamBandwidth();
1084
-
1085
- /**
1086
- * Block storage when it goes to parse the manifest. Since we don't want
1087
- * to change the flow, return a valid manifest once it resolves.
1088
- * @type {shaka.util.PublicPromise}
1089
- */
1090
- const stallStorage = new shaka.util.PublicPromise();
1091
- storage.parseManifest = async () => {
1092
- await stallStorage;
1093
- return manifest;
1094
- };
1095
-
1096
- // The uri won't matter much, as we have overriden |parseManifest|.
1097
- /** @type {!shaka.extern.IAbortableOperation} */
1098
- const waitOnStore = storage.store('any-uri', noMetadata, fakeMimeType);
1099
-
1100
- // Request for storage to be destroyed. Before waiting for it to resolve,
1101
- // resolve the promise that we are using to stall the store operation.
1102
- const waitOnDestroy = storage.destroy();
1103
- stallStorage.resolve();
1104
- await waitOnDestroy;
1105
-
1106
- // The store request should not resolve, but instead be rejected.
1107
- const expected = Util.jasmineError(new shaka.util.Error(
1108
- shaka.util.Error.Severity.CRITICAL,
1109
- shaka.util.Error.Category.STORAGE,
1110
- shaka.util.Error.Code.OPERATION_ABORTED));
1111
- await expectAsync(waitOnStore.promise).toBeRejectedWith(expected);
1112
- });
1113
-
1114
- it('cancels downloads if destroyed mid-store', async () => {
1115
- await networkCancelTest((abortable) => {
1116
- return storage.destroy();
1117
- });
1118
- });
1119
-
1120
- it('cancels downloads if canceled mid-store', async () => {
1121
- await networkCancelTest((abortable) => {
1122
- return abortable.abort();
1123
- });
1124
- });
1125
-
1126
- /**
1127
- * @param {function(shaka.extern.IAbortableOperation):!Promise} interruption
1128
- */
1129
- async function networkCancelTest(interruption) {
1130
- const delays = [];
1131
- /** @type {!shaka.util.PublicPromise} */
1132
- const aRequestIsStarted = new shaka.util.PublicPromise();
1133
-
1134
- // Set delays for the URIs of the manifest.
1135
- const uris = [segment1Uri, segment2Uri, segment3Uri, segment4Uri];
1136
- for (let i = 0; i < uris.length; i++) {
1137
- const promise = new shaka.util.PublicPromise();
1138
- delays.push(promise);
1139
-
1140
- // The fake networking engine provides a "abortCheck" callback to the
1141
- // response, so that you can check whether or not the network operation
1142
- // has been aborted.
1143
- netEngine.setResponse(uris[i], async (abortCheck) => {
1144
- aRequestIsStarted.resolve();
1145
- await promise;
1146
-
1147
- expect(abortCheck()).toBe(true);
1148
-
1149
- return new ArrayBuffer(16);
1150
- });
1151
- }
1152
-
1153
- /** @type {!shaka.extern.IAbortableOperation} */
1154
- const storeOperation = storage.store(
1155
- manifestWithPerStreamBandwidthUri, noMetadata, fakeMimeType);
1156
- await aRequestIsStarted;
1157
- const interruptionPromise = interruption(storeOperation);
1158
- for (const promise of delays) {
1159
- promise.resolve();
1160
- }
1161
- await interruptionPromise;
1162
-
1163
- const expected = Util.jasmineError(new shaka.util.Error(
1164
- shaka.util.Error.Severity.CRITICAL,
1165
- shaka.util.Error.Category.STORAGE,
1166
- shaka.util.Error.Code.OPERATION_ABORTED));
1167
- await expectAsync(storeOperation.promise).toBeRejectedWith(expected);
1168
- }
1169
-
1170
- it('stops for networking errors', async () => {
1171
- // Force all network requests to fail.
1172
- const error = new shaka.util.Error(
1173
- shaka.util.Error.Severity.CRITICAL, shaka.util.Error.Category.NETWORK,
1174
- shaka.util.Error.Code.HTTP_ERROR);
1175
- netEngine.request.and.callFake(() => {
1176
- return shaka.util.AbortableOperation.failed(error);
1177
- });
1178
-
1179
- const storeOperation = storage.store(
1180
- manifestWithPerStreamBandwidthUri, noMetadata, fakeMimeType);
1181
- await expectAsync(storeOperation.promise)
1182
- .toBeRejectedWith(Util.jasmineError(error));
1183
- });
1184
-
1185
- it('throws an error if removing malformed uri', async () => {
1186
- const badUri = 'this-is-an-invalid-uri';
1187
- const expected = Util.jasmineError(new shaka.util.Error(
1188
- shaka.util.Error.Severity.CRITICAL,
1189
- shaka.util.Error.Category.STORAGE,
1190
- shaka.util.Error.Code.MALFORMED_OFFLINE_URI,
1191
- badUri));
1192
- await expectAsync(storage.remove(badUri)).toBeRejectedWith(expected);
1193
- });
1194
-
1195
- it('throws an error if removing missing manifest', async () => {
1196
- // Store a piece of content, but then change the uri slightly so that
1197
- // it won't be found when we try to remove it (with the wrong uri).
1198
- const stored = await storage.store(
1199
- manifestWithPerStreamBandwidthUri, noMetadata, fakeMimeType).promise;
1200
- goog.asserts.assert(stored.offlineUri != null, 'URI should not be null!');
1201
- const storedUri = shaka.offline.OfflineUri.parse(stored.offlineUri);
1202
- const missingManifestUri = shaka.offline.OfflineUri.manifest(
1203
- storedUri.mechanism(), storedUri.cell(), storedUri.key() + 1);
1204
-
1205
- const expected = Util.jasmineError(new shaka.util.Error(
1206
- shaka.util.Error.Severity.CRITICAL,
1207
- shaka.util.Error.Category.STORAGE,
1208
- shaka.util.Error.Code.KEY_NOT_FOUND,
1209
- jasmine.any(String)));
1210
- await expectAsync(storage.remove(missingManifestUri.toString()))
1211
- .toBeRejectedWith(expected);
1212
- });
1213
-
1214
- it('removes manifest', async () => {
1215
- const stored = await storage.store(
1216
- manifestWithPerStreamBandwidthUri, noMetadata, fakeMimeType).promise;
1217
- goog.asserts.assert(stored.offlineUri != null, 'URI should not be null!');
1218
- await storage.remove(stored.offlineUri);
1219
- });
1220
-
1221
- it('removes manifest with missing segments', async () => {
1222
- const stored = await storage.store(
1223
- manifestWithPerStreamBandwidthUri, noMetadata, fakeMimeType).promise;
1224
- goog.asserts.assert(stored.offlineUri != null, 'URI should not be null!');
1225
-
1226
- /** @type {shaka.offline.OfflineUri} */
1227
- const uri = shaka.offline.OfflineUri.parse(stored.offlineUri);
1228
- expect(uri).toBeTruthy();
1229
-
1230
- /** @type {!shaka.offline.StorageMuxer} */
1231
- const muxer = new shaka.offline.StorageMuxer();
1232
-
1233
- try {
1234
- await muxer.init();
1235
- const cell = await muxer.getCell(uri.mechanism(), uri.cell());
1236
- const manifests = await cell.getManifests([uri.key()]);
1237
- const manifest = manifests[0];
1238
-
1239
- // Get the stream from the manifest. The segment count is based on how
1240
- // we created manifest in the "make*Manifest" functions.
1241
- const stream = manifest.streams[0];
1242
- expect(stream).toBeTruthy();
1243
- expect(stream.segments.length).toBe(4);
1244
-
1245
- // Remove all the segments so that all segments will be missing.
1246
- // There should be way more than one segment.
1247
- const keys = stream.segments.map((segment) => segment.dataKey);
1248
- expect(keys.length).toBeGreaterThan(0);
1249
-
1250
- const noop = () => {};
1251
- await cell.removeSegments(keys, noop);
1252
- } finally {
1253
- await muxer.destroy();
1254
- }
1255
-
1256
- await storage.remove(uri.toString());
1257
- });
1258
-
1259
- it('tracks progress on remove', async () => {
1260
- const selectOneTrack = (tracks) => {
1261
- const allVariants = tracks.filter((t) => {
1262
- return t.type == 'variant';
1263
- });
1264
- expect(allVariants).toBeTruthy();
1265
- expect(allVariants.length).toBeGreaterThan(0);
1266
-
1267
- const frenchVariants = allVariants.filter((t) => {
1268
- return t.language == frenchCanadian;
1269
- });
1270
- expect(frenchVariants).toBeTruthy();
1271
- expect(frenchVariants.length).toBe(1);
1272
-
1273
- return frenchVariants;
1274
- };
1275
-
1276
- // Store a manifest with one track. We are using only one track so that it
1277
- // will be easier to understand the progress values.
1278
- storage.configure({
1279
- offline: {
1280
- trackSelectionCallback: selectOneTrack,
1281
- },
1282
- });
1283
- const content = await storage.store(
1284
- manifestWithPerStreamBandwidthUri, noMetadata, fakeMimeType).promise;
1285
- goog.asserts.assert(
1286
- content.offlineUri != null, 'URI should not be null!');
1287
-
1288
- // We expect 5 progress events because there are 4 unique segments, plus
1289
- // the manifest.
1290
- /** @type {!Array.<number>}*/
1291
- const progressSteps = [
1292
- 0.2, 0.4, 0.6, 0.8, 1,
1293
- ];
1294
-
1295
- const progressCallback = (content, progress) => {
1296
- expect(progress).toBeCloseTo(progressSteps.shift());
1297
- };
1298
-
1299
- storage.configure({
1300
- offline: {
1301
- progressCallback: progressCallback,
1302
- },
1303
- });
1304
-
1305
- await storage.remove(content.offlineUri);
1306
- expect(progressSteps).toBeTruthy();
1307
- expect(progressSteps.length).toBe(0);
1308
- });
1309
- });
1310
-
1311
- describe('storage without player', () => {
1312
- const testSchemeMimeType = 'application/x-test-manifest';
1313
- const manifestUri = 'test:sintel';
1314
-
1315
- it('stores content', async () => {
1316
- /** @type {shaka.offline.Storage} */
1317
- const storage = new shaka.offline.Storage();
1318
- try {
1319
- await storage.store(
1320
- manifestUri, noMetadata, testSchemeMimeType).promise;
1321
- } finally {
1322
- await storage.destroy();
1323
- }
1324
- });
1325
- });
1326
-
1327
- describe('deduplication', () => {
1328
- const testSchemeMimeType = 'application/x-test-manifest';
1329
- const manifestUri = 'test:sintel';
1330
-
1331
- // Regression test for https://github.com/shaka-project/shaka-player/issues/2781
1332
- it('does not cache failures or cancellations', async () => {
1333
- /** @type {shaka.offline.Storage} */
1334
- const storage = new shaka.offline.Storage();
1335
-
1336
- try {
1337
- storage.getNetworkingEngine().registerRequestFilter(
1338
- (type, request) => {
1339
- if (type == shaka.net.NetworkingEngine.RequestType.SEGMENT) {
1340
- throw new Error('Break download!');
1341
- }
1342
- });
1343
-
1344
- const firstOperation = storage.store(
1345
- manifestUri, noMetadata, testSchemeMimeType);
1346
- // We killed the operation with a network failure, so this should be
1347
- // rejected.
1348
- await expectAsync(firstOperation.promise).toBeRejected();
1349
-
1350
- // Clear the filter that caused the error.
1351
- storage.getNetworkingEngine().clearAllRequestFilters();
1352
-
1353
- // Now we can try again, and it should be able to succeed, even though
1354
- // some downloads for the same URIs failed in the first attempt. In
1355
- // #2781, this would fail because the network failure was cached.
1356
- const secondOperation = storage.store(
1357
- manifestUri, noMetadata, testSchemeMimeType);
1358
- await expectAsync(secondOperation.promise).toBeResolved();
1359
- } finally {
1360
- await storage.destroy();
1361
- }
1362
- });
1363
- });
1364
-
1365
- /**
1366
- * @param {number} id
1367
- * @param {number} height
1368
- * @param {string} language
1369
- * @param {number} bandwidth
1370
- * @return {shaka.extern.Track}
1371
- */
1372
- function variantTrack(id, height, language, bandwidth) {
1373
- const videoId = id * 2;
1374
- const audioId = id * 2 + 1;
1375
- return {
1376
- id: id,
1377
- active: false,
1378
- type: 'variant',
1379
- bandwidth: bandwidth,
1380
- language: language,
1381
- originalLanguage: language,
1382
- label: null,
1383
- kind: null,
1384
- width: height * (16 / 9),
1385
- height: height,
1386
- frameRate: 30,
1387
- pixelAspectRatio: '59:54',
1388
- hdr: null,
1389
- videoLayout: null,
1390
- mimeType: 'video/mp4,audio/mp4',
1391
- audioMimeType: 'audio/mp4',
1392
- videoMimeType: 'video/mp4',
1393
- codecs: 'mp4,mp4',
1394
- audioCodec: 'mp4',
1395
- videoCodec: 'mp4',
1396
- primary: false,
1397
- roles: [],
1398
- audioRoles: [],
1399
- forced: false,
1400
- videoId: videoId,
1401
- audioId: audioId,
1402
- channelsCount: 2,
1403
- audioSamplingRate: 48000,
1404
- spatialAudio: false,
1405
- tilesLayout: null,
1406
- audioBandwidth: bandwidth * 0.33,
1407
- videoBandwidth: bandwidth * 0.67,
1408
- originalVideoId: videoId.toString(),
1409
- originalAudioId: audioId.toString(),
1410
- originalTextId: null,
1411
- originalImageId: null,
1412
- accessibilityPurpose: null,
1413
- };
1414
- }
1415
-
1416
- /**
1417
- * @param {number} id
1418
- * @param {string} language
1419
- * @return {shaka.extern.Track}
1420
- */
1421
- function textTrack(id, language) {
1422
- return {
1423
- id: id,
1424
- active: false,
1425
- type: 'text',
1426
- bandwidth: 1000,
1427
- language: language,
1428
- originalLanguage: language,
1429
- label: null,
1430
- kind: null,
1431
- width: null,
1432
- height: null,
1433
- frameRate: null,
1434
- pixelAspectRatio: null,
1435
- hdr: null,
1436
- videoLayout: null,
1437
- mimeType: 'text/vtt',
1438
- audioMimeType: null,
1439
- videoMimeType: null,
1440
- codecs: 'vtt',
1441
- audioCodec: null,
1442
- videoCodec: null,
1443
- primary: false,
1444
- roles: [],
1445
- audioRoles: null,
1446
- forced: false,
1447
- videoId: null,
1448
- audioId: null,
1449
- channelsCount: null,
1450
- audioSamplingRate: null,
1451
- spatialAudio: false,
1452
- tilesLayout: null,
1453
- audioBandwidth: null,
1454
- videoBandwidth: null,
1455
- originalVideoId: null,
1456
- originalAudioId: null,
1457
- originalTextId: id.toString(),
1458
- originalImageId: null,
1459
- accessibilityPurpose: null,
1460
- };
1461
- }
1462
-
1463
- /** @return {shaka.extern.Manifest} */
1464
- function makeManifestWithVideoInitSegments() {
1465
- const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
1466
- manifest.presentationTimeline.setDuration(20);
1467
-
1468
- manifest.addVariant(0, (variant) => {
1469
- variant.bandwidth = kbps(13);
1470
- variant.addVideo(1, (stream) => {
1471
- stream.bandwidth = kbps(13);
1472
- stream.size(100, 200);
1473
- });
1474
- });
1475
- manifest.addVariant(2, (variant) => {
1476
- variant.bandwidth = kbps(20);
1477
- variant.addVideo(3, (stream) => {
1478
- stream.bandwidth = kbps(20);
1479
- stream.size(200, 400);
1480
- });
1481
- });
1482
- });
1483
-
1484
- const stream = manifest.variants[0].video;
1485
- goog.asserts.assert(stream, 'The first stream should exist');
1486
- stream.encrypted = true;
1487
- const init = new shaka.media.InitSegmentReference(
1488
- () => [initSegmentUri], 0, null);
1489
- const refs = [
1490
- makeReference(segment1Uri, 0, 1),
1491
- makeReference(segment2Uri, 1, 2),
1492
- makeReference(segment3Uri, 2, 3),
1493
- makeReference(segment4Uri, 3, 4),
1494
- ];
1495
- for (const ref of refs) {
1496
- ref.initSegmentReference = init;
1497
- }
1498
- overrideSegmentIndex(stream, refs);
1499
-
1500
- const streamAlt = manifest.variants[1].video;
1501
- goog.asserts.assert(streamAlt, 'The second stream should exist');
1502
- streamAlt.encrypted = true;
1503
- const initAlt = new shaka.media.InitSegmentReference(
1504
- () => [alternateInitSegmentUri], 0, null);
1505
- const refsAlt = [
1506
- makeReference(alternateSegment1Uri, 0, 1),
1507
- makeReference(alternateSegment2Uri, 1, 2),
1508
- makeReference(alternateSegment3Uri, 2, 3),
1509
- makeReference(alternateSegment4Uri, 3, 4),
1510
- ];
1511
- for (const ref of refsAlt) {
1512
- ref.initSegmentReference = initAlt;
1513
- }
1514
- overrideSegmentIndex(streamAlt, refsAlt);
1515
-
1516
- return manifest;
1517
- }
1518
-
1519
- /** @return {shaka.extern.Manifest} */
1520
- function makeManifestWithPerStreamBandwidth() {
1521
- const manifest = shaka.test.ManifestGenerator.generate((manifest) => {
1522
- manifest.presentationTimeline.setDuration(20);
1523
-
1524
- manifest.addVariant(0, (variant) => {
1525
- variant.language = englishUS;
1526
- variant.bandwidth = kbps(13);
1527
- variant.addVideo(1, (stream) => {
1528
- stream.bandwidth = kbps(10);
1529
- stream.size(100, 200);
1530
- });
1531
- variant.addAudio(2, (stream) => {
1532
- stream.language = englishUS;
1533
- stream.bandwidth = kbps(3);
1534
- });
1535
- });
1536
- manifest.addVariant(3, (variant) => {
1537
- variant.language = frenchCanadian;
1538
- variant.bandwidth = kbps(13);
1539
- variant.addExistingStream(1);
1540
- variant.addAudio(5, (stream) => {
1541
- stream.language = frenchCanadian;
1542
- stream.bandwidth = kbps(3);
1543
- });
1544
- });
1545
- });
1546
-
1547
- for (const stream of getAllStreams(manifest)) {
1548
- // Make a new copy each time, as the segment index can modify each
1549
- // reference.
1550
- const refs = [
1551
- makeReference(segment1Uri, 0, 1),
1552
- makeReference(segment2Uri, 1, 2),
1553
- makeReference(segment3Uri, 2, 3),
1554
- makeReference(segment4Uri, 3, 4),
1555
- ];
1556
-
1557
- overrideSegmentIndex(stream, refs);
1558
- }
1559
-
1560
- return manifest;
1561
- }
1562
-
1563
- /**
1564
- * @return {shaka.extern.Manifest}
1565
- */
1566
- function makeManifestWithoutPerStreamBandwidth() {
1567
- const manifest = makeManifestWithPerStreamBandwidth();
1568
-
1569
- // Remove the per stream bandwidth.
1570
- for (const stream of getAllStreams(manifest)) {
1571
- stream.bandwidth = undefined;
1572
- }
1573
-
1574
- return manifest;
1575
- }
1576
-
1577
- /**
1578
- * @return {shaka.extern.Manifest}
1579
- */
1580
- function makeManifestWithNonZeroStart() {
1581
- const manifest = makeManifestWithPerStreamBandwidth();
1582
-
1583
- for (const stream of getAllStreams(manifest)) {
1584
- const refs = [
1585
- makeReference(segment1Uri, 10, 11),
1586
- makeReference(segment2Uri, 11, 12),
1587
- makeReference(segment3Uri, 12, 13),
1588
- makeReference(segment4Uri, 13, 14),
1589
- ];
1590
-
1591
- overrideSegmentIndex(stream, refs);
1592
- }
1593
-
1594
- return manifest;
1595
- }
1596
-
1597
- /**
1598
- * @return {shaka.extern.Manifest}
1599
- */
1600
- function makeManifestWithLiveTimeline() {
1601
- const manifest = makeManifestWithPerStreamBandwidth();
1602
- manifest.presentationTimeline.setDuration(Infinity);
1603
- manifest.presentationTimeline.setStatic(false);
1604
- return manifest;
1605
- }
1606
-
1607
- /**
1608
- * @return {shaka.extern.Manifest}
1609
- */
1610
- function makeManifestWithAlternateSegments() {
1611
- const manifest = makeManifestWithPerStreamBandwidth();
1612
-
1613
- for (const stream of getAllStreams(manifest)) {
1614
- const refs = [
1615
- makeReference(alternateSegment1Uri, 10, 11),
1616
- makeReference(alternateSegment2Uri, 11, 12),
1617
- makeReference(alternateSegment3Uri, 12, 13),
1618
- makeReference(alternateSegment4Uri, 13, 14),
1619
- ];
1620
-
1621
- overrideSegmentIndex(stream, refs);
1622
- }
1623
-
1624
- return manifest;
1625
- }
1626
-
1627
- /**
1628
- * @param {shaka.extern.Manifest} manifest
1629
- * @return {!Array.<shaka.extern.Stream>}
1630
- */
1631
- function getAllStreams(manifest) {
1632
- const streams = [];
1633
-
1634
- for (const variant of manifest.variants) {
1635
- if (variant.audio) {
1636
- streams.push(variant.audio);
1637
- }
1638
- if (variant.video) {
1639
- streams.push(variant.video);
1640
- }
1641
- }
1642
- for (const stream of manifest.textStreams) {
1643
- streams.push(stream);
1644
- }
1645
-
1646
- return streams;
1647
- }
1648
-
1649
- /**
1650
- * @param {shaka.extern.Stream} stream
1651
- * @param {!Array.<shaka.media.SegmentReference>} segments
1652
- */
1653
- function overrideSegmentIndex(stream, segments) {
1654
- const index = new shaka.media.SegmentIndex(segments);
1655
- stream.createSegmentIndex = () => Promise.resolve();
1656
- stream.segmentIndex = index;
1657
- }
1658
-
1659
- /** @return {!shaka.test.FakeNetworkingEngine} */
1660
- function makeNetworkEngine() {
1661
- return new shaka.test.FakeNetworkingEngine()
1662
- .setResponseValue(segment1Uri, new ArrayBuffer(16))
1663
- .setResponseValue(segment2Uri, new ArrayBuffer(16))
1664
- .setResponseValue(segment3Uri, new ArrayBuffer(16))
1665
- .setResponseValue(segment4Uri, new ArrayBuffer(16))
1666
- .setResponseValue(alternateSegment1Uri, new ArrayBuffer(16))
1667
- .setResponseValue(alternateSegment2Uri, new ArrayBuffer(16))
1668
- .setResponseValue(alternateSegment3Uri, new ArrayBuffer(16))
1669
- .setResponseValue(alternateSegment4Uri, new ArrayBuffer(16));
1670
- }
1671
-
1672
- async function eraseStorage() {
1673
- /** @type {!shaka.offline.StorageMuxer} */
1674
- const muxer = new shaka.offline.StorageMuxer();
1675
-
1676
- try {
1677
- await muxer.erase();
1678
- } finally {
1679
- await muxer.destroy();
1680
- }
1681
- }
1682
-
1683
- /**
1684
- * @param {!shaka.offline.Storage} storage
1685
- * @param {!shaka.media.DrmEngine} drm
1686
- * @param {shaka.extern.Manifest} manifest
1687
- */
1688
- function overrideDrmAndManifest(storage, drm, manifest) {
1689
- storage.parseManifest = () => Promise.resolve(manifest);
1690
- storage.createDrmEngine = () => Promise.resolve(drm);
1691
- }
1692
-
1693
- /**
1694
- * @return {shaka.extern.DrmInfo}
1695
- */
1696
- function makeDrmInfo() {
1697
- const drmInfo = {
1698
- keySystem: 'com.example.abc',
1699
- licenseServerUri: 'http://example.com',
1700
- persistentStateRequired: true,
1701
- distinctiveIdentifierRequired: false,
1702
- initData: null,
1703
- keyIds: null,
1704
- sessionType: 'temporary',
1705
- serverCertificate: null,
1706
- serverCertificateUri: '',
1707
- audioRobustness: 'HARDY',
1708
- videoRobustness: 'OTHER',
1709
- };
1710
-
1711
- return drmInfo;
1712
- }
1713
-
1714
- // TODO(vaage): Replace this with |shaka.test.FakeManifestParser|
1715
- /** @implements {shaka.extern.ManifestParser} */
1716
- const FakeManifestParser = class {
1717
- constructor() {
1718
- this.map_ = {};
1719
- this.map_[manifestWithPerStreamBandwidthUri] =
1720
- makeManifestWithPerStreamBandwidth();
1721
- this.map_[manifestWithoutPerStreamBandwidthUri] =
1722
- makeManifestWithoutPerStreamBandwidth();
1723
- this.map_[manifestWithNonZeroStartUri] =
1724
- makeManifestWithNonZeroStart();
1725
- this.map_[manifestWithLiveTimelineUri] =
1726
- makeManifestWithLiveTimeline();
1727
- this.map_[manifestWithAlternateSegmentsUri] =
1728
- makeManifestWithAlternateSegments();
1729
- this.map_[manifestWithVideoInitSegmentsUri] =
1730
- makeManifestWithVideoInitSegments();
1731
- }
1732
-
1733
- /** @override */
1734
- configure(params) {}
1735
-
1736
- /** @override */
1737
- start(uri, player) {
1738
- return Promise.resolve(this.map_[uri]);
1739
- }
1740
-
1741
- /** @override */
1742
- stop() {
1743
- return Promise.resolve();
1744
- }
1745
-
1746
- /** @override */
1747
- update() {}
1748
-
1749
- /** @override */
1750
- onExpirationUpdated(session, number) {}
1751
-
1752
- /** @override */
1753
- onInitialVariantChosen(variant) {}
1754
-
1755
- /** @override */
1756
- banLocation(uri) {}
1757
- };
1758
-
1759
- /**
1760
- * @param {!shaka.media.DrmEngine} drmEngine
1761
- * @param {string} sessionName
1762
- * @return {!Promise.<MediaKeySession>}
1763
- *
1764
- * @suppress {accessControls}
1765
- */
1766
- function loadOfflineSession(drmEngine, sessionName) {
1767
- return drmEngine.loadOfflineSession_(
1768
- sessionName, {initData: null, initDataType: null});
1769
- }
1770
-
1771
- /**
1772
- * @param {!shaka.offline.OfflineUri} uri
1773
- * @return {!Promise.<shaka.extern.Manifest>}
1774
- */
1775
- async function getStoredManifest(uri) {
1776
- /** @type {!shaka.offline.ManifestConverter} */
1777
- const converter = new shaka.offline.ManifestConverter(
1778
- uri.mechanism(), uri.cell());
1779
-
1780
- /** @type {!shaka.offline.StorageMuxer} */
1781
- const muxer = new shaka.offline.StorageMuxer();
1782
-
1783
- try {
1784
- await muxer.init();
1785
- const cell = await muxer.getCell(uri.mechanism(), uri.cell());
1786
- const manifests = await cell.getManifests([uri.key()]);
1787
- const manifest = manifests[0];
1788
-
1789
- goog.asserts.assert(manifest, 'A manifest should have been found');
1790
- return converter.fromManifestDB(manifest);
1791
- } finally {
1792
- await muxer.destroy();
1793
- }
1794
- }
1795
-
1796
- /**
1797
- * @param {!shaka.Player} player
1798
- * @param {shaka.extern.Manifest} manifest
1799
- * @param {function(!shaka.media.DrmEngine):Promise} action
1800
- * @return {!Promise}
1801
- */
1802
- async function withDrm(player, manifest, action) {
1803
- const net = player.getNetworkingEngine();
1804
- goog.asserts.assert(net, 'Player should have a net engine right now');
1805
-
1806
- let error = null;
1807
-
1808
- /** @type {!shaka.media.DrmEngine} */
1809
- const drm = new shaka.media.DrmEngine({
1810
- netEngine: net,
1811
- onError: (e) => { error = error || e; },
1812
- onKeyStatus: () => {},
1813
- onExpirationUpdated: () => {},
1814
- onEvent: () => {},
1815
- });
1816
-
1817
- try {
1818
- drm.configure(player.getConfiguration().drm);
1819
- const variants = manifest.variants;
1820
- await drm.initForStorage(variants, /* usePersistentLicenses= */ true);
1821
- await action(drm);
1822
- } finally {
1823
- await drm.destroy();
1824
- }
1825
-
1826
- if (error) {
1827
- throw error;
1828
- }
1829
- }
1830
-
1831
- /**
1832
- * Creates a real SegmentReference. This is distinct from the fake ones used
1833
- * in ManifestParser tests because it can be on the left-hand side of an
1834
- * expect(). You can't expect jasmine.any(Number) to equal
1835
- * jasmine.any(Number). :-(
1836
- *
1837
- * @param {string} uri
1838
- * @param {number} startTime
1839
- * @param {number} endTime
1840
- * @param {shakaNamespaceType=} compiledShaka
1841
- * @return {shaka.media.SegmentReference}
1842
- */
1843
- function makeReference(uri, startTime, endTime, compiledShaka) {
1844
- /** @type {shakaNamespaceType} */
1845
- const shaka = compiledShaka || window['shaka'];
1846
-
1847
- return new shaka.media.SegmentReference(
1848
- startTime,
1849
- endTime,
1850
- /* getUris= */ () => [uri],
1851
- /* startByte= */ 0,
1852
- /* endByte= */ null,
1853
- /* initSegmentReference= */ null,
1854
- /* timestampOffset= */ 0,
1855
- /* appendWindowStart= */ 0,
1856
- /* appendWindowEnd= */ Infinity);
1857
- }
1858
- });