Bug 1145011 - Implement waitingforkey event. r=jya

Bubble information from SamplesWaitingForKey to an HTMLMediaElement so that we
can emit a waitingForKey event. If we are unable to decode more samples due to
needing a key the event will be signalled. See
http://w3c.github.io/encrypted-media/#dom-evt-waitingforkey for more information
on this event.

The code in place before this patch handles updating readyState when we are
waiting for a key, this patch adds the event which should be emitted in such a
case. The spec defines certain preconditions should be the case before running
the algo to emit this event. For example, the element should potentially be
playing, and it should have at least HAVE_FUTURE_DATA ready state. This is not
strictly true for when the new code is run, due how existing code handles ready
state. We are honoring the spirit of the spec, though the letter of the spec is
lightly gone against in the handling of the preconditions.

MozReview-Commit-ID: LKlDd4wkRSE
This commit is contained in:
Bryce Van Dyk
2016-08-22 08:51:01 +12:00
parent bf1ab30f1a
commit 8c84be1a8f
12 changed files with 105 additions and 4 deletions

View File

@@ -907,6 +907,7 @@ void HTMLMediaElement::ShutdownDecoder()
{
RemoveMediaElementFromURITable();
NS_ASSERTION(mDecoder, "Must have decoder to shut down");
mWaitingForKeyListener.DisconnectIfExists();
mDecoder->Shutdown();
mDecoder = nullptr;
}
@@ -983,6 +984,7 @@ void HTMLMediaElement::AbortExistingLoads()
#ifdef MOZ_EME
mPendingEncryptedInitData.mInitDatas.Clear();
#endif // MOZ_EME
mWaitingForKey = false;
mSourcePointer = nullptr;
mTags = nullptr;
@@ -2509,6 +2511,7 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
mMediaSecurityVerified(false),
mCORSMode(CORS_NONE),
mIsEncrypted(false),
mWaitingForKey(false),
mDownloadSuspendedByCache(false, "HTMLMediaElement::mDownloadSuspendedByCache"),
mAudioChannelVolume(1.0),
mPlayingThroughTheAudioChannel(false),
@@ -3439,6 +3442,13 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder,
}
#endif
MediaEventSource<void>* waitingForKeyProducer = mDecoder->WaitingForKeyEvent();
// Not every decoder will produce waitingForKey events, only add ones that can
if (waitingForKeyProducer) {
mWaitingForKeyListener = waitingForKeyProducer->Connect(
AbstractThread::MainThread(), this, &HTMLMediaElement::CannotDecryptWaitingForKey);
}
if (mChannelLoader) {
mChannelLoader->Done();
mChannelLoader = nullptr;
@@ -4501,6 +4511,7 @@ void HTMLMediaElement::ChangeReadyState(nsMediaReadyState aState)
if (oldState < nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA &&
mReadyState >= nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA &&
IsPotentiallyPlaying()) {
mWaitingForKey = false;
DispatchAsyncEvent(NS_LITERAL_STRING("playing"));
}
@@ -5886,6 +5897,27 @@ HTMLMediaElement::GetTopLevelPrincipal()
}
#endif // MOZ_EME
void
HTMLMediaElement::CannotDecryptWaitingForKey()
{
// See: http://w3c.github.io/encrypted-media/#dom-evt-waitingforkey
// Spec: 7.5.4 Queue a "waitingforkey" Event
// Spec: 1. Let the media element be the specified HTMLMediaElement object.
// Note, existing code will handle the ready state of this element, as
// such this function does not handle changing or checking mReadyState.
// Spec: 2. If the media element's waiting for key value is true, abort these steps.
if (!mWaitingForKey) {
// Spec: 3. Set the media element's waiting for key value to true.
// Spec: 4. Queue a task to fire a simple event named waitingforkey at the media element.
DispatchAsyncEvent(NS_LITERAL_STRING("waitingforkey"));
mWaitingForKey = true;
// No need to explicitly suspend playback, it happens automatically when
// it's starving for decoded frames.
}
}
NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged(bool aCapture)
{
MOZ_ASSERT(mAudioChannelAgent);