From c935cc17703297a44b3ce3bda75d8f2ea37f4147 Mon Sep 17 00:00:00 2001 From: Joey Parrish Date: Thu, 18 Aug 2022 14:47:10 -0700 Subject: [PATCH] fix: Fix vanishing tracks while offline (#4426) Introduced in #4189, as a side-effect of restricting tracks when a network failure occurs. We should not trigger such restrictions when the browser is known to be offline. Closes #4408 --- lib/player.js | 6 ++++++ test/player_unit.js | 40 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/lib/player.js b/lib/player.js index 1c8f5f4bed..855a8fec17 100644 --- a/lib/player.js +++ b/lib/player.js @@ -5625,6 +5625,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget { return false; } + if (!navigator.onLine) { + // Don't restrict variants if we're completely offline, or else we end up + // rapidly restricting all of them. + return false; + } + let maxDisabledTime = this.config_.streaming.maxDisabledTime; if (maxDisabledTime == 0) { if (error.code == shaka.util.Error.Code.SEGMENT_MISSING) { diff --git a/test/player_unit.js b/test/player_unit.js index 7f9be60b57..0b1e02cffd 100644 --- a/test/player_unit.js +++ b/test/player_unit.js @@ -422,7 +422,6 @@ describe('Player', () => { dispatchEventSpy.calls.reset(); player.configure({streaming: {maxDisabledTime}}); player.setMaxHardwareResolution(123, 456); - onErrorCallback(httpError); }); afterEach(() => { @@ -434,14 +433,18 @@ describe('Player', () => { }); it('handles HTTP_ERROR', () => { + onErrorCallback(httpError); expect(httpError.handled).toBeTruthy(); }); it('does not dispatch any error', () => { + onErrorCallback(httpError); expect(dispatchEventSpy).not.toHaveBeenCalled(); }); it('disables the current variant and applies restrictions', () => { + onErrorCallback(httpError); + const foundDisabledVariant = manifest.variants.some(({disabledUntilTime}) => disabledUntilTime == currentTime + maxDisabledTime); @@ -453,11 +456,46 @@ describe('Player', () => { }); it('switches the variant', () => { + onErrorCallback(httpError); + expect(chooseVariantSpy).toHaveBeenCalled(); expect(getBufferedInfoSpy).toHaveBeenCalled(); expect(switchVariantSpy) .toHaveBeenCalledWith(chosenVariant, false, true, 14); }); + + describe('but browser is truly offline', () => { + /** @type {!Object} */ + let navigatorOnLineDescriptor; + + // eslint-disable-next-line no-restricted-syntax + const navigatorPrototype = Navigator.prototype; + + beforeAll(() => { + navigatorOnLineDescriptor = + /** @type {!Object} */(Object.getOwnPropertyDescriptor( + navigatorPrototype, 'onLine')); + }); + + beforeEach(() => { + // Redefine the property, replacing only the getter. + Object.defineProperty(navigatorPrototype, 'onLine', + Object.assign(navigatorOnLineDescriptor, { + get: () => false, + })); + }); + + afterEach(() => { + // Restore the original property definition. + Object.defineProperty( + navigatorPrototype, 'onLine', navigatorOnLineDescriptor); + }); + + it('does not handle HTTP_ERROR', () => { + onErrorCallback(httpError); + expect(httpError.handled).toBe(false); + }); + }); }); }); });