Bug 1035056 part 1 - Force CDMProxy to shutdown on tab close or navigation. r=ehsan

This commit is contained in:
Chris Pearce 2014-08-18 09:41:50 +12:00
parent 3d6731b54e
commit d195f4a49f
6 changed files with 76 additions and 6 deletions

View File

@ -4299,6 +4299,32 @@ nsDocument::SetScopeObject(nsIGlobalObject* aGlobal)
}
}
#ifdef MOZ_EME
static void
CheckIfContainsEMEContent(nsISupports* aSupports, void* aContainsEME)
{
nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aSupports));
if (domMediaElem) {
nsCOMPtr<nsIContent> content(do_QueryInterface(domMediaElem));
MOZ_ASSERT(content, "aSupports is not a content");
HTMLMediaElement* mediaElem = static_cast<HTMLMediaElement*>(content.get());
bool* contains = static_cast<bool*>(aContainsEME);
if (mediaElem->GetMediaKeys()) {
*contains = true;
}
}
}
bool
nsDocument::ContainsEMEContent()
{
bool containsEME = false;
EnumerateActivityObservers(CheckIfContainsEMEContent,
static_cast<void*>(&containsEME));
return containsEME;
}
#endif // MOZ_EME
static void
NotifyActivityChanged(nsISupports *aSupports, void *aUnused)
{
@ -8456,6 +8482,14 @@ nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
}
#endif // MOZ_WEBRTC
#ifdef MOZ_EME
// Don't save presentations for documents containing EME content, so that
// CDMs reliably shutdown upon user navigation.
if (ContainsEMEContent()) {
return false;
}
#endif
bool canCache = true;
if (mSubDocuments)
PL_DHashTableEnumerate(mSubDocuments, CanCacheSubDocument, &canCache);

View File

@ -1406,6 +1406,10 @@ public:
js::ExpandoAndGeneration mExpandoAndGeneration;
#ifdef MOZ_EME
bool ContainsEMEContent();
#endif
protected:
already_AddRefed<nsIPresShell> doCreateShell(nsPresContext* aContext,
nsViewManager* aViewManager,

View File

@ -3412,6 +3412,20 @@ void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendE
if (aPauseElement != mPausedForInactiveDocumentOrChannel) {
mPausedForInactiveDocumentOrChannel = aPauseElement;
if (aPauseElement) {
#ifdef MOZ_EME
// For EME content, force destruction of the CDM client (and CDM
// instance if this is the last client for that CDM instance) and
// the CDM's decoder. This ensures the CDM gets reliable and prompt
// shutdown notifications, as it may have book-keeping it needs
// to do on shutdown.
if (mMediaKeys) {
mMediaKeys->Shutdown();
mMediaKeys = nullptr;
}
if (mDecoder) {
ShutdownDecoder();
}
#endif
if (mDecoder) {
mDecoder->Pause();
mDecoder->Suspend();
@ -3420,6 +3434,9 @@ void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendE
}
mEventDeliveryPaused = aSuspendEvents;
} else {
#ifdef MOZ_EME
MOZ_ASSERT(!mMediaKeys);
#endif
if (mDecoder) {
mDecoder->Resume(false);
if (!mPaused && !mDecoder->IsEnded()) {

View File

@ -39,6 +39,7 @@ void
CDMProxy::Init(PromiseId aPromiseId)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE_VOID(!mKeys.IsNull());
nsresult rv = mKeys->GetOrigin(mOrigin);
if (NS_FAILED(rv)) {
@ -103,11 +104,10 @@ void
CDMProxy::OnCDMCreated(uint32_t aPromiseId)
{
MOZ_ASSERT(NS_IsMainThread());
if (!mKeys.IsNull()) {
mKeys->OnCDMCreated(aPromiseId);
} else {
NS_WARNING("CDMProxy unable to reject promise!");
if (mKeys.IsNull()) {
return;
}
mKeys->OnCDMCreated(aPromiseId);
}
void
@ -323,8 +323,6 @@ CDMProxy::RejectPromise(PromiseId aId, nsresult aCode)
if (NS_IsMainThread()) {
if (!mKeys.IsNull()) {
mKeys->RejectPromise(aId, aCode);
} else {
NS_WARNING("CDMProxy unable to reject promise!");
}
} else {
nsRefPtr<nsIRunnable> task(new RejectPromiseTask(this, aId, aCode));
@ -361,6 +359,9 @@ CDMProxy::OnResolveNewSessionPromise(uint32_t aPromiseId,
const nsAString& aSessionId)
{
MOZ_ASSERT(NS_IsMainThread());
if (mKeys.IsNull()) {
return;
}
mKeys->OnSessionCreated(aPromiseId, aSessionId);
}
@ -370,6 +371,9 @@ CDMProxy::OnSessionMessage(const nsAString& aSessionId,
const nsAString& aDestinationURL)
{
MOZ_ASSERT(NS_IsMainThread());
if (mKeys.IsNull()) {
return;
}
nsRefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
if (session) {
session->DispatchKeyMessage(aMessage, aDestinationURL);
@ -411,6 +415,9 @@ CDMProxy::OnSessionError(const nsAString& aSessionId,
const nsAString& aMsg)
{
MOZ_ASSERT(NS_IsMainThread());
if (mKeys.IsNull()) {
return;
}
nsRefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId));
if (session) {
session->DispatchKeyError(aSystemCode);

View File

@ -54,6 +54,12 @@ RejectPromises(const uint32_t& aKey,
}
MediaKeys::~MediaKeys()
{
Shutdown();
}
void
MediaKeys::Shutdown()
{
if (mProxy) {
mProxy->Shutdown();

View File

@ -103,6 +103,8 @@ public:
nsresult GetOrigin(nsString& aOutOrigin);
void Shutdown();
private:
// Removes promise from mPromises, and returns it.