Bug 1208371 - Ensure a media element's ImageContainer is protected when playing a stream. r=mt,jesup

HTMLMediaElement needs special protection when playing a stream since its
ImageContainer can outlive the video track of a stream.

Consider for instance when a (cross-origin) video track is removed from a
DOMMediaStream by a user and the remaining video track (non-CORS) does not yet
contain any actual video frames. The HTMLMediaElement will display a frame from
the removed track but the DOMMediaStream's principal has been updated to not
include the principal from the removed track.

With this patch we handle this by letting VideoFrameContainer notify
HTMLMediaElement when it has flushed out all video frames belonging to a
certain PrincipalHandle. I.e., when a new PrincipalHandle has been applied to the
underlying ImageContainer.

MozReview-Commit-ID: LvIZPl6Rdgj
This commit is contained in:
Andreas Pehrson
2016-02-04 09:27:09 +08:00
parent c791b10b67
commit 23adbf5caf
5 changed files with 122 additions and 7 deletions

View File

@@ -4193,14 +4193,53 @@ HTMLMediaElement::PrincipalChanged(DOMMediaStream* aStream)
"%p. Waiting for it to reach VideoFrameContainer before "
"setting.", this, aStream->GetVideoPrincipal()));
if (mVideoFrameContainer) {
UpdateSrcStreamVideoPrincipal(aStream->GetVideoPrincipal());
UpdateSrcStreamVideoPrincipal(mVideoFrameContainer->GetLastPrincipalHandle());
}
}
void
HTMLMediaElement::UpdateSrcStreamVideoPrincipal(nsIPrincipal* aPrincipal)
HTMLMediaElement::UpdateSrcStreamVideoPrincipal(const PrincipalHandle& aPrincipalHandle)
{
mSrcStreamVideoPrincipal = aPrincipal;
nsTArray<RefPtr<VideoStreamTrack>> videoTracks;
mSrcStream->GetVideoTracks(videoTracks);
PrincipalHandle handle(aPrincipalHandle);
bool matchesTrackPrincipal = false;
for (const RefPtr<VideoStreamTrack>& track : videoTracks) {
if (PrincipalHandleMatches(handle,
track->GetPrincipal()) &&
!track->Ended()) {
// When the PrincipalHandle for the VideoFrameContainer changes to that of
// a track in mSrcStream we know that a removed track was displayed but
// is no longer so.
matchesTrackPrincipal = true;
LOG(LogLevel::Debug, ("HTMLMediaElement %p VideoFrameContainer's "
"PrincipalHandle matches track %p. That's all we "
"need.", this, track.get()));
break;
}
}
if (matchesTrackPrincipal) {
mSrcStreamVideoPrincipal = mSrcStream->GetVideoPrincipal();
}
}
void
HTMLMediaElement::PrincipalHandleChangedForVideoFrameContainer(VideoFrameContainer* aContainer,
const PrincipalHandle& aNewPrincipalHandle)
{
MOZ_ASSERT(NS_IsMainThread());
if (!mSrcStream) {
return;
}
LOG(LogLevel::Debug, ("HTMLMediaElement %p PrincipalHandle changed in "
"VideoFrameContainer.",
this));
UpdateSrcStreamVideoPrincipal(aNewPrincipalHandle);
}
nsresult HTMLMediaElement::DispatchEvent(const nsAString& aName)