From d9b9bae785525487bd5e0f4b07b3ad49b77dcfc5 Mon Sep 17 00:00:00 2001 From: Daniel Marino <1237997+CHaNGeTe@users.noreply.github.com> Date: Wed, 27 Nov 2024 13:37:16 +0100 Subject: [PATCH] fix: Timeout unfulfilled request to decodingInfo and requestMediaKeySystemAccess On some (Android) WebView environments, decodingInfo and requestMediaKeySystemAccess will not resolve or reject, at least if RESOURCE_PROTECTED_MEDIA_ID is not set. This is a workaround for that issue. --- lib/media/drm_engine.js | 50 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/lib/media/drm_engine.js b/lib/media/drm_engine.js index 5ccd43d57d..601c1f1b46 100644 --- a/lib/media/drm_engine.js +++ b/lib/media/drm_engine.js @@ -1870,8 +1870,27 @@ shaka.media.DrmEngine = class { offlineConfig.sessionTypes = ['persistent-license']; const configs = [offlineConfig, basicConfig]; - - const access = await navigator.requestMediaKeySystemAccess( + // On some (Android) WebView environments, + // requestMediaKeySystemAccess will + // not resolve or reject, at least if RESOURCE_PROTECTED_MEDIA_ID + // is not set. This is a workaround for that issue. + const TIMEOUT_FOR_CHECKACCESS_IN_SECONDS = 1; + const checkAccessOrTimeout = (keySystem, configs) => { + return new Promise((resolve, reject) => { + let resolved = false; + navigator.requestMediaKeySystemAccess(keySystem, configs) + .then((access) => { + resolved = true; + resolve(access); + }); + new shaka.util.Timer(() => { + if (!resolved) { + reject(new Error('Timeout requestMediaKeySystemAccess')); + } + }).tickAfter(TIMEOUT_FOR_CHECKACCESS_IN_SECONDS); + }); + }; + const access = await checkAccessOrTimeout( keySystem, configs); await processMediaKeySystemAccess(keySystem, access); } catch (error) {} // Ignore errors. @@ -1907,13 +1926,34 @@ shaka.media.DrmEngine = class { }, }, }; - + // On some (Android) WebView environments, decodingInfo will + // not resolve or reject, at least if RESOURCE_PROTECTED_MEDIA_ID + // is not set. This is a workaround for that issue. + const TIMEOUT_FOR_DECODING_INFO_IN_SECONDS = 1; + const decodeOrTimeout = (decodingConfig) => { + return new Promise((resolve, reject) => { + let resolved = false; + navigator.mediaCapabilities.decodingInfo(decodingConfig) + .then((result) => { + resolved = true; + resolve(result); + }); + new shaka.util.Timer(() => { + if (!resolved) { + reject(new Error('Timeout decodingInfo')); + } + }).tickAfter(TIMEOUT_FOR_DECODING_INFO_IN_SECONDS); + }); + }; const decodingInfo = - await navigator.mediaCapabilities.decodingInfo(decodingConfig); + await decodeOrTimeout(decodingConfig); const access = decodingInfo.keySystemAccess; await processMediaKeySystemAccess(keySystem, access); - } catch (error) {} // Ignore errors. + } catch (error) { + // Ignore errors. + shaka.log.v2('Failed to probe support for', keySystem, error); + } }; // Initialize the support structure for each key system.