shaka-player 4.2.1 → 4.2.3
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.
- package/.github/workflows/build-and-test.yaml +42 -22
- package/.github/workflows/compute-incremental-coverage.py +14 -3
- package/.github/workflows/custom-actions/set-commit-status/action.yaml +1 -5
- package/.github/workflows/deflake.yaml +28 -0
- package/.github/workflows/demo-version-index.yaml +1 -1
- package/.github/workflows/nightly-demo.yaml +1 -1
- package/.github/workflows/release-please.yaml +5 -5
- package/.github/workflows/report-incremental-coverage.yaml +1 -1
- package/.github/workflows/selenium-lab-tests.yaml +21 -10
- package/AUTHORS +4 -0
- package/CHANGELOG.md +36 -0
- package/CONTRIBUTORS +4 -0
- package/demo/common/message_ids.js +1 -0
- package/demo/config.js +3 -1
- package/demo/locales/en.json +1 -0
- package/demo/locales/source.json +4 -0
- package/dist/demo.compiled.debug.js +7 -6
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +7 -6
- package/dist/demo.compiled.map +3 -3
- package/dist/deps.js +4 -4
- package/dist/locales.js +32 -32
- package/dist/receiver.compiled.debug.js +4 -3
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +4 -3
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.d.ts +3 -2
- package/dist/shaka-player.compiled.debug.d.ts +3 -2
- package/dist/shaka-player.compiled.debug.externs.js +25 -24
- package/dist/shaka-player.compiled.debug.js +268 -259
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +25 -24
- package/dist/shaka-player.compiled.js +749 -746
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +3 -2
- package/dist/shaka-player.ui.debug.d.ts +3 -2
- package/dist/shaka-player.ui.debug.externs.js +25 -24
- package/dist/shaka-player.ui.debug.js +243 -234
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +25 -24
- package/dist/shaka-player.ui.js +908 -904
- package/dist/shaka-player.ui.map +4 -4
- package/docs/jsdoc-template/publish.js +33 -0
- package/docs/jsdoc-template/tmpl/container.tmpl +4 -1
- package/docs/jsdoc.conf.json +1 -0
- package/docs/tutorials/welcome.md +2 -2
- package/externs/shaka/manifest_parser.js +4 -1
- package/externs/shaka/player.js +7 -1
- package/lib/ads/client_side_ad_manager.js +12 -2
- package/lib/cast/cast_sender.js +39 -14
- package/lib/cea/cea608_memory.js +4 -0
- package/lib/hls/hls_parser.js +48 -15
- package/lib/media/drm_engine.js +59 -7
- package/lib/media/media_source_engine.js +43 -15
- package/lib/media/playhead.js +1 -1
- package/lib/media/segment_index.js +4 -1
- package/lib/media/streaming_engine.js +79 -14
- package/lib/offline/indexeddb/storage_mechanism.js +24 -0
- package/lib/offline/storage.js +1 -0
- package/lib/player.js +17 -5
- package/lib/polyfill/media_capabilities.js +7 -6
- package/lib/text/ttml_text_parser.js +69 -87
- package/lib/text/vtt_text_parser.js +1 -1
- package/lib/util/error.js +7 -0
- package/lib/util/periods.js +9 -9
- package/lib/util/platform.js +19 -5
- package/lib/util/player_configuration.js +4 -0
- package/lib/util/pssh.js +2 -1
- package/lib/util/stream_utils.js +2 -1
- package/lib/util/xml_utils.js +45 -6
- package/package.json +1 -1
- package/test/cea/cea608_memory_unit.js +88 -0
- package/test/dash/dash_parser_content_protection_unit.js +1 -0
- package/test/dash/dash_parser_live_unit.js +1 -0
- package/test/dash/dash_parser_manifest_unit.js +1 -0
- package/test/dash/dash_parser_segment_base_unit.js +1 -0
- package/test/dash/dash_parser_segment_list_unit.js +1 -0
- package/test/dash/dash_parser_segment_template_unit.js +1 -0
- package/test/hls/hls_live_unit.js +169 -247
- package/test/hls/hls_parser_unit.js +60 -2
- package/test/media/drm_engine_unit.js +61 -0
- package/test/media/media_source_engine_integration.js +36 -0
- package/test/media/media_source_engine_unit.js +118 -1
- package/test/media/segment_index_unit.js +28 -2
- package/test/media/streaming_engine_integration.js +9 -7
- package/test/media/streaming_engine_unit.js +29 -0
- package/test/offline/offline_integration.js +3 -3
- package/test/offline/storage_integration.js +30 -0
- package/test/player_integration.js +2 -2
- package/test/test/util/dash_parser_util.js +2 -0
- package/test/test/util/ttml_utils.js +0 -2
- package/test/text/ttml_text_parser_unit.js +46 -0
- package/test/text/vtt_text_parser_unit.js +23 -1
- package/test/ui/text_displayer_layout_unit.js +17 -2
- package/test/util/periods_unit.js +149 -11
- package/test/util/xml_utils_unit.js +64 -0
- package/ui/controls.js +0 -7
|
@@ -75,6 +75,10 @@ shaka.util.PlayerConfiguration = class {
|
|
|
75
75
|
updateExpirationTime: 1,
|
|
76
76
|
preferredKeySystems: [],
|
|
77
77
|
keySystemsMapping: {},
|
|
78
|
+
// The Xbox One browser does not detect DRM key changes signalled by a
|
|
79
|
+
// change in the PSSH in media segments. We need to parse PSSH from media
|
|
80
|
+
// segments to detect key changes.
|
|
81
|
+
parseInbandPsshEnabled: shaka.util.Platform.isXboxOne(),
|
|
78
82
|
};
|
|
79
83
|
|
|
80
84
|
const manifest = {
|
package/lib/util/pssh.js
CHANGED
|
@@ -42,11 +42,12 @@ shaka.util.Pssh = class {
|
|
|
42
42
|
|
|
43
43
|
new shaka.util.Mp4Parser()
|
|
44
44
|
.box('moov', shaka.util.Mp4Parser.children)
|
|
45
|
+
.box('moof', shaka.util.Mp4Parser.children)
|
|
45
46
|
.fullBox('pssh', (box) => this.parsePsshBox_(box))
|
|
46
47
|
.parse(psshBox);
|
|
47
48
|
|
|
48
49
|
if (this.data.length == 0) {
|
|
49
|
-
shaka.log.
|
|
50
|
+
shaka.log.v2('No pssh box found!');
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
package/lib/util/stream_utils.js
CHANGED
|
@@ -474,7 +474,8 @@ shaka.util.StreamUtils = class {
|
|
|
474
474
|
if (shaka.util.Platform.isXboxOne() && video &&
|
|
475
475
|
((video.width && video.width > 1920) ||
|
|
476
476
|
(video.height && video.height > 1080)) &&
|
|
477
|
-
video.codecs.includes('avc1.')
|
|
477
|
+
(video.codecs.includes('avc1.') ||
|
|
478
|
+
video.codecs.includes('avc3.'))) {
|
|
478
479
|
shaka.log.debug('Dropping variant - not compatible with platform',
|
|
479
480
|
shaka.util.StreamUtils.getVariantSummaryString_(variant));
|
|
480
481
|
return false;
|
package/lib/util/xml_utils.js
CHANGED
|
@@ -8,6 +8,7 @@ goog.provide('shaka.util.XmlUtils');
|
|
|
8
8
|
|
|
9
9
|
goog.require('goog.asserts');
|
|
10
10
|
goog.require('shaka.log');
|
|
11
|
+
goog.require('shaka.util.Lazy');
|
|
11
12
|
goog.require('shaka.util.StringUtils');
|
|
12
13
|
|
|
13
14
|
|
|
@@ -348,19 +349,21 @@ shaka.util.XmlUtils = class {
|
|
|
348
349
|
*/
|
|
349
350
|
static parseXmlString(xmlString, expectedRootElemName) {
|
|
350
351
|
const parser = new DOMParser();
|
|
351
|
-
|
|
352
|
+
const unsafeXmlString =
|
|
353
|
+
shaka.util.XmlUtils.trustedHTMLFromString_.value()(xmlString);
|
|
354
|
+
let unsafeXml = null;
|
|
352
355
|
try {
|
|
353
|
-
|
|
356
|
+
unsafeXml = parser.parseFromString(unsafeXmlString, 'text/xml');
|
|
354
357
|
} catch (exception) {
|
|
355
358
|
shaka.log.error('XML parsing exception:', exception);
|
|
356
359
|
return null;
|
|
357
360
|
}
|
|
358
361
|
|
|
359
362
|
// According to MDN, parseFromString never returns null.
|
|
360
|
-
goog.asserts.assert(
|
|
363
|
+
goog.asserts.assert(unsafeXml, 'Parsed XML document cannot be null!');
|
|
361
364
|
|
|
362
365
|
// Check for empty documents.
|
|
363
|
-
const rootElem =
|
|
366
|
+
const rootElem = unsafeXml.documentElement;
|
|
364
367
|
if (!rootElem) {
|
|
365
368
|
shaka.log.error('XML document was empty!');
|
|
366
369
|
return null;
|
|
@@ -374,13 +377,28 @@ shaka.util.XmlUtils = class {
|
|
|
374
377
|
}
|
|
375
378
|
|
|
376
379
|
// The top-level element in the loaded XML should have the name we expect.
|
|
377
|
-
if (
|
|
380
|
+
if (rootElem.tagName != expectedRootElemName) {
|
|
378
381
|
shaka.log.error(
|
|
379
382
|
`XML tag name does not match expected "${expectedRootElemName}":`,
|
|
380
|
-
|
|
383
|
+
rootElem.tagName);
|
|
381
384
|
return null;
|
|
382
385
|
}
|
|
383
386
|
|
|
387
|
+
// SECURITY: Verify that the document does not contain elements from the
|
|
388
|
+
// HTML or SVG namespaces, which could trigger script execution and XSS.
|
|
389
|
+
const iterator = document.createNodeIterator(
|
|
390
|
+
unsafeXml,
|
|
391
|
+
NodeFilter.SHOW_ALL,
|
|
392
|
+
);
|
|
393
|
+
let currentNode;
|
|
394
|
+
while (currentNode = iterator.nextNode()) {
|
|
395
|
+
if (currentNode instanceof HTMLElement ||
|
|
396
|
+
currentNode instanceof SVGElement) {
|
|
397
|
+
shaka.log.error('XML document embeds unsafe content!');
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
384
402
|
return rootElem;
|
|
385
403
|
}
|
|
386
404
|
|
|
@@ -402,3 +420,24 @@ shaka.util.XmlUtils = class {
|
|
|
402
420
|
}
|
|
403
421
|
}
|
|
404
422
|
};
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Promote a string to TrustedHTML. This function is security-sensitive and
|
|
426
|
+
* should only be used with security approval where the string is guaranteed not
|
|
427
|
+
* to cause an XSS vulnerability.
|
|
428
|
+
*
|
|
429
|
+
* @private {!shaka.util.Lazy.<function(!string): (!TrustedHTML|!string)>}
|
|
430
|
+
*/
|
|
431
|
+
shaka.util.XmlUtils.trustedHTMLFromString_ = new shaka.util.Lazy(() => {
|
|
432
|
+
if (typeof trustedTypes !== 'undefined') {
|
|
433
|
+
// Create a Trusted Types policy for promoting the string to TrustedHTML.
|
|
434
|
+
// The Lazy wrapper ensures this policy is only created once.
|
|
435
|
+
const policy = trustedTypes.createPolicy('shaka-player#xml', {
|
|
436
|
+
createHTML: (s) => s,
|
|
437
|
+
});
|
|
438
|
+
return (s) => policy.createHTML(s);
|
|
439
|
+
}
|
|
440
|
+
// Fall back to strings in environments that don't support Trusted Types.
|
|
441
|
+
return (s) => s;
|
|
442
|
+
});
|
|
443
|
+
|
package/package.json
CHANGED
|
@@ -295,5 +295,93 @@ describe('Cea608Memory', () => {
|
|
|
295
295
|
const caption = memory.forceEmit(startTime, endTime);
|
|
296
296
|
expect(caption).toEqual(expectedCaption);
|
|
297
297
|
});
|
|
298
|
+
|
|
299
|
+
it('does not move rows if source row index is negative', () => {
|
|
300
|
+
const startTime = 1;
|
|
301
|
+
const endTime = 2;
|
|
302
|
+
const text = 'test';
|
|
303
|
+
|
|
304
|
+
// Add the text to the buffer, each character on separate rows.
|
|
305
|
+
// At this point, the memory looks like:
|
|
306
|
+
// [1]: t
|
|
307
|
+
// [2]: e
|
|
308
|
+
// [3]: s
|
|
309
|
+
// [4]: t
|
|
310
|
+
for (const c of text) {
|
|
311
|
+
memory.addChar(CharSet.BASIC_NORTH_AMERICAN,
|
|
312
|
+
c.charCodeAt(0));
|
|
313
|
+
memory.setRow(memory.getRow() + 1); // increment row
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const srcRowIdx = -1;
|
|
317
|
+
const dstRowIdx = 2;
|
|
318
|
+
const rowsToMove = 3;
|
|
319
|
+
memory.moveRows(dstRowIdx, srcRowIdx, rowsToMove);
|
|
320
|
+
|
|
321
|
+
// Expected text is 't\ne\ns\nt'
|
|
322
|
+
const topLevelCue = new shaka.text.Cue(startTime, endTime, '');
|
|
323
|
+
topLevelCue.nestedCues = [
|
|
324
|
+
CeaUtils.createDefaultCue(startTime, endTime, 't'),
|
|
325
|
+
CeaUtils.createLineBreakCue(startTime, endTime),
|
|
326
|
+
CeaUtils.createDefaultCue(startTime, endTime, 'e'),
|
|
327
|
+
CeaUtils.createLineBreakCue(startTime, endTime),
|
|
328
|
+
CeaUtils.createDefaultCue(startTime, endTime, 's'),
|
|
329
|
+
CeaUtils.createLineBreakCue(startTime, endTime),
|
|
330
|
+
CeaUtils.createDefaultCue(startTime, endTime, 't'),
|
|
331
|
+
];
|
|
332
|
+
|
|
333
|
+
const expectedCaption = {
|
|
334
|
+
stream,
|
|
335
|
+
cue: topLevelCue,
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
// Force out the new memory.
|
|
339
|
+
const caption = memory.forceEmit(startTime, endTime);
|
|
340
|
+
expect(caption).toEqual(expectedCaption);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it('does not move rows if destination row index is negative', () => {
|
|
344
|
+
const startTime = 1;
|
|
345
|
+
const endTime = 2;
|
|
346
|
+
const text = 'test';
|
|
347
|
+
|
|
348
|
+
// Add the text to the buffer, each character on separate rows.
|
|
349
|
+
// At this point, the memory looks like:
|
|
350
|
+
// [1]: t
|
|
351
|
+
// [2]: e
|
|
352
|
+
// [3]: s
|
|
353
|
+
// [4]: t
|
|
354
|
+
for (const c of text) {
|
|
355
|
+
memory.addChar(CharSet.BASIC_NORTH_AMERICAN,
|
|
356
|
+
c.charCodeAt(0));
|
|
357
|
+
memory.setRow(memory.getRow() + 1); // increment row
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const srcRowIdx = 1;
|
|
361
|
+
const dstRowIdx = -2;
|
|
362
|
+
const rowsToMove = 3;
|
|
363
|
+
memory.moveRows(dstRowIdx, srcRowIdx, rowsToMove);
|
|
364
|
+
|
|
365
|
+
// Expected text is 't\ne\ns\nt'
|
|
366
|
+
const topLevelCue = new shaka.text.Cue(startTime, endTime, '');
|
|
367
|
+
topLevelCue.nestedCues = [
|
|
368
|
+
CeaUtils.createDefaultCue(startTime, endTime, 't'),
|
|
369
|
+
CeaUtils.createLineBreakCue(startTime, endTime),
|
|
370
|
+
CeaUtils.createDefaultCue(startTime, endTime, 'e'),
|
|
371
|
+
CeaUtils.createLineBreakCue(startTime, endTime),
|
|
372
|
+
CeaUtils.createDefaultCue(startTime, endTime, 's'),
|
|
373
|
+
CeaUtils.createLineBreakCue(startTime, endTime),
|
|
374
|
+
CeaUtils.createDefaultCue(startTime, endTime, 't'),
|
|
375
|
+
];
|
|
376
|
+
|
|
377
|
+
const expectedCaption = {
|
|
378
|
+
stream,
|
|
379
|
+
cue: topLevelCue,
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
// Force out the new memory.
|
|
383
|
+
const caption = memory.forceEmit(startTime, endTime);
|
|
384
|
+
expect(caption).toEqual(expectedCaption);
|
|
385
|
+
});
|
|
298
386
|
});
|
|
299
387
|
});
|
|
@@ -348,6 +348,7 @@ describe('DashParser SegmentList', () => {
|
|
|
348
348
|
isLowLatencyMode: () => false,
|
|
349
349
|
isAutoLowLatencyMode: () => false,
|
|
350
350
|
enableLowLatencyMode: () => {},
|
|
351
|
+
updateDuration: () => {},
|
|
351
352
|
};
|
|
352
353
|
const manifest = await dashParser.start('dummy://foo', playerInterface);
|
|
353
354
|
const stream = manifest.variants[0].video;
|