From a71a3fa081b369ff23dda84578c0b74682948c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Velad=20Galv=C3=A1n?= Date: Tue, 12 Oct 2021 19:59:06 +0200 Subject: [PATCH] fix: Work around override of MediaCapabilities polyfill in Apple browsers (#3668) See also #3696 Closes #3530 --- externs/media_capabilities.js | 16 ++++++++++++++++ lib/polyfill/media_capabilities.js | 16 +++++++++------- lib/util/stream_utils.js | 4 ++-- test/media/drm_engine_unit.js | 6 +++--- test/player_unit.js | 10 +++++----- test/util/stream_utils_unit.js | 8 ++++---- 6 files changed, 39 insertions(+), 21 deletions(-) create mode 100644 externs/media_capabilities.js diff --git a/externs/media_capabilities.js b/externs/media_capabilities.js new file mode 100644 index 0000000000..e450542dc9 --- /dev/null +++ b/externs/media_capabilities.js @@ -0,0 +1,16 @@ +/*! @license + * Shaka Player + * Copyright 2016 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Externs for Shaka MediaCapabilities which were missing in the + * Closure compiler. + * + * @externs + */ + + +/** @type {MediaCapabilities} */ +window.shakaMediaCapabilities; diff --git a/lib/polyfill/media_capabilities.js b/lib/polyfill/media_capabilities.js index 192e146fd2..6aec26c9cb 100644 --- a/lib/polyfill/media_capabilities.js +++ b/lib/polyfill/media_capabilities.js @@ -39,14 +39,16 @@ shaka.polyfill.MediaCapabilities = class { navigator.mediaCapabilities) { shaka.log.debug( 'MediaCapabilities: Native mediaCapabilities support found.'); - return; - } - - if (!navigator.mediaCapabilities) { - navigator.mediaCapabilities = /** @type {!MediaCapabilities} */ ({}); + } else { + if (!navigator.mediaCapabilities) { + navigator.mediaCapabilities = /** @type {!MediaCapabilities} */ ({}); + } + navigator.mediaCapabilities.decodingInfo = + shaka.polyfill.MediaCapabilities.decodingInfo_; } - navigator.mediaCapabilities.decodingInfo = - shaka.polyfill.MediaCapabilities.decodingInfo_; + // Workaround because in Apple browsers there is no way to overwrite + // MediaCapabilities. + window.shakaMediaCapabilities = navigator.mediaCapabilities; } /** diff --git a/lib/util/stream_utils.js b/lib/util/stream_utils.js index 6a7d4d00c7..16482531c6 100644 --- a/lib/util/stream_utils.js +++ b/lib/util/stream_utils.js @@ -419,7 +419,7 @@ shaka.util.StreamUtils = class { */ static async filterManifestByMediaCapabilities( manifest, usePersistentLicenses) { - goog.asserts.assert(navigator.mediaCapabilities, + goog.asserts.assert(window.shakaMediaCapabilities, 'MediaCapabilities should be valid.'); await shaka.util.StreamUtils.getDecodingInfosForVariants( @@ -468,7 +468,7 @@ shaka.util.StreamUtils = class { return; } - const mediaCapabilities = navigator.mediaCapabilities; + const mediaCapabilities = window.shakaMediaCapabilities; const operations = []; const getVariantDecodingInfos = (async (variant, decodingConfig) => { diff --git a/test/media/drm_engine_unit.js b/test/media/drm_engine_unit.js index 707a2372c6..4cb204d9cb 100644 --- a/test/media/drm_engine_unit.js +++ b/test/media/drm_engine_unit.js @@ -31,7 +31,7 @@ describe('DrmEngine', () => { navigator.requestMediaKeySystemAccess; const originalLogError = shaka.log.error; const originalBatchTime = shaka.media.DrmEngine.KEY_STATUS_BATCH_TIME; - const originalDecodingInfo = navigator.mediaCapabilities.decodingInfo; + const originalDecodingInfo = window.shakaMediaCapabilities.decodingInfo; /** @type {!jasmine.Spy} */ let decodingInfoSpy; @@ -76,7 +76,7 @@ describe('DrmEngine', () => { beforeEach(() => { decodingInfoSpy = jasmine.createSpy('decodingInfo'); - navigator.mediaCapabilities.decodingInfo = + window.shakaMediaCapabilities.decodingInfo = shaka.test.Util.spyFunc(decodingInfoSpy); logErrorSpy = jasmine.createSpy('shaka.log.error'); @@ -153,7 +153,7 @@ describe('DrmEngine', () => { navigator.requestMediaKeySystemAccess = originalRequestMediaKeySystemAccess; - navigator.mediaCapabilities.decodingInfo = originalDecodingInfo; + window.shakaMediaCapabilities.decodingInfo = originalDecodingInfo; shaka.log.error = originalLogError; }); diff --git a/test/player_unit.js b/test/player_unit.js index 0a9a3852e1..fc791d2dde 100644 --- a/test/player_unit.js +++ b/test/player_unit.js @@ -36,7 +36,7 @@ describe('Player', () => { const originalLogWarn = shaka.log.warning; const originalLogAlwaysWarn = shaka.log.alwaysWarn; const originalIsTypeSupported = window.MediaSource.isTypeSupported; - const originalDecodingInfo = navigator.mediaCapabilities.decodingInfo; + const originalDecodingInfo = window.shakaMediaCapabilities.decodingInfo; const fakeManifestUri = 'fake-manifest-uri'; const fakeMimeType = 'application/test'; @@ -93,7 +93,7 @@ describe('Player', () => { // Since this is not an integration test, we don't want MediaCapabilities to // fail assertions based on browser support for types. Pretend that all // video and audio types are supported. - navigator.mediaCapabilities.decodingInfo = async (config) => { + window.shakaMediaCapabilities.decodingInfo = async (config) => { await Promise.resolve(); const videoType = config['video'] ? config['video'].contentType.split('/')[0] : null; @@ -177,7 +177,7 @@ describe('Player', () => { shaka.log.alwaysWarn = originalLogAlwaysWarn; window.MediaSource.isTypeSupported = originalIsTypeSupported; shaka.media.ManifestParser.unregisterParserByMime(fakeMimeType); - navigator.mediaCapabilities.decodingInfo = originalDecodingInfo; + window.shakaMediaCapabilities.decodingInfo = originalDecodingInfo; } }); @@ -2463,7 +2463,7 @@ describe('Player', () => { it('throws CONTENT_UNSUPPORTED_BY_BROWSER', async () => { window.MediaSource.isTypeSupported = (mimeType) => false; - navigator.mediaCapabilities.decodingInfo = async (config) => { + window.shakaMediaCapabilities.decodingInfo = async (config) => { await Promise.resolve(); return {supported: false}; }; @@ -2827,7 +2827,7 @@ describe('Player', () => { }); }); - navigator.mediaCapabilities.decodingInfo = async (config) => { + window.shakaMediaCapabilities.decodingInfo = async (config) => { await Promise.resolve(); const videoType = config['video'] ? config['video'].contentType : ''; if (videoType.includes('video') && diff --git a/test/util/stream_utils_unit.js b/test/util/stream_utils_unit.js index d121031fcf..a68c2fb362 100644 --- a/test/util/stream_utils_unit.js +++ b/test/util/stream_utils_unit.js @@ -16,14 +16,14 @@ describe('StreamUtils', () => { /** @type {!jasmine.Spy} */ let decodingInfoSpy; - const originalDecodingInfo = navigator.mediaCapabilities.decodingInfo; + const originalDecodingInfo = window.shakaMediaCapabilities.decodingInfo; beforeEach(() => { decodingInfoSpy = jasmine.createSpy('decodingInfo'); }); afterEach(() => { - navigator.mediaCapabilities.decodingInfo = originalDecodingInfo; + window.shakaMediaCapabilities.decodingInfo = originalDecodingInfo; }); describe('filterStreamsByLanguageAndRole', () => { @@ -511,7 +511,7 @@ describe('StreamUtils', () => { }); it('handles decodingInfo exception', async () => { - navigator.mediaCapabilities.decodingInfo = + window.shakaMediaCapabilities.decodingInfo = shaka.test.Util.spyFunc(decodingInfoSpy); // If decodingInfo() fails, setDecodingInfo should finish without throwing // an exception, and the variant should have no decodingInfo result. @@ -826,7 +826,7 @@ describe('StreamUtils', () => { }); }); }); - navigator.mediaCapabilities.decodingInfo = + window.shakaMediaCapabilities.decodingInfo = shaka.test.Util.spyFunc(decodingInfoSpy); decodingInfoSpy.and.callFake((config) => { const res = config.video.contentType.includes('notsmooth') ?