From 4aa2430a1b6cae7331cb6b2a51c0faea0dad82c4 Mon Sep 17 00:00:00 2001 From: Jacob Trimble Date: Mon, 19 Jun 2017 14:43:42 -0700 Subject: [PATCH] Fix key status problems with EME polyfills. Our EME polyfills give a key status with a Key ID of '00' (a single 0 byte). This breaks the Player logic for restricted tracks since it assumes that those are not playable. When we get this Key ID, we should treat the key status as a global status, not for that specific Key ID. Closes #884 Closes #890 Change-Id: I392550227274fb321d2c223eb8d483a0a4733186 --- lib/player.js | 15 ++++++- test/media/drm_engine_integration.js | 3 +- test/player_unit.js | 60 ++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/lib/player.js b/lib/player.js index f7de3d0b22..aa9d269396 100644 --- a/lib/player.js +++ b/lib/player.js @@ -2585,6 +2585,19 @@ shaka.Player.prototype.onKeyStatus_ = function(keyStatusMap) { var period = this.streamingEngine_.getCurrentPeriod(); var tracksChanged = false; + // If EME is using a synthetic key, the only key is '00' (a single 0 byte). + // In this case, it is only used to report global success/failure. + // See note about old platforms in: https://goo.gl/KtQMja + var isGlobalStatus = Object.keys(keyStatusMap).length == 1 && + Object.keys(keyStatusMap)[0] == '00'; + + if (isGlobalStatus) { + shaka.log.warning( + 'Got a synthetic key status event, so we don\'t know the real key ' + + 'statuses. If we don\'t have all the keys, you\'ll need to set ' + + 'restrictions so we don\'t select those tracks.'); + } + period.variants.forEach(function(variant) { var streams = []; if (variant.audio) streams.push(variant.audio); @@ -2596,7 +2609,7 @@ shaka.Player.prototype.onKeyStatus_ = function(keyStatusMap) { // Only update if we have a key ID for the stream. If the key isn't // present, then we don't have that key and it should be restricted. if (stream.keyId) { - var keyStatus = keyStatusMap[stream.keyId]; + var keyStatus = keyStatusMap[isGlobalStatus ? '00' : stream.keyId]; variant.allowedByKeySystem = !!keyStatus && restrictedStatuses.indexOf(keyStatus) < 0; } diff --git a/test/media/drm_engine_integration.js b/test/media/drm_engine_integration.js index d0baf4800a..cd3a3712fc 100644 --- a/test/media/drm_engine_integration.js +++ b/test/media/drm_engine_integration.js @@ -216,8 +216,7 @@ describe('DrmEngine', function() { } }).then(function() { // Some platforms (notably 2017 Tizen TVs) do not fire key status - // events. This is a temporary workaround for the test failure - // in https://github.com/google/shaka-player/issues/891 + // events. var keyStatusTimeout = shaka.test.Util.delay(5); return Promise.race([keyStatusTimeout, keyStatusEventSeen]); }).then(function() { diff --git a/test/player_unit.js b/test/player_unit.js index d8fd810af9..c3f516850f 100644 --- a/test/player_unit.js +++ b/test/player_unit.js @@ -1909,6 +1909,66 @@ describe('Player', function() { }).catch(fail).then(done); }); + it('doesn\'t remove when using synthetic key status', function(done) { + manifest = new shaka.test.ManifestGenerator() + .addPeriod(0) + .addVariant(0) + .addVideo(1).keyId('abc') + .addVariant(2) + .addVideo(3) + .build(); + + parser = new shaka.test.FakeManifestParser(manifest); + parserFactory = function() { return parser; }; + player.load('', 0, parserFactory).then(function() { + // "initialize" the current period. + chooseStreams(); + canSwitch(); + }).then(function() { + expect(player.getVariantTracks().length).toBe(2); + + // A synthetic key status contains a single key status with key '00'. + onKeyStatus({'00': 'usable'}); + + expect(player.getVariantTracks().length).toBe(2); + }).catch(fail).then(done); + }); + + it('removes all encrypted tracks for errors with synthetic key status', + function(done) { + manifest = new shaka.test.ManifestGenerator() + .addPeriod(0) + .addVariant(0) + .addVideo(1).keyId('abc') + .addVariant(2) + .addVideo(3).keyId('xyz') + .addVariant(4) + .addVideo(5) + .build(); + + parser = new shaka.test.FakeManifestParser(manifest); + parserFactory = function() { return parser; }; + player.load('', 0, parserFactory) + .then(function() { + // "initialize" the current period. + chooseStreams(); + canSwitch(); + }) + .then(function() { + expect(player.getVariantTracks().length).toBe(3); + + // A synthetic key status contains a single key status with key + // '00'. + onKeyStatus({'00': 'internal-error'}); + + var tracks = player.getVariantTracks(); + expect(tracks.length).toBe(1); + expect(tracks[0].id).toBe(4); + }) + .catch(fail) + .then(done); + }); + it('removes if key system does not support codec', function(done) { manifest = new shaka.test.ManifestGenerator() .addPeriod(0)