Skip to content

Commit

Permalink
fix: Fix exceptions when quickly shutting down src= on Safari (#4088)
Browse files Browse the repository at this point in the history
Some events and timers were used to process track changes with src=
playback on Safari, but they did not properly clean up when the player
was unloaded or destroyed.  In the case that this happened quickly
after starting playback, exceptions would be thrown or tracks could
manipulated after new content began.

This fixes the cleanup of these timers and events to be aware of
Player unloads or destruction.

Closes #4087
  • Loading branch information
joeyparrish committed Mar 31, 2022
1 parent 9660ce8 commit ca08230
Showing 1 changed file with 26 additions and 11 deletions.
37 changes: 26 additions & 11 deletions lib/player.js
Expand Up @@ -2217,6 +2217,14 @@ shaka.Player = class extends shaka.util.FakeEventTarget {

this.playhead_ = new shaka.media.SrcEqualsPlayhead(has.mediaElement);

// This flag is used below in the language preference setup and
// track-management to check if this load was canceled before the necessary
// events fired.
let unloaded = false;
this.cleanupOnUnload_.push(() => {
unloaded = true;
});

if (has.startTime != null) {
this.playhead_.setStartTime(has.startTime);
}
Expand Down Expand Up @@ -2268,6 +2276,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
}
if (this.video_.textTracks) {
this.eventManager_.listen(this.video_.textTracks, 'addtrack', (e) => {
// If we have moved on to another piece of content while waiting for
// the above event, we should not process tracks here.
if (unloaded) {
return;
}

const trackEvent = /** @type {!TrackEvent} */(e);
if (trackEvent.track) {
const track = trackEvent.track;
Expand Down Expand Up @@ -2327,13 +2341,6 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
fullyLoaded.resolve();
});

// This flag is used below in the language preference setup to check if this
// load was canceled before the necessary events fire.
let unloaded = false;
this.cleanupOnUnload_.push(() => {
unloaded = true;
});

// We can't switch to preferred languages, though, until the data is loaded.
shaka.util.MediaReadyState.waitForReadyState(this.video_,
HTMLMediaElement.HAVE_CURRENT_DATA,
Expand Down Expand Up @@ -2488,12 +2495,16 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
// In Safari the initial assignment does not always work, so we schedule
// this process to be repeated several times to ensure that it has been put
// in the correct mode.
new shaka.util.Timer(() => {
const timer = new shaka.util.Timer(() => {
const textTracks = this.getMetadataTracks_();
for (const textTrack of textTracks) {
textTrack.mode = 'hidden';
}
}).tickNow().tickAfter(/* seconds= */ 0.5);
}).tickNow().tickAfter(0.5);

this.cleanupOnUnload_.push(() => {
timer.stop();
});
}


Expand Down Expand Up @@ -2561,12 +2572,16 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
// In Safari the initial assignment does not always work, so we schedule
// this process to be repeated several times to ensure that it has been put
// in the correct mode.
new shaka.util.Timer(() => {
const timer = new shaka.util.Timer(() => {
const chaptersTracks = this.getChaptersTracks_();
for (const chaptersTrack of chaptersTracks) {
chaptersTrack.mode = 'hidden';
}
}).tickNow().tickAfter(/* seconds= */ 0.5);
}).tickNow().tickAfter(0.5);

this.cleanupOnUnload_.push(() => {
timer.stop();
});
}

/**
Expand Down

0 comments on commit ca08230

Please sign in to comment.