diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index cbbc23b252..07d68d6184 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -866,10 +866,3 @@ bin/libfreebl_32int64_3.so #if defined(MOZ_ASAN) && defined(CLANG_CL) @BINPATH@/clang_rt.asan_dynamic-i386.dll #endif - - -; media -#ifdef MOZ_EME -@RESPATH@/gmp-clearkey/0.1/@DLL_PREFIX@clearkey@DLL_SUFFIX@ -@RESPATH@/gmp-clearkey/0.1/clearkey.info -#endif diff --git a/configure.in b/configure.in index a3c91c49ea..d8a73fb493 100644 --- a/configure.in +++ b/configure.in @@ -5290,23 +5290,6 @@ MOZ_ARG_DISABLE_BOOL(fmp4, if test -n "$MOZ_FMP4"; then AC_DEFINE(MOZ_FMP4) - MOZ_EME=1 -fi; - -dnl ======================================================== -dnl = EME support -dnl ======================================================== - -MOZ_ARG_DISABLE_BOOL(eme, -[ --disable-eme Disable support for Encrypted Media Extensions], - MOZ_EME=, - MOZ_EME=1) - -if test -n "$MOZ_EME"; then - if test -z "$MOZ_FMP4"; then - AC_MSG_ERROR([Encrypted Media Extension support requires Fragmented MP4 support]) - fi - AC_DEFINE(MOZ_EME) fi; dnl ======================================================== @@ -8737,7 +8720,6 @@ AC_SUBST(MOZ_WEBM) AC_SUBST(MOZ_WMF) AC_SUBST(MOZ_FFMPEG) AC_SUBST(MOZ_FMP4) -AC_SUBST(MOZ_EME) AC_SUBST(MOZ_DIRECTSHOW) AC_SUBST(MOZ_ANDROID_OMX) AC_SUBST(MOZ_APPLEMEDIA) diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index a9ef52536e..c8ddcf72f9 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -112,10 +112,6 @@ #include "mozilla/dom/FeatureList.h" -#ifdef MOZ_EME -#include "mozilla/EMEUtils.h" -#endif - namespace mozilla { namespace dom { @@ -200,9 +196,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedResolveResults) -#ifdef MOZ_EME - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager) -#endif NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END @@ -317,12 +310,6 @@ Navigator::Invalidate() mServiceWorkerContainer = nullptr; -#ifdef MOZ_EME - if (mMediaKeySystemAccessManager) { - mMediaKeySystemAccessManager->Shutdown(); - mMediaKeySystemAccessManager = nullptr; - } -#endif } //***************************************************************************** @@ -2630,27 +2617,5 @@ Navigator::GetUserAgent(nsPIDOMWindow* aWindow, nsIURI* aURI, return siteSpecificUA->GetUserAgentForURIAndWindow(aURI, aWindow, aUserAgent); } -#ifdef MOZ_EME -already_AddRefed -Navigator::RequestMediaKeySystemAccess(const nsAString& aKeySystem, - const Optional>& aOptions, - ErrorResult& aRv) -{ - nsCOMPtr go = do_QueryInterface(mWindow); - nsRefPtr promise = Promise::Create(go, aRv); - if (aRv.Failed()) { - return nullptr; - } - - if (!mMediaKeySystemAccessManager) { - mMediaKeySystemAccessManager = new MediaKeySystemAccessManager(mWindow); - } - - mMediaKeySystemAccessManager->Request(promise, aKeySystem, aOptions); - return promise.forget(); -} - -#endif - } // namespace dom } // namespace mozilla diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h index 20abc8d6f7..7eaad6f7fc 100644 --- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h @@ -18,9 +18,6 @@ #include "nsInterfaceHashtable.h" #include "nsString.h" #include "nsTArray.h" -#ifdef MOZ_EME -#include "mozilla/dom/MediaKeySystemAccessManager.h" -#endif class nsPluginArray; class nsMimeTypeArray; @@ -330,15 +327,6 @@ public: // any, else null. static already_AddRefed GetWindowFromGlobal(JSObject* aGlobal); -#ifdef MOZ_EME - already_AddRefed - RequestMediaKeySystemAccess(const nsAString& aKeySystem, - const Optional>& aOptions, - ErrorResult& aRv); -private: - nsRefPtr mMediaKeySystemAccessManager; -#endif - private: virtual ~Navigator(); diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 07fbd8822f..04053700e7 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -4554,32 +4554,6 @@ nsDocument::SetScopeObject(nsIGlobalObject* aGlobal) } } -#ifdef MOZ_EME -static void -CheckIfContainsEMEContent(nsISupports* aSupports, void* aContainsEME) -{ - nsCOMPtr domMediaElem(do_QueryInterface(aSupports)); - if (domMediaElem) { - nsCOMPtr content(do_QueryInterface(domMediaElem)); - MOZ_ASSERT(content, "aSupports is not a content"); - HTMLMediaElement* mediaElem = static_cast(content.get()); - bool* contains = static_cast(aContainsEME); - if (mediaElem->GetMediaKeys()) { - *contains = true; - } - } -} - -bool -nsDocument::ContainsEMEContent() -{ - bool containsEME = false; - EnumerateActivityObservers(CheckIfContainsEMEContent, - static_cast(&containsEME)); - return containsEME; -} -#endif // MOZ_EME - static void CheckIfContainsMSEContent(nsISupports* aSupports, void* aContainsMSE) { @@ -8855,14 +8829,6 @@ 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 - // Don't save presentations for documents containing MSE content, to // reduce memory usage. if (ContainsMSEContent()) { diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h index fa5108bcb2..edd076ea85 100644 --- a/dom/base/nsDocument.h +++ b/dom/base/nsDocument.h @@ -1473,10 +1473,6 @@ public: js::ExpandoAndGeneration mExpandoAndGeneration; -#ifdef MOZ_EME - bool ContainsEMEContent(); -#endif - bool ContainsMSEContent(); protected: diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index c3bc3402f5..b35635b781 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -11,9 +11,6 @@ #include "mozilla/ArrayUtils.h" #include "mozilla/MathAlgorithms.h" #include "mozilla/AsyncEventDispatcher.h" -#ifdef MOZ_EME -#include "mozilla/dom/MediaEncryptedEvent.h" -#endif #include "base/basictypes.h" #include "nsIDOMHTMLMediaElement.h" @@ -451,9 +448,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTM NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextTrackManager) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioTrackList) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVideoTrackList) -#ifdef MOZ_EME - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeys) -#endif NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLElement) @@ -476,9 +470,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTMLE NS_IMPL_CYCLE_COLLECTION_UNLINK(mTextTrackManager) NS_IMPL_CYCLE_COLLECTION_UNLINK(mAudioTrackList) NS_IMPL_CYCLE_COLLECTION_UNLINK(mVideoTrackList) -#ifdef MOZ_EME - NS_IMPL_CYCLE_COLLECTION_UNLINK(mMediaKeys) -#endif NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLMediaElement) @@ -642,14 +633,6 @@ void HTMLMediaElement::ShutdownDecoder() void HTMLMediaElement::AbortExistingLoads() { -#ifdef MOZ_EME - // If there is no existing decoder then we don't have anything to - // report. This prevents reporting the initial load from an - // empty video element as a failed EME load. - if (mDecoder) { - ReportEMETelemetry(); - } -#endif // Abort any already-running instance of the resource selection algorithm. mLoadWaitStatus = NOT_WAITING; @@ -1183,14 +1166,6 @@ nsresult HTMLMediaElement::LoadResource() // Set the media element's CORS mode only when loading a resource mCORSMode = AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)); -#ifdef MOZ_EME - if (mMediaKeys && - !IsMediaStreamURI(mLoadingSrc) && - Preferences::GetBool("media.eme.mse-only", true)) { - return NS_ERROR_DOM_NOT_SUPPORTED_ERR; - } -#endif - HTMLMediaElement* other = LookupMediaElementURITable(mLoadingSrc); if (other && other->mDecoder) { // Clone it. @@ -1881,11 +1856,6 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded) if (!window) { return nullptr; } -#ifdef MOZ_EME - if (ContainsRestrictedContent()) { - return nullptr; - } -#endif OutputMediaStream* out = mOutputStreams.AppendElement(); out->mStream = DOMMediaStream::CreateTrackUnionStream(window); nsRefPtr principal = GetCurrentPrincipal(); @@ -2587,20 +2557,6 @@ nsresult HTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParen return rv; } -#ifdef MOZ_EME -void -HTMLMediaElement::ReportEMETelemetry() -{ - // Report telemetry for EME videos when a page is unloaded. - NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); - if (mIsEncrypted && Preferences::GetBool("media.eme.enabled")) { - Telemetry::Accumulate(Telemetry::VIDEO_EME_PLAY_SUCCESS, mLoadedDataFired); - LOG(PR_LOG_DEBUG, ("%p VIDEO_EME_PLAY_SUCCESS = %s", - this, mLoadedDataFired ? "true" : "false")); - } -} -#endif - void HTMLMediaElement::ReportMSETelemetry() { @@ -2845,12 +2801,6 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder, return rv; } -#ifdef MOZ_EME - if (mMediaKeys) { - mDecoder->SetCDMProxy(mMediaKeys->GetCDMProxy()); - } -#endif - // Decoder successfully created, the decoder now owns the MediaResource // which owns the channel. mChannel = nullptr; @@ -3909,25 +3859,8 @@ void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendE if (aPauseElement) { if (mMediaSource) { ReportMSETelemetry(); -#ifdef MOZ_EME - ReportEMETelemetry(); -#endif } -#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(); @@ -3936,9 +3869,6 @@ 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->IsEndedOrShutdown()) { @@ -4496,137 +4426,6 @@ NS_IMETHODIMP HTMLMediaElement::CanPlayChanged(int32_t canPlay) return NS_OK; } -#ifdef MOZ_EME -MediaKeys* -HTMLMediaElement::GetMediaKeys() const -{ - return mMediaKeys; -} - -bool -HTMLMediaElement::ContainsRestrictedContent() -{ - return GetMediaKeys() != nullptr; -} - -already_AddRefed -HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys, - ErrorResult& aRv) -{ - if (MozAudioCaptured()) { - aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return nullptr; - } - - nsCOMPtr global = - do_QueryInterface(OwnerDoc()->GetInnerWindow()); - if (!global) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - nsRefPtr promise = Promise::Create(global, aRv); - if (aRv.Failed()) { - return nullptr; - } - if (mMediaKeys == aMediaKeys) { - promise->MaybeResolve(JS::UndefinedHandleValue); - return promise.forget(); - } - if (aMediaKeys && aMediaKeys->IsBoundToMediaElement()) { - promise->MaybeReject(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR); - return promise.forget(); - } - if (mMediaKeys) { - // Existing MediaKeys object. Shut it down. - mMediaKeys->Shutdown(); - mMediaKeys = nullptr; - } - if (mDecoder && - !mMediaSource && - Preferences::GetBool("media.eme.mse-only", true)) { - ShutdownDecoder(); - promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return promise.forget(); - } - - mMediaKeys = aMediaKeys; - if (mMediaKeys) { - if (NS_FAILED(mMediaKeys->Bind(this))) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - mMediaKeys = nullptr; - return promise.forget(); - } - if (mDecoder) { - mDecoder->SetCDMProxy(mMediaKeys->GetCDMProxy()); - } - } - promise->MaybeResolve(JS::UndefinedHandleValue); - return promise.forget(); -} - -EventHandlerNonNull* -HTMLMediaElement::GetOnencrypted() -{ - EventListenerManager *elm = GetExistingListenerManager(); - return elm ? elm->GetEventHandler(nsGkAtoms::onencrypted, EmptyString()) - : nullptr; -} - -void -HTMLMediaElement::SetOnencrypted(EventHandlerNonNull* handler) -{ - EventListenerManager *elm = GetOrCreateListenerManager(); - if (elm) { - elm->SetEventHandler(nsGkAtoms::onencrypted, EmptyString(), handler); - } -} - -void -HTMLMediaElement::DispatchEncrypted(const nsTArray& aInitData, - const nsAString& aInitDataType) -{ - nsRefPtr event; - if (IsCORSSameOrigin()) { - event = MediaEncryptedEvent::Constructor(this, aInitDataType, aInitData); - } else { - event = MediaEncryptedEvent::Constructor(this); - } - - nsRefPtr asyncDispatcher = - new AsyncEventDispatcher(this, event); - asyncDispatcher->PostDOMEvent(); -} - -bool -HTMLMediaElement::IsEventAttributeName(nsIAtom* aName) -{ - return aName == nsGkAtoms::onencrypted || - nsGenericHTMLElement::IsEventAttributeName(aName); -} - -already_AddRefed -HTMLMediaElement::GetTopLevelPrincipal() -{ - nsRefPtr principal; - nsCOMPtr window = do_QueryInterface(OwnerDoc()->GetParentObject()); - nsCOMPtr topWindow; - if (!window) { - return nullptr; - } - window->GetTop(getter_AddRefs(topWindow)); - nsCOMPtr top = do_QueryInterface(topWindow); - if (!top) { - return nullptr; - } - nsIDocument* doc = top->GetExtantDoc(); - if (!doc) { - return nullptr; - } - principal = doc->NodePrincipal(); - return principal.forget(); -} -#endif // MOZ_EME - NS_IMETHODIMP HTMLMediaElement::WindowVolumeChanged() { SetVolumeInternal(); diff --git a/dom/html/HTMLMediaElement.h b/dom/html/HTMLMediaElement.h index a4c4757989..402e5f263c 100644 --- a/dom/html/HTMLMediaElement.h +++ b/dom/html/HTMLMediaElement.h @@ -20,9 +20,6 @@ #include "mozilla/dom/Promise.h" #include "mozilla/dom/TextTrackManager.h" #include "MediaDecoder.h" -#ifdef MOZ_EME -#include "mozilla/dom/MediaKeys.h" -#endif #include "nsGkAtoms.h" // X.h on Linux #defines CurrentTime as 0L, so we have to #undef it here. @@ -552,28 +549,6 @@ public: // XPCOM MozPreservesPitch() is OK -#ifdef MOZ_EME - MediaKeys* GetMediaKeys() const; - - already_AddRefed SetMediaKeys(MediaKeys* mediaKeys, - ErrorResult& aRv); - - mozilla::dom::EventHandlerNonNull* GetOnencrypted(); - void SetOnencrypted(mozilla::dom::EventHandlerNonNull* listener); - - void DispatchEncrypted(const nsTArray& aInitData, - const nsAString& aInitDataType) override; - - - bool IsEventAttributeName(nsIAtom* aName) override; - - // Returns the principal of the "top level" document; the origin displayed - // in the URL bar of the browser window. - already_AddRefed GetTopLevelPrincipal(); - - bool ContainsRestrictedContent(); -#endif // MOZ_EME - bool MozAutoplayEnabled() const { return mAutoplayEnabled; @@ -982,9 +957,6 @@ protected: return isPaused; } -#ifdef MOZ_EME - void ReportEMETelemetry(); -#endif void ReportMSETelemetry(); // Check the permissions for audiochannel. @@ -1190,11 +1162,6 @@ protected: // Timer used for updating progress events nsCOMPtr mProgressTimer; -#ifdef MOZ_EME - // Encrypted Media Extension media keys. - nsRefPtr mMediaKeys; -#endif - // Stores the time at the start of the current 'played' range. double mCurrentPlayRangeStart; diff --git a/dom/media/AbstractMediaDecoder.h b/dom/media/AbstractMediaDecoder.h index 7094b5fe95..8f714fe3ed 100644 --- a/dom/media/AbstractMediaDecoder.h +++ b/dom/media/AbstractMediaDecoder.h @@ -25,9 +25,6 @@ class ReentrantMonitor; class VideoFrameContainer; class TimedMetadata; class MediaDecoderOwner; -#ifdef MOZ_EME -class CDMProxy; -#endif typedef nsDataHashtable MetadataTags; @@ -159,10 +156,6 @@ public: AbstractMediaDecoder* mDecoder; }; -#ifdef MOZ_EME - virtual nsresult SetCDMProxy(CDMProxy* aProxy) { return NS_ERROR_NOT_IMPLEMENTED; } - virtual CDMProxy* GetCDMProxy() { return nullptr; } -#endif }; class MetadataContainer diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index 5aa1e2a97e..53ec265900 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -1776,27 +1776,6 @@ bool MediaDecoder::CanPlayThrough() return stats.mDownloadPosition > stats.mPlaybackPosition + readAheadMargin; } -#ifdef MOZ_EME -nsresult -MediaDecoder::SetCDMProxy(CDMProxy* aProxy) -{ - ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); - MOZ_ASSERT(NS_IsMainThread()); - mProxy = aProxy; - // Awaken any readers waiting for the proxy. - NotifyWaitingForResourcesStatusChanged(); - return NS_OK; -} - -CDMProxy* -MediaDecoder::GetCDMProxy() -{ - GetReentrantMonitor().AssertCurrentThreadIn(); - MOZ_ASSERT(OnDecodeThread() || NS_IsMainThread()); - return mProxy; -} -#endif - #ifdef MOZ_RAW bool MediaDecoder::IsRawEnabled() diff --git a/dom/media/MediaDecoder.h b/dom/media/MediaDecoder.h index df7edd3920..50997a48d7 100644 --- a/dom/media/MediaDecoder.h +++ b/dom/media/MediaDecoder.h @@ -196,9 +196,6 @@ destroying the MediaDecoder object. #include "MediaStreamGraph.h" #include "AbstractMediaDecoder.h" #include "necko-config.h" -#ifdef MOZ_EME -#include "mozilla/CDMProxy.h" -#endif class nsIStreamListener; class nsIPrincipal; @@ -853,14 +850,6 @@ public: // The decoder monitor must be held. bool IsLogicallyPlaying(); -#ifdef MOZ_EME - // This takes the decoder monitor. - virtual nsresult SetCDMProxy(CDMProxy* aProxy) override; - - // Decoder monitor must be held. - virtual CDMProxy* GetCDMProxy() override; -#endif - #ifdef MOZ_RAW static bool IsRawEnabled(); #endif @@ -1117,10 +1106,6 @@ private: // change. Explicitly private for force access via GetReentrantMonitor. ReentrantMonitor mReentrantMonitor; -#ifdef MOZ_EME - nsRefPtr mProxy; -#endif - protected: // Data about MediaStreams that are being fed by this decoder. nsTArray mOutputStreams; diff --git a/dom/media/MediaDecoderOwner.h b/dom/media/MediaDecoderOwner.h index 23f7e96344..cf6be0f5d3 100644 --- a/dom/media/MediaDecoderOwner.h +++ b/dom/media/MediaDecoderOwner.h @@ -133,14 +133,6 @@ public: // Called by the media decoder object, on the main thread, // when the connection between Rtsp server and client gets lost. virtual void ResetConnectionState() = 0; - -#ifdef MOZ_EME - // Dispatches a "encrypted" event to the HTMLMediaElement, with the - // provided init data. - // Main thread only. - virtual void DispatchEncrypted(const nsTArray& aInitData, - const nsAString& aInitDataType) = 0; -#endif }; } diff --git a/dom/media/eme/CDMCallbackProxy.cpp b/dom/media/eme/CDMCallbackProxy.cpp deleted file mode 100644 index 4466a3d08c..0000000000 --- a/dom/media/eme/CDMCallbackProxy.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/CDMCallbackProxy.h" -#include "mozilla/CDMProxy.h" -#include "nsString.h" -#include "mozilla/dom/MediaKeys.h" -#include "mozilla/dom/MediaKeySession.h" -#include "mozIGoannaMediaPluginService.h" -#include "nsContentCID.h" -#include "nsServiceManagerUtils.h" -#include "MainThreadUtils.h" -#include "mozilla/EMEUtils.h" - -namespace mozilla { - -CDMCallbackProxy::CDMCallbackProxy(CDMProxy* aProxy) - : mProxy(aProxy) -{ - -} - -class SetSessionIdTask : public nsRunnable { -public: - SetSessionIdTask(CDMProxy* aProxy, - uint32_t aToken, - const nsCString& aSessionId) - : mProxy(aProxy) - , mToken(aToken) - , mSid(NS_ConvertUTF8toUTF16(aSessionId)) - { - } - - NS_IMETHOD Run() { - mProxy->OnSetSessionId(mToken, mSid); - return NS_OK; - } - - nsRefPtr mProxy; - uint32_t mToken; - nsString mSid; -}; - -void -CDMCallbackProxy::SetSessionId(uint32_t aToken, - const nsCString& aSessionId) -{ - MOZ_ASSERT(mProxy->IsOnGMPThread()); - - nsRefPtr task(new SetSessionIdTask(mProxy, - aToken, - aSessionId)); - NS_DispatchToMainThread(task); -} - -class LoadSessionTask : public nsRunnable { -public: - LoadSessionTask(CDMProxy* aProxy, - uint32_t aPromiseId, - bool aSuccess) - : mProxy(aProxy) - , mPid(aPromiseId) - , mSuccess(aSuccess) - { - } - - NS_IMETHOD Run() { - mProxy->OnResolveLoadSessionPromise(mPid, mSuccess); - return NS_OK; - } - - nsRefPtr mProxy; - dom::PromiseId mPid; - bool mSuccess; -}; - -void -CDMCallbackProxy::ResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess) -{ - MOZ_ASSERT(mProxy->IsOnGMPThread()); - - nsRefPtr task(new LoadSessionTask(mProxy, - aPromiseId, - aSuccess)); - NS_DispatchToMainThread(task); -} - -void -CDMCallbackProxy::ResolvePromise(uint32_t aPromiseId) -{ - MOZ_ASSERT(mProxy->IsOnGMPThread()); - - // Note: CDMProxy proxies this from non-main threads to main thread. - mProxy->ResolvePromise(aPromiseId); -} - -class RejectPromiseTask : public nsRunnable { -public: - RejectPromiseTask(CDMProxy* aProxy, - uint32_t aPromiseId, - nsresult aException, - const nsCString& aMessage) - : mProxy(aProxy) - , mPid(aPromiseId) - , mException(aException) - , mMsg(NS_ConvertUTF8toUTF16(aMessage)) - { - } - - NS_IMETHOD Run() { - mProxy->OnRejectPromise(mPid, mException, mMsg); - return NS_OK; - } - - nsRefPtr mProxy; - dom::PromiseId mPid; - nsresult mException; - nsString mMsg; -}; - - -void -CDMCallbackProxy::RejectPromise(uint32_t aPromiseId, - nsresult aException, - const nsCString& aMessage) -{ - MOZ_ASSERT(mProxy->IsOnGMPThread()); - - nsRefPtr task; - task = new RejectPromiseTask(mProxy, - aPromiseId, - aException, - aMessage); - NS_DispatchToMainThread(task); -} - -class SessionMessageTask : public nsRunnable { -public: - SessionMessageTask(CDMProxy* aProxy, - const nsCString& aSessionId, - GMPSessionMessageType aMessageType, - const nsTArray& aMessage) - : mProxy(aProxy) - , mSid(NS_ConvertUTF8toUTF16(aSessionId)) - , mMsgType(aMessageType) - { - mMsg.AppendElements(aMessage); - } - - NS_IMETHOD Run() { - mProxy->OnSessionMessage(mSid, mMsgType, mMsg); - return NS_OK; - } - - nsRefPtr mProxy; - dom::PromiseId mPid; - nsString mSid; - GMPSessionMessageType mMsgType; - nsTArray mMsg; -}; - -void -CDMCallbackProxy::SessionMessage(const nsCString& aSessionId, - GMPSessionMessageType aMessageType, - const nsTArray& aMessage) -{ - MOZ_ASSERT(mProxy->IsOnGMPThread()); - - nsRefPtr task; - task = new SessionMessageTask(mProxy, - aSessionId, - aMessageType, - aMessage); - NS_DispatchToMainThread(task); -} - -class ExpirationChangeTask : public nsRunnable { -public: - ExpirationChangeTask(CDMProxy* aProxy, - const nsCString& aSessionId, - GMPTimestamp aExpiryTime) - : mProxy(aProxy) - , mSid(NS_ConvertUTF8toUTF16(aSessionId)) - , mTimestamp(aExpiryTime) - {} - - NS_IMETHOD Run() { - mProxy->OnExpirationChange(mSid, mTimestamp); - return NS_OK; - } - - nsRefPtr mProxy; - nsString mSid; - GMPTimestamp mTimestamp; -}; - -void -CDMCallbackProxy::ExpirationChange(const nsCString& aSessionId, - GMPTimestamp aExpiryTime) -{ - MOZ_ASSERT(mProxy->IsOnGMPThread()); - - nsRefPtr task; - task = new ExpirationChangeTask(mProxy, - aSessionId, - aExpiryTime); - NS_DispatchToMainThread(task); -} - -void -CDMCallbackProxy::SessionClosed(const nsCString& aSessionId) -{ - MOZ_ASSERT(mProxy->IsOnGMPThread()); - - nsRefPtr task; - task = NS_NewRunnableMethodWithArg(mProxy, - &CDMProxy::OnSessionClosed, - NS_ConvertUTF8toUTF16(aSessionId)); - NS_DispatchToMainThread(task); -} - -class SessionErrorTask : public nsRunnable { -public: - SessionErrorTask(CDMProxy* aProxy, - const nsCString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsCString& aMessage) - : mProxy(aProxy) - , mSid(NS_ConvertUTF8toUTF16(aSessionId)) - , mException(aException) - , mSystemCode(aSystemCode) - , mMsg(NS_ConvertUTF8toUTF16(aMessage)) - {} - - NS_IMETHOD Run() { - mProxy->OnSessionError(mSid, mException, mSystemCode, mMsg); - return NS_OK; - } - - nsRefPtr mProxy; - dom::PromiseId mPid; - nsString mSid; - nsresult mException; - uint32_t mSystemCode; - nsString mMsg; -}; - -void -CDMCallbackProxy::SessionError(const nsCString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsCString& aMessage) -{ - MOZ_ASSERT(mProxy->IsOnGMPThread()); - - nsRefPtr task; - task = new SessionErrorTask(mProxy, - aSessionId, - aException, - aSystemCode, - aMessage); - NS_DispatchToMainThread(task); -} - -void -CDMCallbackProxy::KeyStatusChanged(const nsCString& aSessionId, - const nsTArray& aKeyId, - GMPMediaKeyStatus aStatus) -{ - MOZ_ASSERT(mProxy->IsOnGMPThread()); - - bool keyStatusesChange = false; - { - CDMCaps::AutoLock caps(mProxy->Capabilites()); - keyStatusesChange = caps.SetKeyStatus(aKeyId, - NS_ConvertUTF8toUTF16(aSessionId), - aStatus); - } - if (keyStatusesChange) { - nsRefPtr task; - task = NS_NewRunnableMethodWithArg(mProxy, - &CDMProxy::OnKeyStatusesChange, - NS_ConvertUTF8toUTF16(aSessionId)); - NS_DispatchToMainThread(task); - } -} - -void -CDMCallbackProxy::SetCaps(uint64_t aCaps) -{ - MOZ_ASSERT(mProxy->IsOnGMPThread()); - - CDMCaps::AutoLock caps(mProxy->Capabilites()); - caps.SetCaps(aCaps); -} - -void -CDMCallbackProxy::Decrypted(uint32_t aId, - GMPErr aResult, - const nsTArray& aDecryptedData) -{ - MOZ_ASSERT(mProxy->IsOnGMPThread()); - - mProxy->gmp_Decrypted(aId, aResult, aDecryptedData); -} - -void -CDMCallbackProxy::Terminated() -{ - MOZ_ASSERT(mProxy->IsOnGMPThread()); - nsRefPtr task = NS_NewRunnableMethod(mProxy, &CDMProxy::Terminated); - NS_DispatchToMainThread(task); -} - -} // namespace mozilla diff --git a/dom/media/eme/CDMCallbackProxy.h b/dom/media/eme/CDMCallbackProxy.h deleted file mode 100644 index 60e085e6c5..0000000000 --- a/dom/media/eme/CDMCallbackProxy.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef CDMCallbackProxy_h_ -#define CDMCallbackProxy_h_ - -#include "mozilla/CDMProxy.h" -#include "gmp-decryption.h" -#include "GMPDecryptorProxy.h" - -namespace mozilla { - -// Proxies call backs from the CDM on the GMP thread back to the MediaKeys -// object on the main thread. -class CDMCallbackProxy : public GMPDecryptorProxyCallback { -public: - virtual void SetSessionId(uint32_t aCreateSessionToken, - const nsCString& aSessionId) override; - - virtual void ResolveLoadSessionPromise(uint32_t aPromiseId, - bool aSuccess) override; - - virtual void ResolvePromise(uint32_t aPromiseId) override; - - virtual void RejectPromise(uint32_t aPromiseId, - nsresult aException, - const nsCString& aSessionId) override; - - virtual void SessionMessage(const nsCString& aSessionId, - GMPSessionMessageType aMessageType, - const nsTArray& aMessage) override; - - virtual void ExpirationChange(const nsCString& aSessionId, - GMPTimestamp aExpiryTime) override; - - virtual void SessionClosed(const nsCString& aSessionId) override; - - virtual void SessionError(const nsCString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsCString& aMessage) override; - - virtual void KeyStatusChanged(const nsCString& aSessionId, - const nsTArray& aKeyId, - GMPMediaKeyStatus aStatus) override; - - virtual void SetCaps(uint64_t aCaps) override; - - virtual void Decrypted(uint32_t aId, - GMPErr aResult, - const nsTArray& aDecryptedData) override; - - virtual void Terminated() override; - - ~CDMCallbackProxy() {} - -private: - friend class CDMProxy; - explicit CDMCallbackProxy(CDMProxy* aProxy); - - // Warning: Weak ref. - CDMProxy* mProxy; -}; - -} // namespace mozilla - -#endif // CDMCallbackProxy_h_ diff --git a/dom/media/eme/CDMCaps.cpp b/dom/media/eme/CDMCaps.cpp deleted file mode 100644 index a082566530..0000000000 --- a/dom/media/eme/CDMCaps.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/CDMCaps.h" -#include "mozilla/EMEUtils.h" -#include "nsThreadUtils.h" -#include "SamplesWaitingForKey.h" - -namespace mozilla { - -CDMCaps::CDMCaps() - : mMonitor("CDMCaps") - , mCaps(0) -{ -} - -CDMCaps::~CDMCaps() -{ -} - -void -CDMCaps::Lock() -{ - mMonitor.Lock(); -} - -void -CDMCaps::Unlock() -{ - mMonitor.Unlock(); -} - -bool -CDMCaps::HasCap(uint64_t aCap) -{ - mMonitor.AssertCurrentThreadOwns(); - return (mCaps & aCap) == aCap; -} - -CDMCaps::AutoLock::AutoLock(CDMCaps& aInstance) - : mData(aInstance) -{ - mData.Lock(); -} - -CDMCaps::AutoLock::~AutoLock() -{ - mData.Unlock(); -} - -#ifdef PR_LOGGING -static void -TestCap(uint64_t aFlag, - uint64_t aCaps, - const nsACString& aCapName, - nsACString& aCapStr) -{ - if (!(aFlag & aCaps)) { - return; - } - if (!aCapStr.IsEmpty()) { - aCapStr.AppendLiteral(","); - } - aCapStr.Append(aCapName); -} - -nsCString -CapsToString(uint64_t aCaps) -{ - nsCString capsStr; - TestCap(GMP_EME_CAP_DECRYPT_AUDIO, aCaps, NS_LITERAL_CSTRING("DecryptAudio"), capsStr); - TestCap(GMP_EME_CAP_DECRYPT_VIDEO, aCaps, NS_LITERAL_CSTRING("DecryptVideo"), capsStr); - TestCap(GMP_EME_CAP_DECRYPT_AND_DECODE_AUDIO, aCaps, NS_LITERAL_CSTRING("DecryptAndDecodeAudio"), capsStr); - TestCap(GMP_EME_CAP_DECRYPT_AND_DECODE_VIDEO, aCaps, NS_LITERAL_CSTRING("DecryptAndDecodeVideo"), capsStr); - return capsStr; -} -#endif // PR_LOGGING - -void -CDMCaps::AutoLock::SetCaps(uint64_t aCaps) -{ - EME_LOG("SetCaps() %s", CapsToString(aCaps).get()); - mData.mMonitor.AssertCurrentThreadOwns(); - mData.mCaps = aCaps; - for (size_t i = 0; i < mData.mWaitForCaps.Length(); i++) { - NS_DispatchToMainThread(mData.mWaitForCaps[i], NS_DISPATCH_NORMAL); - } - mData.mWaitForCaps.Clear(); -} - -void -CDMCaps::AutoLock::CallOnMainThreadWhenCapsAvailable(nsIRunnable* aContinuation) -{ - mData.mMonitor.AssertCurrentThreadOwns(); - if (mData.mCaps) { - NS_DispatchToMainThread(aContinuation, NS_DISPATCH_NORMAL); - MOZ_ASSERT(mData.mWaitForCaps.IsEmpty()); - } else { - mData.mWaitForCaps.AppendElement(aContinuation); - } -} - -bool -CDMCaps::AutoLock::IsKeyUsable(const CencKeyId& aKeyId) -{ - mData.mMonitor.AssertCurrentThreadOwns(); - const auto& keys = mData.mKeyStatuses; - for (size_t i = 0; i < keys.Length(); i++) { - if (keys[i].mId != aKeyId) { - continue; - } - if (keys[i].mStatus == kGMPUsable || - keys[i].mStatus == kGMPOutputDownscaled) { - return true; - } - } - return false; -} - -bool -CDMCaps::AutoLock::SetKeyStatus(const CencKeyId& aKeyId, - const nsString& aSessionId, - GMPMediaKeyStatus aStatus) -{ - mData.mMonitor.AssertCurrentThreadOwns(); - KeyStatus key(aKeyId, aSessionId, aStatus); - auto index = mData.mKeyStatuses.IndexOf(key); - - if (aStatus == kGMPUnknown) { - // Return true if the element is found to notify key changes. - return mData.mKeyStatuses.RemoveElement(key); - } - - if (index != mData.mKeyStatuses.NoIndex) { - if (mData.mKeyStatuses[index].mStatus == aStatus) { - return false; - } - auto oldStatus = mData.mKeyStatuses[index].mStatus; - mData.mKeyStatuses[index].mStatus = aStatus; - if (oldStatus == kGMPUsable || oldStatus == kGMPOutputDownscaled) { - return true; - } - } else { - mData.mKeyStatuses.AppendElement(key); - } - - // Both kGMPUsable and kGMPOutputDownscaled are treated able to decrypt. - // We don't need to notify when transition happens between kGMPUsable and - // kGMPOutputDownscaled. Only call NotifyUsable() when we are going from - // ![kGMPUsable|kGMPOutputDownscaled] to [kGMPUsable|kGMPOutputDownscaled] - if (aStatus != kGMPUsable && aStatus != kGMPOutputDownscaled) { - return true; - } - - auto& waiters = mData.mWaitForKeys; - size_t i = 0; - while (i < waiters.Length()) { - auto& w = waiters[i]; - if (w.mKeyId == aKeyId) { - w.mListener->NotifyUsable(aKeyId); - waiters.RemoveElementAt(i); - } else { - i++; - } - } - return true; -} - -void -CDMCaps::AutoLock::NotifyWhenKeyIdUsable(const CencKeyId& aKey, - SamplesWaitingForKey* aListener) -{ - mData.mMonitor.AssertCurrentThreadOwns(); - MOZ_ASSERT(!IsKeyUsable(aKey)); - MOZ_ASSERT(aListener); - mData.mWaitForKeys.AppendElement(WaitForKeys(aKey, aListener)); -} - -bool -CDMCaps::AutoLock::AreCapsKnown() -{ - mData.mMonitor.AssertCurrentThreadOwns(); - return mData.mCaps != 0; -} - -bool -CDMCaps::AutoLock::CanDecryptAndDecodeAudio() -{ - return mData.HasCap(GMP_EME_CAP_DECRYPT_AND_DECODE_AUDIO); -} - -bool -CDMCaps::AutoLock::CanDecryptAndDecodeVideo() -{ - return mData.HasCap(GMP_EME_CAP_DECRYPT_AND_DECODE_VIDEO); -} - -bool -CDMCaps::AutoLock::CanDecryptAudio() -{ - return mData.HasCap(GMP_EME_CAP_DECRYPT_AUDIO); -} - -bool -CDMCaps::AutoLock::CanDecryptVideo() -{ - return mData.HasCap(GMP_EME_CAP_DECRYPT_VIDEO); -} - -void -CDMCaps::AutoLock::GetKeyStatusesForSession(const nsAString& aSessionId, - nsTArray& aOutKeyStatuses) -{ - for (size_t i = 0; i < mData.mKeyStatuses.Length(); i++) { - const auto& key = mData.mKeyStatuses[i]; - if (key.mSessionId.Equals(aSessionId)) { - aOutKeyStatuses.AppendElement(key); - } - } -} - -void -CDMCaps::AutoLock::GetSessionIdsForKeyId(const CencKeyId& aKeyId, - nsTArray& aOutSessionIds) -{ - for (const auto& keyStatus : mData.mKeyStatuses) { - if (keyStatus.mId == aKeyId) { - aOutSessionIds.AppendElement(NS_ConvertUTF16toUTF8(keyStatus.mSessionId)); - } - } -} - -} // namespace mozilla diff --git a/dom/media/eme/CDMCaps.h b/dom/media/eme/CDMCaps.h deleted file mode 100644 index 89216e7906..0000000000 --- a/dom/media/eme/CDMCaps.h +++ /dev/null @@ -1,125 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef CDMCaps_h_ -#define CDMCaps_h_ - -#include "nsString.h" -#include "nsAutoPtr.h" -#include "mozilla/Monitor.h" -#include "nsIThread.h" -#include "nsTArray.h" -#include "mozilla/Attributes.h" -#include "SamplesWaitingForKey.h" -#include "gmp-decryption.h" - -namespace mozilla { - -// CDM capabilities; what keys a CDMProxy can use, and whether it can decrypt, or -// decrypt-and-decode on a per stream basis. Must be locked to access state. -class CDMCaps { -public: - CDMCaps(); - ~CDMCaps(); - - struct KeyStatus { - KeyStatus(const CencKeyId& aId, - const nsString& aSessionId, - GMPMediaKeyStatus aStatus) - : mId(aId) - , mSessionId(aSessionId) - , mStatus(aStatus) - {} - KeyStatus(const KeyStatus& aOther) - : mId(aOther.mId) - , mSessionId(aOther.mSessionId) - , mStatus(aOther.mStatus) - {} - bool operator==(const KeyStatus& aOther) const { - return mId == aOther.mId && - mSessionId == aOther.mSessionId; - }; - - CencKeyId mId; - nsString mSessionId; - GMPMediaKeyStatus mStatus; - }; - - // Locks the CDMCaps. It must be locked to access its shared state. - // Threadsafe when locked. - class MOZ_STACK_CLASS AutoLock { - public: - explicit AutoLock(CDMCaps& aKeyCaps); - ~AutoLock(); - - // Returns true if the capabilities of the CDM are known, i.e. they have - // been reported by the CDM to Goanna. - bool AreCapsKnown(); - - bool IsKeyUsable(const CencKeyId& aKeyId); - - // Returns true if key status changed, - // i.e. the key status changed from usable to expired. - bool SetKeyStatus(const CencKeyId& aKeyId, const nsString& aSessionId, GMPMediaKeyStatus aStatus); - - void GetKeyStatusesForSession(const nsAString& aSessionId, - nsTArray& aOutKeyStatuses); - - void GetSessionIdsForKeyId(const CencKeyId& aKeyId, - nsTArray& aOutSessionIds); - - // Sets the capabilities of the CDM. aCaps is the logical OR of the - // GMP_EME_CAP_* flags from gmp-decryption.h. - void SetCaps(uint64_t aCaps); - - bool CanDecryptAndDecodeAudio(); - bool CanDecryptAndDecodeVideo(); - - bool CanDecryptAudio(); - bool CanDecryptVideo(); - - void CallOnMainThreadWhenCapsAvailable(nsIRunnable* aContinuation); - - // Notifies the SamplesWaitingForKey when key become usable. - void NotifyWhenKeyIdUsable(const CencKeyId& aKey, - SamplesWaitingForKey* aSamplesWaiting); - private: - // Not taking a strong ref, since this should be allocated on the stack. - CDMCaps& mData; - }; - -private: - void Lock(); - void Unlock(); - bool HasCap(uint64_t); - - struct WaitForKeys { - WaitForKeys(const CencKeyId& aKeyId, - SamplesWaitingForKey* aListener) - : mKeyId(aKeyId) - , mListener(aListener) - {} - CencKeyId mKeyId; - nsRefPtr mListener; - }; - - Monitor mMonitor; - - nsTArray mKeyStatuses; - - nsTArray mWaitForKeys; - - nsTArray> mWaitForCaps; - uint64_t mCaps; - - // It is not safe to copy this object. - CDMCaps(const CDMCaps&) = delete; - CDMCaps& operator=(const CDMCaps&) = delete; -}; - -} // namespace mozilla - -#endif diff --git a/dom/media/eme/CDMProxy.cpp b/dom/media/eme/CDMProxy.cpp deleted file mode 100644 index ce6e7bb2bd..0000000000 --- a/dom/media/eme/CDMProxy.cpp +++ /dev/null @@ -1,615 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/CDMProxy.h" -#include "nsString.h" -#include "mozilla/dom/MediaKeys.h" -#include "mozilla/dom/MediaKeySession.h" -#include "mozIGoannaMediaPluginService.h" -#include "nsContentCID.h" -#include "nsServiceManagerUtils.h" -#include "MainThreadUtils.h" -#include "mozilla/EMEUtils.h" -#include "nsIConsoleService.h" -#include "prenv.h" -#include "mozilla/PodOperations.h" -#include "mozilla/CDMCallbackProxy.h" - -namespace mozilla { - -CDMProxy::CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem) - : mKeys(aKeys) - , mKeySystem(aKeySystem) - , mCDM(nullptr) - , mDecryptionJobCount(0) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_COUNT_CTOR(CDMProxy); -} - -CDMProxy::~CDMProxy() -{ - MOZ_COUNT_DTOR(CDMProxy); -} - -void -CDMProxy::Init(PromiseId aPromiseId, - const nsAString& aOrigin, - const nsAString& aTopLevelOrigin, - bool aInPrivateBrowsing) -{ - MOZ_ASSERT(NS_IsMainThread()); - NS_ENSURE_TRUE_VOID(!mKeys.IsNull()); - - EME_LOG("CDMProxy::Init (%s, %s) %s", - NS_ConvertUTF16toUTF8(aOrigin).get(), - NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(), - (aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing")); - - if (!mGMPThread) { - nsCOMPtr mps = - do_GetService("@mozilla.org/goanna-media-plugin-service;1"); - if (!mps) { - RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); - return; - } - mps->GetThread(getter_AddRefs(mGMPThread)); - if (!mGMPThread) { - RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); - return; - } - } - nsAutoPtr data(new InitData()); - data->mPromiseId = aPromiseId; - data->mOrigin = aOrigin; - data->mTopLevelOrigin = aTopLevelOrigin; - data->mInPrivateBrowsing = aInPrivateBrowsing; - nsRefPtr task( - NS_NewRunnableMethodWithArg>(this, - &CDMProxy::gmp_Init, - data)); - mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -#ifdef DEBUG -bool -CDMProxy::IsOnGMPThread() -{ - return NS_GetCurrentThread() == mGMPThread; -} -#endif - -void -CDMProxy::gmp_Init(nsAutoPtr aData) -{ - MOZ_ASSERT(IsOnGMPThread()); - - nsCOMPtr mps = - do_GetService("@mozilla.org/goanna-media-plugin-service;1"); - if (!mps) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); - return; - } - - nsCString version; - nsTArray tags; - tags.AppendElement(NS_ConvertUTF16toUTF8(mKeySystem)); - - nsresult rv = mps->GetNodeId(aData->mOrigin, - aData->mTopLevelOrigin, - aData->mInPrivateBrowsing, - mNodeId); - - MOZ_ASSERT(!GetNodeId().IsEmpty()); - if (NS_FAILED(rv)) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); - return; - } - - EME_LOG("CDMProxy::gmp_Init (%s, %s) %s NodeId=%s", - NS_ConvertUTF16toUTF8(aData->mOrigin).get(), - NS_ConvertUTF16toUTF8(aData->mTopLevelOrigin).get(), - (aData->mInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"), - GetNodeId().get()); - - rv = mps->GetGMPDecryptor(&tags, GetNodeId(), &mCDM); - if (NS_FAILED(rv) || !mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); - } else { - mCallback = new CDMCallbackProxy(this); - mCDM->Init(mCallback); - nsRefPtr task( - NS_NewRunnableMethodWithArg(this, - &CDMProxy::OnCDMCreated, - aData->mPromiseId)); - NS_DispatchToMainThread(task); - } -} - -void -CDMProxy::OnCDMCreated(uint32_t aPromiseId) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - MOZ_ASSERT(!GetNodeId().IsEmpty()); - if (mCDM) { - mKeys->OnCDMCreated(aPromiseId, GetNodeId(), mCDM->GetPluginId()); - } else { - // No CDM? Just reject the promise. - mKeys->RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); - } -} - -void -CDMProxy::CreateSession(uint32_t aCreateSessionToken, - dom::SessionType aSessionType, - PromiseId aPromiseId, - const nsAString& aInitDataType, - nsTArray& aInitData) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mGMPThread); - - nsAutoPtr data(new CreateSessionData()); - data->mSessionType = aSessionType; - data->mCreateSessionToken = aCreateSessionToken; - data->mPromiseId = aPromiseId; - data->mInitDataType = NS_ConvertUTF16toUTF8(aInitDataType); - data->mInitData = Move(aInitData); - - nsRefPtr task( - NS_NewRunnableMethodWithArg>(this, &CDMProxy::gmp_CreateSession, data)); - mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -GMPSessionType -ToGMPSessionType(dom::SessionType aSessionType) { - switch (aSessionType) { - case dom::SessionType::Temporary: return kGMPTemporySession; - case dom::SessionType::Persistent: return kGMPPersistentSession; - default: return kGMPTemporySession; - }; -}; - -void -CDMProxy::gmp_CreateSession(nsAutoPtr aData) -{ - MOZ_ASSERT(IsOnGMPThread()); - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); - return; - } - mCDM->CreateSession(aData->mCreateSessionToken, - aData->mPromiseId, - aData->mInitDataType, - aData->mInitData, - ToGMPSessionType(aData->mSessionType)); -} - -void -CDMProxy::LoadSession(PromiseId aPromiseId, - const nsAString& aSessionId) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mGMPThread); - - nsAutoPtr data(new SessionOpData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - nsRefPtr task( - NS_NewRunnableMethodWithArg>(this, &CDMProxy::gmp_LoadSession, data)); - mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -CDMProxy::gmp_LoadSession(nsAutoPtr aData) -{ - MOZ_ASSERT(IsOnGMPThread()); - - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); - return; - } - mCDM->LoadSession(aData->mPromiseId, aData->mSessionId); -} - -void -CDMProxy::SetServerCertificate(PromiseId aPromiseId, - nsTArray& aCert) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mGMPThread); - - nsAutoPtr data; - data->mPromiseId = aPromiseId; - data->mCert = Move(aCert); - nsRefPtr task( - NS_NewRunnableMethodWithArg>(this, &CDMProxy::gmp_SetServerCertificate, data)); - mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -CDMProxy::gmp_SetServerCertificate(nsAutoPtr aData) -{ - MOZ_ASSERT(IsOnGMPThread()); - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); - return; - } - mCDM->SetServerCertificate(aData->mPromiseId, aData->mCert); -} - -void -CDMProxy::UpdateSession(const nsAString& aSessionId, - PromiseId aPromiseId, - nsTArray& aResponse) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mGMPThread); - NS_ENSURE_TRUE_VOID(!mKeys.IsNull()); - - nsAutoPtr data(new UpdateSessionData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - data->mResponse = Move(aResponse); - nsRefPtr task( - NS_NewRunnableMethodWithArg>(this, &CDMProxy::gmp_UpdateSession, data)); - mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -CDMProxy::gmp_UpdateSession(nsAutoPtr aData) -{ - MOZ_ASSERT(IsOnGMPThread()); - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); - return; - } - mCDM->UpdateSession(aData->mPromiseId, - aData->mSessionId, - aData->mResponse); -} - -void -CDMProxy::CloseSession(const nsAString& aSessionId, - PromiseId aPromiseId) -{ - MOZ_ASSERT(NS_IsMainThread()); - NS_ENSURE_TRUE_VOID(!mKeys.IsNull()); - - nsAutoPtr data(new SessionOpData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - nsRefPtr task( - NS_NewRunnableMethodWithArg>(this, &CDMProxy::gmp_CloseSession, data)); - mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -CDMProxy::gmp_CloseSession(nsAutoPtr aData) -{ - MOZ_ASSERT(IsOnGMPThread()); - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); - return; - } - mCDM->CloseSession(aData->mPromiseId, aData->mSessionId); -} - -void -CDMProxy::RemoveSession(const nsAString& aSessionId, - PromiseId aPromiseId) -{ - MOZ_ASSERT(NS_IsMainThread()); - NS_ENSURE_TRUE_VOID(!mKeys.IsNull()); - - nsAutoPtr data(new SessionOpData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - nsRefPtr task( - NS_NewRunnableMethodWithArg>(this, &CDMProxy::gmp_RemoveSession, data)); - mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -CDMProxy::gmp_RemoveSession(nsAutoPtr aData) -{ - MOZ_ASSERT(IsOnGMPThread()); - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR); - return; - } - mCDM->RemoveSession(aData->mPromiseId, aData->mSessionId); -} - -void -CDMProxy::Shutdown() -{ - MOZ_ASSERT(NS_IsMainThread()); - mKeys.Clear(); - // Note: This may end up being the last owning reference to the CDMProxy. - nsRefPtr task(NS_NewRunnableMethod(this, &CDMProxy::gmp_Shutdown)); - if (mGMPThread) { - mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL); - } -} - -void -CDMProxy::gmp_Shutdown() -{ - MOZ_ASSERT(IsOnGMPThread()); - - // Abort any pending decrypt jobs, to awaken any clients waiting on a job. - for (size_t i = 0; i < mDecryptionJobs.Length(); i++) { - DecryptJob* job = mDecryptionJobs[i]; - job->mClient->Decrypted(GMPAbortedErr, nullptr); - } - mDecryptionJobs.Clear(); - - if (mCDM) { - mCDM->Close(); - mCDM = nullptr; - } -} - -void -CDMProxy::RejectPromise(PromiseId aId, nsresult aCode) -{ - if (NS_IsMainThread()) { - if (!mKeys.IsNull()) { - mKeys->RejectPromise(aId, aCode); - } - } else { - nsRefPtr task(new RejectPromiseTask(this, aId, aCode)); - NS_DispatchToMainThread(task); - } -} - -void -CDMProxy::ResolvePromise(PromiseId aId) -{ - if (NS_IsMainThread()) { - if (!mKeys.IsNull()) { - mKeys->ResolvePromise(aId); - } else { - NS_WARNING("CDMProxy unable to resolve promise!"); - } - } else { - nsRefPtr task; - task = NS_NewRunnableMethodWithArg(this, - &CDMProxy::ResolvePromise, - aId); - NS_DispatchToMainThread(task); - } -} - -const nsCString& -CDMProxy::GetNodeId() const -{ - return mNodeId; -} - -void -CDMProxy::OnSetSessionId(uint32_t aCreateSessionToken, - const nsAString& aSessionId) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - - nsRefPtr session(mKeys->GetPendingSession(aCreateSessionToken)); - if (session) { - session->SetSessionId(aSessionId); - } -} - -void -CDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - mKeys->OnSessionLoaded(aPromiseId, aSuccess); -} - -static dom::MediaKeyMessageType -ToMediaKeyMessageType(GMPSessionMessageType aMessageType) { - switch (aMessageType) { - case kGMPLicenseRequest: return dom::MediaKeyMessageType::License_request; - case kGMPLicenseRenewal: return dom::MediaKeyMessageType::License_renewal; - case kGMPLicenseRelease: return dom::MediaKeyMessageType::License_release; - case kGMPIndividualizationRequest: return dom::MediaKeyMessageType::Individualization_request; - default: return dom::MediaKeyMessageType::License_request; - }; -}; - -void -CDMProxy::OnSessionMessage(const nsAString& aSessionId, - GMPSessionMessageType aMessageType, - nsTArray& aMessage) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - nsRefPtr session(mKeys->GetSession(aSessionId)); - if (session) { - session->DispatchKeyMessage(ToMediaKeyMessageType(aMessageType), aMessage); - } -} - -void -CDMProxy::OnKeyStatusesChange(const nsAString& aSessionId) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - nsRefPtr session(mKeys->GetSession(aSessionId)); - if (session) { - session->DispatchKeyStatusesChange(); - } -} - -void -CDMProxy::OnExpirationChange(const nsAString& aSessionId, - GMPTimestamp aExpiryTime) -{ - MOZ_ASSERT(NS_IsMainThread()); - NS_WARNING("CDMProxy::OnExpirationChange() not implemented"); -} - -void -CDMProxy::OnSessionClosed(const nsAString& aSessionId) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - nsRefPtr session(mKeys->GetSession(aSessionId)); - if (session) { - session->OnClosed(); - } -} - -static void -LogToConsole(const nsAString& aMsg) -{ - nsCOMPtr console( - do_GetService("@mozilla.org/consoleservice;1")); - if (!console) { - NS_WARNING("Failed to log message to console."); - return; - } - nsAutoString msg(aMsg); - console->LogStringMessage(msg.get()); -} - -void -CDMProxy::OnSessionError(const nsAString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsAString& aMsg) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - nsRefPtr session(mKeys->GetSession(aSessionId)); - if (session) { - session->DispatchKeyError(aSystemCode); - } - LogToConsole(aMsg); -} - -void -CDMProxy::OnRejectPromise(uint32_t aPromiseId, - nsresult aDOMException, - const nsAString& aMsg) -{ - MOZ_ASSERT(NS_IsMainThread()); - RejectPromise(aPromiseId, aDOMException); - LogToConsole(aMsg); -} - -const nsString& -CDMProxy::KeySystem() const -{ - return mKeySystem; -} - -CDMCaps& -CDMProxy::Capabilites() { - return mCapabilites; -} - -void -CDMProxy::Decrypt(mp4_demuxer::MP4Sample* aSample, - DecryptionClient* aClient) -{ - nsAutoPtr job(new DecryptJob(aSample, aClient)); - nsRefPtr task( - NS_NewRunnableMethodWithArg>(this, &CDMProxy::gmp_Decrypt, job)); - mGMPThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -CDMProxy::gmp_Decrypt(nsAutoPtr aJob) -{ - MOZ_ASSERT(IsOnGMPThread()); - MOZ_ASSERT(aJob->mClient); - MOZ_ASSERT(aJob->mSample); - - if (!mCDM) { - aJob->mClient->Decrypted(GMPAbortedErr, nullptr); - return; - } - - aJob->mId = ++mDecryptionJobCount; - nsTArray data; - data.AppendElements(aJob->mSample->data, aJob->mSample->size); - mCDM->Decrypt(aJob->mId, aJob->mSample->crypto, data); - mDecryptionJobs.AppendElement(aJob.forget()); -} - -void -CDMProxy::gmp_Decrypted(uint32_t aId, - GMPErr aResult, - const nsTArray& aDecryptedData) -{ - MOZ_ASSERT(IsOnGMPThread()); - for (size_t i = 0; i < mDecryptionJobs.Length(); i++) { - DecryptJob* job = mDecryptionJobs[i]; - if (job->mId == aId) { - if (aDecryptedData.Length() != job->mSample->size) { - NS_WARNING("CDM returned incorrect number of decrypted bytes"); - } - if (GMP_SUCCEEDED(aResult)) { - PodCopy(job->mSample->data, - aDecryptedData.Elements(), - std::min(aDecryptedData.Length(), job->mSample->size)); - job->mClient->Decrypted(GMPNoErr, job->mSample.forget()); - } else if (aResult == GMPNoKeyErr) { - NS_WARNING("CDM returned GMPNoKeyErr"); - // We still have the encrypted sample, so we can re-enqueue it to be - // decrypted again once the key is usable again. - job->mClient->Decrypted(GMPNoKeyErr, job->mSample.forget()); - } else { - nsAutoCString str("CDM returned decode failure GMPErr="); - str.AppendInt(aResult); - NS_WARNING(str.get()); - job->mClient->Decrypted(aResult, nullptr); - } - mDecryptionJobs.RemoveElementAt(i); - return; - } - } - NS_WARNING("GMPDecryptorChild returned incorrect job ID"); -} - -void -CDMProxy::GetSessionIdsForKeyId(const nsTArray& aKeyId, - nsTArray& aSessionIds) -{ - CDMCaps::AutoLock caps(Capabilites()); - caps.GetSessionIdsForKeyId(aKeyId, aSessionIds); -} - -void -CDMProxy::Terminated() -{ - MOZ_ASSERT(NS_IsMainThread()); - NS_WARNING("CDM terminated"); - if (!mKeys.IsNull()) { - mKeys->Terminated(); - } -} - -} // namespace mozilla diff --git a/dom/media/eme/CDMProxy.h b/dom/media/eme/CDMProxy.h deleted file mode 100644 index 1bf3b504e7..0000000000 --- a/dom/media/eme/CDMProxy.h +++ /dev/null @@ -1,328 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef CDMProxy_h_ -#define CDMProxy_h_ - -#include "nsString.h" -#include "nsAutoPtr.h" -#include "mozilla/dom/MediaKeys.h" -#include "mozilla/Monitor.h" -#include "nsIThread.h" -#include "GMPDecryptorProxy.h" -#include "mozilla/CDMCaps.h" -#include "mp4_demuxer/DecoderData.h" - -namespace mozilla { - -class CDMCallbackProxy; - -namespace dom { -class MediaKeySession; -} - -class DecryptionClient { -public: - virtual ~DecryptionClient() {} - virtual void Decrypted(GMPErr aResult, - mp4_demuxer::MP4Sample* aSample) = 0; -}; - -// Proxies calls GMP/CDM, and proxies calls back. -// Note: Promises are passed in via a PromiseId, so that the ID can be -// passed via IPC to the CDM, which can then signal when to reject or -// resolve the promise using its PromiseId. -class CDMProxy { - typedef dom::PromiseId PromiseId; - typedef dom::SessionType SessionType; -public: - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMProxy) - - // Main thread only. - CDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem); - - // Main thread only. - // Loads the CDM corresponding to mKeySystem. - // Calls MediaKeys::OnCDMCreated() when the CDM is created. - void Init(PromiseId aPromiseId, - const nsAString& aOrigin, - const nsAString& aTopLevelOrigin, - bool aInPrivateBrowsing); - - // Main thread only. - // Uses the CDM to create a key session. - // Calls MediaKeys::OnSessionActivated() when session is created. - // Assumes ownership of (Move()s) aInitData's contents. - void CreateSession(uint32_t aCreateSessionToken, - dom::SessionType aSessionType, - PromiseId aPromiseId, - const nsAString& aInitDataType, - nsTArray& aInitData); - - // Main thread only. - // Uses the CDM to load a presistent session stored on disk. - // Calls MediaKeys::OnSessionActivated() when session is loaded. - void LoadSession(PromiseId aPromiseId, - const nsAString& aSessionId); - - // Main thread only. - // Sends a new certificate to the CDM. - // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has - // processed the request. - // Assumes ownership of (Move()s) aCert's contents. - void SetServerCertificate(PromiseId aPromiseId, - nsTArray& aCert); - - // Main thread only. - // Sends an update to the CDM. - // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has - // processed the request. - // Assumes ownership of (Move()s) aResponse's contents. - void UpdateSession(const nsAString& aSessionId, - PromiseId aPromiseId, - nsTArray& aResponse); - - // Main thread only. - // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has - // processed the request. - // If processing this operation results in the session actually closing, - // we also call MediaKeySession::OnClosed(), which in turn calls - // MediaKeys::OnSessionClosed(). - void CloseSession(const nsAString& aSessionId, - PromiseId aPromiseId); - - // Main thread only. - // Removes all data for a persisent session. - // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has - // processed the request. - void RemoveSession(const nsAString& aSessionId, - PromiseId aPromiseId); - - // Main thread only. - void Shutdown(); - - // Main thread only. - void Terminated(); - - // Threadsafe. - const nsCString& GetNodeId() const; - - // Main thread only. - void OnSetSessionId(uint32_t aCreateSessionToken, - const nsAString& aSessionId); - - // Main thread only. - void OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess); - - // Main thread only. - void OnSessionMessage(const nsAString& aSessionId, - GMPSessionMessageType aMessageType, - nsTArray& aMessage); - - // Main thread only. - void OnExpirationChange(const nsAString& aSessionId, - GMPTimestamp aExpiryTime); - - // Main thread only. - void OnSessionClosed(const nsAString& aSessionId); - - // Main thread only. - void OnSessionError(const nsAString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsAString& aMsg); - - // Main thread only. - void OnRejectPromise(uint32_t aPromiseId, - nsresult aDOMException, - const nsAString& aMsg); - - // Threadsafe. - void Decrypt(mp4_demuxer::MP4Sample* aSample, - DecryptionClient* aSink); - - // Reject promise with DOMException corresponding to aExceptionCode. - // Can be called from any thread. - void RejectPromise(PromiseId aId, nsresult aExceptionCode); - - // Resolves promise with "undefined". - // Can be called from any thread. - void ResolvePromise(PromiseId aId); - - // Threadsafe. - const nsString& KeySystem() const; - - // GMP thread only. - void gmp_Decrypted(uint32_t aId, - GMPErr aResult, - const nsTArray& aDecryptedData); - - CDMCaps& Capabilites(); - - // Main thread only. - void OnKeyStatusesChange(const nsAString& aSessionId); - - void GetSessionIdsForKeyId(const nsTArray& aKeyId, - nsTArray& aSessionIds); - -#ifdef DEBUG - bool IsOnGMPThread(); -#endif - -private: - - struct InitData { - uint32_t mPromiseId; - nsAutoString mOrigin; - nsAutoString mTopLevelOrigin; - bool mInPrivateBrowsing; - }; - - // GMP thread only. - void gmp_Init(nsAutoPtr aData); - - // GMP thread only. - void gmp_Shutdown(); - - // Main thread only. - void OnCDMCreated(uint32_t aPromiseId); - - struct CreateSessionData { - dom::SessionType mSessionType; - uint32_t mCreateSessionToken; - PromiseId mPromiseId; - nsAutoCString mInitDataType; - nsTArray mInitData; - }; - // GMP thread only. - void gmp_CreateSession(nsAutoPtr aData); - - struct SessionOpData { - PromiseId mPromiseId; - nsAutoCString mSessionId; - }; - // GMP thread only. - void gmp_LoadSession(nsAutoPtr aData); - - struct SetServerCertificateData { - PromiseId mPromiseId; - nsTArray mCert; - }; - // GMP thread only. - void gmp_SetServerCertificate(nsAutoPtr aData); - - struct UpdateSessionData { - PromiseId mPromiseId; - nsAutoCString mSessionId; - nsTArray mResponse; - }; - // GMP thread only. - void gmp_UpdateSession(nsAutoPtr aData); - - // GMP thread only. - void gmp_CloseSession(nsAutoPtr aData); - - // GMP thread only. - void gmp_RemoveSession(nsAutoPtr aData); - - struct DecryptJob { - DecryptJob(mp4_demuxer::MP4Sample* aSample, - DecryptionClient* aClient) - : mId(0) - , mSample(aSample) - , mClient(aClient) - {} - uint32_t mId; - nsAutoPtr mSample; - nsAutoPtr mClient; - }; - // GMP thread only. - void gmp_Decrypt(nsAutoPtr aJob); - - class RejectPromiseTask : public nsRunnable { - public: - RejectPromiseTask(CDMProxy* aProxy, - PromiseId aId, - nsresult aCode) - : mProxy(aProxy) - , mId(aId) - , mCode(aCode) - { - } - NS_METHOD Run() { - mProxy->RejectPromise(mId, mCode); - return NS_OK; - } - private: - nsRefPtr mProxy; - PromiseId mId; - nsresult mCode; - }; - - ~CDMProxy(); - - // Helper to enforce that a raw pointer is only accessed on the main thread. - template - class MainThreadOnlyRawPtr { - public: - explicit MainThreadOnlyRawPtr(Type* aPtr) - : mPtr(aPtr) - { - MOZ_ASSERT(NS_IsMainThread()); - } - - bool IsNull() const { - MOZ_ASSERT(NS_IsMainThread()); - return !mPtr; - } - - void Clear() { - MOZ_ASSERT(NS_IsMainThread()); - mPtr = nullptr; - } - - Type* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { - MOZ_ASSERT(NS_IsMainThread()); - return mPtr; - } - private: - Type* mPtr; - }; - - // Our reference back to the MediaKeys object. - // WARNING: This is a non-owning reference that is cleared by MediaKeys - // destructor. only use on main thread, and always nullcheck before using! - MainThreadOnlyRawPtr mKeys; - - const nsAutoString mKeySystem; - - // Goanna Media Plugin thread. All interactions with the out-of-process - // EME plugin must come from this thread. - nsRefPtr mGMPThread; - - nsCString mNodeId; - - GMPDecryptorProxy* mCDM; - CDMCaps mCapabilites; - nsAutoPtr mCallback; - - // Decryption jobs sent to CDM, awaiting result. - // GMP thread only. - nsTArray> mDecryptionJobs; - - // Number of buffers we've decrypted. Used to uniquely identify - // decryption jobs sent to CDM. Note we can't just use the length of - // mDecryptionJobs as that shrinks as jobs are completed and removed - // from it. - // GMP thread only. - uint32_t mDecryptionJobCount; -}; - - -} // namespace mozilla - -#endif // CDMProxy_h_ diff --git a/dom/media/eme/EMEUtils.cpp b/dom/media/eme/EMEUtils.cpp deleted file mode 100644 index 02bf0ad62a..0000000000 --- a/dom/media/eme/EMEUtils.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/EMEUtils.h" - -namespace mozilla { - -#ifdef PR_LOGGING - -PRLogModuleInfo* GetEMELog() { - static PRLogModuleInfo* log = nullptr; - if (!log) { - log = PR_NewLogModule("EME"); - } - return log; -} - -PRLogModuleInfo* GetEMEVerboseLog() { - static PRLogModuleInfo* log = nullptr; - if (!log) { - log = PR_NewLogModule("EMEV"); - } - return log; -} - -#endif - -static bool -ContainsOnlyDigits(const nsAString& aString) -{ - nsAString::const_iterator iter, end; - aString.BeginReading(iter); - aString.EndReading(end); - while (iter != end) { - char16_t ch = *iter; - if (ch < '0' || ch > '9') { - return false; - } - iter++; - } - return true; -} - -static bool -ParseKeySystem(const nsAString& aExpectedKeySystem, - const nsAString& aInputKeySystem, - int32_t& aOutCDMVersion) -{ - if (!StringBeginsWith(aInputKeySystem, aExpectedKeySystem)) { - return false; - } - - if (aInputKeySystem.Length() > aExpectedKeySystem.Length() + 8) { - // Allow up to 8 bytes for the ".version" field. 8 bytes should - // be enough for any versioning scheme... - NS_WARNING("Input KeySystem including was suspiciously long"); - return false; - } - - const char16_t* versionStart = aInputKeySystem.BeginReading() + aExpectedKeySystem.Length(); - const char16_t* end = aInputKeySystem.EndReading(); - if (versionStart == end) { - // No version supplied with keysystem. - aOutCDMVersion = NO_CDM_VERSION; - return true; - } - if (*versionStart != '.') { - // version not in correct format. - NS_WARNING("EME keySystem version string not prefixed by '.'"); - return false; - } - versionStart++; - const nsAutoString versionStr(Substring(versionStart, end)); - if (!ContainsOnlyDigits(versionStr)) { - NS_WARNING("Non-digit character in EME keySystem string's version suffix"); - return false; - } - nsresult rv; - int32_t version = versionStr.ToInteger(&rv); - if (NS_FAILED(rv) || version < 0) { - NS_WARNING("Invalid version in EME keySystem string"); - return false; - } - aOutCDMVersion = version; - - return true; -} - -static const char16_t* sKeySystems[] = { - MOZ_UTF16("org.w3.clearkey"), - MOZ_UTF16("com.adobe.access"), - MOZ_UTF16("com.adobe.primetime"), -}; - -bool -ParseKeySystem(const nsAString& aInputKeySystem, - nsAString& aOutKeySystem, - int32_t& aOutCDMVersion) -{ - for (const char16_t* keySystem : sKeySystems) { - int32_t minCDMVersion = NO_CDM_VERSION; - if (ParseKeySystem(nsDependentString(keySystem), - aInputKeySystem, - minCDMVersion)) { - aOutKeySystem = keySystem; - aOutCDMVersion = minCDMVersion; - return true; - } - } - return false; -} - -} // namespace mozilla diff --git a/dom/media/eme/EMEUtils.h b/dom/media/eme/EMEUtils.h deleted file mode 100644 index dd58053923..0000000000 --- a/dom/media/eme/EMEUtils.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef EME_LOG_H_ -#define EME_LOG_H_ - -#include "prlog.h" -#include "nsString.h" - -namespace mozilla { - -#ifdef PR_LOGGING - - #ifndef EME_LOG - PRLogModuleInfo* GetEMELog(); - #define EME_LOG(...) PR_LOG(GetEMELog(), PR_LOG_DEBUG, (__VA_ARGS__)) - #endif - - #ifndef EME_VERBOSE_LOG - PRLogModuleInfo* GetEMEVerboseLog(); - #define EME_VERBOSE_LOG(...) PR_LOG(GetEMEVerboseLog(), PR_LOG_DEBUG, (__VA_ARGS__)) - #else - #ifndef EME_LOG - #define EME_LOG(...) - #endif - - #ifndef EME_VERBOSE_LOG - #define EME_VERBOSE_LOG(...) - #endif - #endif - -#else - - #ifndef EME_LOG - #define EME_LOG(...) - #endif - - #ifndef EME_VERBOSE_LOG - #define EME_VERBOSE_LOG(...) - #endif - -#endif // PR_LOGGING - -#define NO_CDM_VERSION -1 - -// Checks a keySystem string against a whitelist, and determines whether -// the keySystem is in the whitelist, and extracts the requested minimum -// CDM version. -// -// Format of EME keysystems: -// com.domain.keysystem[.minVersionAsInt] -// i.e. org.w3.clearkey, com.adobe.primetime.7 -// -// Returns true if aKeySystem contains a valid keySystem which we support, -// false otherwise. -// -// On success, aOutKeySystem contains the keySystem string stripped of the -// min version number, and aOutMinCDMVersion contains the min version number -// if present. If it was not present, aOutMinCDMVersion is NO_CDM_VERSION. -bool ParseKeySystem(const nsAString& aKeySystem, - nsAString& aOutKeySystem, - int32_t& aOutMinCDMVersion); - -} // namespace mozilla - -#endif // EME_LOG_H_ diff --git a/dom/media/eme/MediaEncryptedEvent.cpp b/dom/media/eme/MediaEncryptedEvent.cpp deleted file mode 100644 index 03129444bb..0000000000 --- a/dom/media/eme/MediaEncryptedEvent.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "MediaEncryptedEvent.h" -#include "mozilla/dom/MediaEncryptedEventBinding.h" -#include "nsContentUtils.h" -#include "jsfriendapi.h" -#include "nsINode.h" -#include "mozilla/dom/MediaKeys.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_CLASS(MediaEncryptedEvent) - -NS_IMPL_ADDREF_INHERITED(MediaEncryptedEvent, Event) -NS_IMPL_RELEASE_INHERITED(MediaEncryptedEvent, Event) - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaEncryptedEvent, Event) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(MediaEncryptedEvent, Event) - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mInitData) -NS_IMPL_CYCLE_COLLECTION_TRACE_END - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaEncryptedEvent, Event) - tmp->mInitData = nullptr; -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaEncryptedEvent) -NS_INTERFACE_MAP_END_INHERITING(Event) - -MediaEncryptedEvent::MediaEncryptedEvent(EventTarget* aOwner) - : Event(aOwner, nullptr, nullptr) -{ - mozilla::HoldJSObjects(this); -} - -MediaEncryptedEvent::~MediaEncryptedEvent() -{ - mInitData = nullptr; - mozilla::DropJSObjects(this); -} - -JSObject* -MediaEncryptedEvent::WrapObjectInternal(JSContext* aCx) -{ - return MediaEncryptedEventBinding::Wrap(aCx, this); -} - -already_AddRefed -MediaEncryptedEvent::Constructor(EventTarget* aOwner) -{ - nsRefPtr e = new MediaEncryptedEvent(aOwner); - e->InitEvent(NS_LITERAL_STRING("encrypted"), false, false); - e->SetTrusted(true); - return e.forget(); -} - -already_AddRefed -MediaEncryptedEvent::Constructor(EventTarget* aOwner, - const nsAString& aInitDataType, - const nsTArray& aInitData) -{ - nsRefPtr e = new MediaEncryptedEvent(aOwner); - e->InitEvent(NS_LITERAL_STRING("encrypted"), false, false); - e->mInitDataType = aInitDataType; - e->mRawInitData = aInitData; - e->SetTrusted(true); - return e.forget(); -} - -already_AddRefed -MediaEncryptedEvent::Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyNeededEventInit& aEventInitDict, - ErrorResult& aRv) -{ - nsCOMPtr owner = do_QueryInterface(aGlobal.GetAsSupports()); - nsRefPtr e = new MediaEncryptedEvent(owner); - bool trusted = e->Init(owner); - e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable); - e->mInitDataType = aEventInitDict.mInitDataType; - if (!aEventInitDict.mInitData.IsNull()) { - const auto& a = aEventInitDict.mInitData.Value(); - a.ComputeLengthAndData(); - e->mInitData = ArrayBuffer::Create(aGlobal.Context(), - a.Length(), - a.Data()); - if (!e->mInitData) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return nullptr; - } - } - e->SetTrusted(trusted); - return e.forget(); -} - -void -MediaEncryptedEvent::GetInitDataType(nsString& aRetVal) const -{ - aRetVal = mInitDataType; -} - -void -MediaEncryptedEvent::GetInitData(JSContext* cx, - JS::MutableHandle aData, - ErrorResult& aRv) -{ - if (mRawInitData.Length()) { - mInitData = ArrayBuffer::Create(cx, - mRawInitData.Length(), - mRawInitData.Elements()); - if (!mInitData) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return; - } - mRawInitData.Clear(); - } - if (mInitData) { - JS::ExposeObjectToActiveJS(mInitData); - } - aData.set(mInitData); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaEncryptedEvent.h b/dom/media/eme/MediaEncryptedEvent.h deleted file mode 100644 index af8229e09a..0000000000 --- a/dom/media/eme/MediaEncryptedEvent.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_MediaKeyNeededEvent_h__ -#define mozilla_dom_MediaKeyNeededEvent_h__ - -#include "mozilla/dom/MediaEncryptedEventBinding.h" -#include "mozilla/Attributes.h" -#include "mozilla/ErrorResult.h" -#include "nsCycleCollectionParticipant.h" -#include "nsWrapperCache.h" -#include "nsCOMPtr.h" -#include "mozilla/dom/Event.h" -#include "mozilla/dom/TypedArray.h" -#include "mozilla/Attributes.h" -#include "mozilla/dom/BindingUtils.h" -#include "js/TypeDecls.h" - -namespace mozilla { -namespace dom { - -class MediaEncryptedEvent final : public Event -{ -public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(MediaEncryptedEvent, Event) -protected: - virtual ~MediaEncryptedEvent(); - explicit MediaEncryptedEvent(EventTarget* aOwner); - - nsString mInitDataType; - JS::Heap mInitData; - -public: - - virtual JSObject* WrapObjectInternal(JSContext* aCx) override; - - static already_AddRefed - Constructor(EventTarget* aOwner); - - static already_AddRefed - Constructor(EventTarget* aOwner, - const nsAString& aInitDataType, - const nsTArray& aInitData); - - static already_AddRefed - Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyNeededEventInit& aEventInitDict, - ErrorResult& aRv); - - void GetInitDataType(nsString& aRetVal) const; - - void GetInitData(JSContext* cx, - JS::MutableHandle aData, - ErrorResult& aRv); -private: - nsTArray mRawInitData; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_MediaKeyNeededEvent_h__ diff --git a/dom/media/eme/MediaKeyError.cpp b/dom/media/eme/MediaKeyError.cpp deleted file mode 100644 index e39ebb55e5..0000000000 --- a/dom/media/eme/MediaKeyError.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "MediaKeyError.h" -#include "mozilla/dom/MediaKeyErrorBinding.h" -#include "nsContentUtils.h" - -namespace mozilla { -namespace dom { - -MediaKeyError::MediaKeyError(EventTarget* aOwner, uint32_t aSystemCode) - : Event(aOwner, nullptr, nullptr) - , mSystemCode(aSystemCode) -{ - InitEvent(NS_LITERAL_STRING("error"), false, false); -} - -MediaKeyError::~MediaKeyError() -{ -} - -uint32_t -MediaKeyError::SystemCode() const -{ - return mSystemCode; -} - -JSObject* -MediaKeyError::WrapObjectInternal(JSContext* aCx) -{ - return MediaKeyErrorBinding::Wrap(aCx, this); -} - - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeyError.h b/dom/media/eme/MediaKeyError.h deleted file mode 100644 index dd86a4ce8f..0000000000 --- a/dom/media/eme/MediaKeyError.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_MediaKeyError_h -#define mozilla_dom_MediaKeyError_h - -#include "mozilla/Attributes.h" -#include "mozilla/ErrorResult.h" -#include "nsWrapperCache.h" -#include "mozilla/dom/Event.h" -#include "js/TypeDecls.h" - -namespace mozilla { -namespace dom { - -class MediaKeyError final : public Event -{ -public: - NS_FORWARD_TO_EVENT - - MediaKeyError(EventTarget* aOwner, uint32_t aSystemCode); - ~MediaKeyError(); - - virtual JSObject* WrapObjectInternal(JSContext* aCx) override; - - uint32_t SystemCode() const; - -private: - uint32_t mSystemCode; -}; - -} // namespace dom -} // namespace mozilla - -#endif diff --git a/dom/media/eme/MediaKeyMessageEvent.cpp b/dom/media/eme/MediaKeyMessageEvent.cpp deleted file mode 100644 index ba58620c82..0000000000 --- a/dom/media/eme/MediaKeyMessageEvent.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/MediaKeyMessageEvent.h" -#include "mozilla/dom/MediaKeyMessageEventBinding.h" -#include "js/GCAPI.h" -#include "jsfriendapi.h" -#include "mozilla/dom/Nullable.h" -#include "mozilla/dom/PrimitiveConversions.h" -#include "mozilla/HoldDropJSObjects.h" -#include "mozilla/dom/TypedArray.h" -#include "nsContentUtils.h" -#include "mozilla/dom/MediaKeys.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_CLASS(MediaKeyMessageEvent) - -NS_IMPL_ADDREF_INHERITED(MediaKeyMessageEvent, Event) -NS_IMPL_RELEASE_INHERITED(MediaKeyMessageEvent, Event) - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaKeyMessageEvent, Event) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(MediaKeyMessageEvent, Event) - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mMessage) -NS_IMPL_CYCLE_COLLECTION_TRACE_END - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaKeyMessageEvent, Event) - tmp->mMessage = nullptr; -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaKeyMessageEvent) -NS_INTERFACE_MAP_END_INHERITING(Event) - -MediaKeyMessageEvent::MediaKeyMessageEvent(EventTarget* aOwner) - : Event(aOwner, nullptr, nullptr) -{ - mozilla::HoldJSObjects(this); -} - -MediaKeyMessageEvent::~MediaKeyMessageEvent() -{ - mMessage = nullptr; - mozilla::DropJSObjects(this); -} - -MediaKeyMessageEvent* -MediaKeyMessageEvent::AsMediaKeyMessageEvent() -{ - return this; -} - -JSObject* -MediaKeyMessageEvent::WrapObjectInternal(JSContext* aCx) -{ - return MediaKeyMessageEventBinding::Wrap(aCx, this); -} - -already_AddRefed -MediaKeyMessageEvent::Constructor(EventTarget* aOwner, - MediaKeyMessageType aMessageType, - const nsTArray& aMessage) -{ - nsRefPtr e = new MediaKeyMessageEvent(aOwner); - e->InitEvent(NS_LITERAL_STRING("message"), false, false); - e->mMessageType = aMessageType; - e->mRawMessage = aMessage; - e->SetTrusted(true); - return e.forget(); -} - -already_AddRefed -MediaKeyMessageEvent::Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyMessageEventInit& aEventInitDict, - ErrorResult& aRv) -{ - nsCOMPtr owner = do_QueryInterface(aGlobal.GetAsSupports()); - nsRefPtr e = new MediaKeyMessageEvent(owner); - bool trusted = e->Init(owner); - e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable); - const uint8_t* data = nullptr; - size_t length = 0; - if (aEventInitDict.mMessage.WasPassed()) { - const auto& a = aEventInitDict.mMessage.Value(); - a.ComputeLengthAndData(); - data = a.Data(); - length = a.Length(); - } - e->mMessage = ArrayBuffer::Create(aGlobal.Context(), length, data); - if (!e->mMessage) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return nullptr; - } - e->mMessageType = aEventInitDict.mMessageType; - e->SetTrusted(trusted); - return e.forget(); -} - -void -MediaKeyMessageEvent::GetMessage(JSContext* cx, - JS::MutableHandle aMessage, - ErrorResult& aRv) -{ - if (!mMessage) { - mMessage = ArrayBuffer::Create(cx, - mRawMessage.Length(), - mRawMessage.Elements()); - if (!mMessage) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return; - } - mRawMessage.Clear(); - } - JS::ExposeObjectToActiveJS(mMessage); - aMessage.set(mMessage); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeyMessageEvent.h b/dom/media/eme/MediaKeyMessageEvent.h deleted file mode 100644 index 2dacc6c514..0000000000 --- a/dom/media/eme/MediaKeyMessageEvent.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_MediaKeyMessageEvent_h__ -#define mozilla_dom_MediaKeyMessageEvent_h__ - -#include "mozilla/Attributes.h" -#include "mozilla/ErrorResult.h" -#include "nsCycleCollectionParticipant.h" -#include "nsWrapperCache.h" -#include "nsCOMPtr.h" -#include "mozilla/dom/Event.h" -#include "mozilla/dom/TypedArray.h" -#include "js/TypeDecls.h" -#include "mozilla/dom/MediaKeyMessageEventBinding.h" - -namespace mozilla { -namespace dom { - -struct MediaKeyMessageEventInit; - -class MediaKeyMessageEvent final : public Event -{ -public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(MediaKeyMessageEvent, Event) -protected: - virtual ~MediaKeyMessageEvent(); - explicit MediaKeyMessageEvent(EventTarget* aOwner); - - MediaKeyMessageType mMessageType; - JS::Heap mMessage; - -public: - virtual MediaKeyMessageEvent* AsMediaKeyMessageEvent(); - - virtual JSObject* WrapObjectInternal(JSContext* aCx) override; - - static already_AddRefed - Constructor(EventTarget* aOwner, - MediaKeyMessageType aMessageType, - const nsTArray& aMessage); - - static already_AddRefed - Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyMessageEventInit& aEventInitDict, - ErrorResult& aRv); - - MediaKeyMessageType MessageType() const { return mMessageType; } - - void GetMessage(JSContext* cx, - JS::MutableHandle aMessage, - ErrorResult& aRv); - -private: - nsTArray mRawMessage; -}; - - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_MediaKeyMessageEvent_h__ diff --git a/dom/media/eme/MediaKeySession.cpp b/dom/media/eme/MediaKeySession.cpp deleted file mode 100644 index 1c4ef21573..0000000000 --- a/dom/media/eme/MediaKeySession.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/HTMLMediaElement.h" -#include "mozilla/dom/MediaKeySession.h" -#include "mozilla/dom/MediaKeyError.h" -#include "mozilla/dom/MediaKeyMessageEvent.h" -#include "mozilla/dom/MediaEncryptedEvent.h" -#include "mozilla/dom/MediaKeyStatusMap.h" -#include "nsCycleCollectionParticipant.h" -#include "mozilla/CDMProxy.h" -#include "mozilla/AsyncEventDispatcher.h" -#include "mozilla/Move.h" -#include "nsContentUtils.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaKeySession, - DOMEventTargetHelper, - mMediaKeyError, - mKeys, - mKeyStatusMap, - mClosed) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaKeySession) -NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) - -NS_IMPL_ADDREF_INHERITED(MediaKeySession, DOMEventTargetHelper) -NS_IMPL_RELEASE_INHERITED(MediaKeySession, DOMEventTargetHelper) - -// Count of number of instances. Used to give each instance a -// unique token. -static uint32_t sMediaKeySessionNum = 0; - -MediaKeySession::MediaKeySession(JSContext* aCx, - nsPIDOMWindow* aParent, - MediaKeys* aKeys, - const nsAString& aKeySystem, - SessionType aSessionType, - ErrorResult& aRv) - : DOMEventTargetHelper(aParent) - , mKeys(aKeys) - , mKeySystem(aKeySystem) - , mSessionType(aSessionType) - , mToken(sMediaKeySessionNum++) - , mIsClosed(false) - , mUninitialized(true) - , mKeyStatusMap(new MediaKeyStatusMap(aCx, aParent, aRv)) -{ - MOZ_ASSERT(aParent); - if (aRv.Failed()) { - return; - } - mClosed = mKeys->MakePromise(aRv); -} - -void MediaKeySession::SetSessionId(const nsAString& aSessionId) -{ - if (NS_WARN_IF(!mSessionId.IsEmpty())) { - return; - } - mSessionId = aSessionId; - mKeys->OnSessionIdReady(this); -} - -MediaKeySession::~MediaKeySession() -{ -} - -MediaKeyError* -MediaKeySession::GetError() const -{ - return mMediaKeyError; -} - -void -MediaKeySession::GetKeySystem(nsString& aKeySystem) const -{ - aKeySystem = mKeySystem; -} - -void -MediaKeySession::GetSessionId(nsString& aSessionId) const -{ - aSessionId = GetSessionId(); -} - -const nsString& -MediaKeySession::GetSessionId() const -{ - return mSessionId; -} - -JSObject* -MediaKeySession::WrapObject(JSContext* aCx) -{ - return MediaKeySessionBinding::Wrap(aCx, this); -} - -double -MediaKeySession::Expiration() const -{ - return JS::GenericNaN(); -} - -Promise* -MediaKeySession::Closed() const -{ - return mClosed; -} - - -void -MediaKeySession::UpdateKeyStatusMap() -{ - MOZ_ASSERT(!IsClosed()); - if (!mKeys->GetCDMProxy()) { - return; - } - - nsTArray keyStatuses; - { - CDMCaps::AutoLock caps(mKeys->GetCDMProxy()->Capabilites()); - caps.GetKeyStatusesForSession(mSessionId, keyStatuses); - } - - mKeyStatusMap->Update(keyStatuses); -} - -MediaKeyStatusMap* -MediaKeySession::KeyStatuses() const -{ - return mKeyStatusMap; -} - -already_AddRefed -MediaKeySession::GenerateRequest(const nsAString& aInitDataType, - const ArrayBufferViewOrArrayBuffer& aInitData, - ErrorResult& aRv) -{ - nsRefPtr promise(mKeys->MakePromise(aRv)); - if (aRv.Failed()) { - return nullptr; - } - - if (!mUninitialized) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); - return promise.forget(); - } - - mUninitialized = false; - - nsTArray data; - if (aInitDataType.IsEmpty() || - !CopyArrayBufferViewOrArrayBufferData(aInitData, data)) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); - return promise.forget(); - } - - PromiseId pid = mKeys->StorePromise(promise); - mKeys->GetCDMProxy()->CreateSession(Token(), - mSessionType, - pid, - aInitDataType, data); - - return promise.forget(); -} - -already_AddRefed -MediaKeySession::Load(const nsAString& aSessionId, ErrorResult& aRv) -{ - nsRefPtr promise(mKeys->MakePromise(aRv)); - if (aRv.Failed()) { - return nullptr; - } - - if (aSessionId.IsEmpty()) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); - // "The sessionId parameter is empty." - return promise.forget(); - } - - if (!mUninitialized) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); - return promise.forget(); - } - - mUninitialized = false; - - // We now know the sessionId being loaded into this session. Remove the - // session from its owning MediaKey's set of sessions awaiting a sessionId. - nsRefPtr session(mKeys->GetPendingSession(Token())); - MOZ_ASSERT(session == this, "Session should be awaiting id on its own token"); - - // Associate with the known sessionId. - SetSessionId(aSessionId); - - mKeys->GetCDMProxy()->LoadSession(mKeys->StorePromise(promise), aSessionId); - - return promise.forget(); -} - -already_AddRefed -MediaKeySession::Update(const ArrayBufferViewOrArrayBuffer& aResponse, ErrorResult& aRv) -{ - nsRefPtr promise(mKeys->MakePromise(aRv)); - if (aRv.Failed()) { - return nullptr; - } - nsTArray data; - if (IsClosed() || - !mKeys->GetCDMProxy() || - !CopyArrayBufferViewOrArrayBufferData(aResponse, data)) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); - return promise.forget(); - } - mKeys->GetCDMProxy()->UpdateSession(mSessionId, - mKeys->StorePromise(promise), - data); - return promise.forget(); -} - -already_AddRefed -MediaKeySession::Close(ErrorResult& aRv) -{ - nsRefPtr promise(mKeys->MakePromise(aRv)); - if (aRv.Failed()) { - return nullptr; - } - if (IsClosed() || !mKeys->GetCDMProxy()) { - promise->MaybeResolve(JS::UndefinedHandleValue); - return promise.forget(); - } - mKeys->GetCDMProxy()->CloseSession(mSessionId, mKeys->StorePromise(promise)); - - return promise.forget(); -} - -void -MediaKeySession::OnClosed() -{ - if (IsClosed()) { - return; - } - mIsClosed = true; - mKeys->OnSessionClosed(this); - mKeys = nullptr; - mClosed->MaybeResolve(JS::UndefinedHandleValue); -} - -bool -MediaKeySession::IsClosed() const -{ - return mIsClosed; -} - -already_AddRefed -MediaKeySession::Remove(ErrorResult& aRv) -{ - nsRefPtr promise(mKeys->MakePromise(aRv)); - if (aRv.Failed()) { - return nullptr; - } - if (mSessionType != SessionType::Persistent) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); - // "The operation is not supported on session type sessions." - return promise.forget(); - } - if (IsClosed() || !mKeys->GetCDMProxy()) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - // "The session is closed." - return promise.forget(); - } - mKeys->GetCDMProxy()->RemoveSession(mSessionId, mKeys->StorePromise(promise)); - return promise.forget(); -} - -void -MediaKeySession::DispatchKeyMessage(MediaKeyMessageType aMessageType, - const nsTArray& aMessage) -{ - nsRefPtr event( - MediaKeyMessageEvent::Constructor(this, aMessageType, aMessage)); - nsRefPtr asyncDispatcher = - new AsyncEventDispatcher(this, event); - asyncDispatcher->PostDOMEvent(); -} - -void -MediaKeySession::DispatchKeyError(uint32_t aSystemCode) -{ - RefPtr event(new MediaKeyError(this, aSystemCode)); - nsRefPtr asyncDispatcher = - new AsyncEventDispatcher(this, event); - asyncDispatcher->PostDOMEvent(); -} - -void -MediaKeySession::DispatchKeyStatusesChange() -{ - if (IsClosed()) { - return; - } - - UpdateKeyStatusMap(); - - nsRefPtr asyncDispatcher = - new AsyncEventDispatcher(this, NS_LITERAL_STRING("keystatuseschange"), false); - asyncDispatcher->PostDOMEvent(); -} - -uint32_t -MediaKeySession::Token() const -{ - return mToken; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeySession.h b/dom/media/eme/MediaKeySession.h deleted file mode 100644 index 14dcd4bb0d..0000000000 --- a/dom/media/eme/MediaKeySession.h +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_MediaKeySession_h -#define mozilla_dom_MediaKeySession_h - -#include "mozilla/Attributes.h" -#include "mozilla/ErrorResult.h" -#include "nsCycleCollectionParticipant.h" -#include "mozilla/DOMEventTargetHelper.h" -#include "nsCOMPtr.h" -#include "mozilla/dom/TypedArray.h" -#include "mozilla/Mutex.h" -#include "mozilla/dom/Date.h" -#include "mozilla/dom/Promise.h" -#include "mozilla/dom/MediaKeySessionBinding.h" -#include "mozilla/dom/MediaKeysBinding.h" -#include "mozilla/dom/MediaKeyMessageEventBinding.h" - -struct JSContext; - -namespace mozilla { - -class CDMProxy; - -namespace dom { - -class ArrayBufferViewOrArrayBuffer; -class MediaKeyError; -class MediaKeyStatusMap; - -class MediaKeySession final : public DOMEventTargetHelper -{ -public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaKeySession, - DOMEventTargetHelper) -public: - MediaKeySession(JSContext* aCx, - nsPIDOMWindow* aParent, - MediaKeys* aKeys, - const nsAString& aKeySystem, - SessionType aSessionType, - ErrorResult& aRv); - - void SetSessionId(const nsAString& aSessionId); - - virtual JSObject* WrapObject(JSContext* aCx) override; - - // Mark this as resultNotAddRefed to return raw pointers - MediaKeyError* GetError() const; - - MediaKeyStatusMap* KeyStatuses() const; - - void GetKeySystem(nsString& aRetval) const; - - void GetSessionId(nsString& aRetval) const; - - const nsString& GetSessionId() const; - - // Number of ms since epoch at which expiration occurs, or NaN if unknown. - // TODO: The type of this attribute is still under contention. - // https://www.w3.org/Bugs/Public/show_bug.cgi?id=25902 - double Expiration() const; - - Promise* Closed() const; - - already_AddRefed GenerateRequest(const nsAString& aInitDataType, - const ArrayBufferViewOrArrayBuffer& aInitData, - ErrorResult& aRv); - - already_AddRefed Load(const nsAString& aSessionId, - ErrorResult& aRv); - - already_AddRefed Update(const ArrayBufferViewOrArrayBuffer& response, - ErrorResult& aRv); - - already_AddRefed Close(ErrorResult& aRv); - - already_AddRefed Remove(ErrorResult& aRv); - - void DispatchKeyMessage(MediaKeyMessageType aMessageType, - const nsTArray& aMessage); - - void DispatchKeyError(uint32_t system_code); - - void DispatchKeyStatusesChange(); - - void OnClosed(); - - bool IsClosed() const; - - // Process-unique identifier. - uint32_t Token() const; - -private: - ~MediaKeySession(); - - void UpdateKeyStatusMap(); - - nsRefPtr mClosed; - - nsRefPtr mMediaKeyError; - nsRefPtr mKeys; - const nsString mKeySystem; - nsString mSessionId; - const SessionType mSessionType; - const uint32_t mToken; - bool mIsClosed; - bool mUninitialized; - nsRefPtr mKeyStatusMap; -}; - -} // namespace dom -} // namespace mozilla - -#endif diff --git a/dom/media/eme/MediaKeyStatusMap.cpp b/dom/media/eme/MediaKeyStatusMap.cpp deleted file mode 100644 index cecebe73b7..0000000000 --- a/dom/media/eme/MediaKeyStatusMap.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/MediaKeyStatusMap.h" -#include "nsPIDOMWindow.h" -#include "mozilla/dom/UnionTypes.h" -#include "mozilla/dom/ToJSValue.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaKeyStatusMap) -NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaKeyStatusMap) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaKeyStatusMap) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -NS_IMPL_CYCLE_COLLECTION_CLASS(MediaKeyStatusMap) - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MediaKeyStatusMap) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent) - NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER - tmp->mMap = nullptr; -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(MediaKeyStatusMap) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(MediaKeyStatusMap) - NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mMap) -NS_IMPL_CYCLE_COLLECTION_TRACE_END - -MediaKeyStatusMap::MediaKeyStatusMap(JSContext* aCx, - nsPIDOMWindow* aParent, - ErrorResult& aRv) - : mParent(aParent) - , mUpdateError(NS_OK) -{ - mMap = JS::NewMapObject(aCx); - if (NS_WARN_IF(!mMap)) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - } - - mozilla::HoldJSObjects(this); -} - -MediaKeyStatusMap::~MediaKeyStatusMap() -{ - mozilla::DropJSObjects(this); -} - -JSObject* -MediaKeyStatusMap::WrapObject(JSContext* aCx) -{ - return MediaKeyStatusMapBinding::Wrap(aCx, this); -} - -nsPIDOMWindow* -MediaKeyStatusMap::GetParentObject() const -{ - return mParent; -} - -MediaKeyStatus -MediaKeyStatusMap::Get(JSContext* aCx, - const ArrayBufferViewOrArrayBuffer& aKey, - ErrorResult& aRv) const -{ - if (NS_FAILED(mUpdateError)) { - aRv.Throw(mUpdateError); - return MediaKeyStatus::Internal_error; - } - - JS::Rooted map(aCx, mMap); - JS::Rooted key(aCx); - JS::Rooted val(aCx); - - if (!aKey.ToJSVal(aCx, map, &key) || - !JS::MapGet(aCx, map, key, &val)) { - aRv.Throw(NS_ERROR_FAILURE); - return MediaKeyStatus::Internal_error; - } - - bool ok; - int index = FindEnumStringIndex( - aCx, val, MediaKeyStatusValues::strings, - "MediaKeyStatus", "Invalid MediaKeyStatus value", &ok); - - return ok ? static_cast(index) : - MediaKeyStatus::Internal_error; -} - -bool -MediaKeyStatusMap::Has(JSContext* aCx, - const ArrayBufferViewOrArrayBuffer& aKey, - ErrorResult& aRv) const -{ - if (NS_FAILED(mUpdateError)) { - aRv.Throw(mUpdateError); - return false; - } - - JS::Rooted map(aCx, mMap); - JS::Rooted key(aCx); - bool result = false; - - if (!aKey.ToJSVal(aCx, map, &key) || - !JS::MapHas(aCx, map, key, &result)) { - aRv.Throw(NS_ERROR_FAILURE); - } - - return result; -} - -template -static void CallMapMethod(JSContext* aCx, - const JS::Heap& aMap, - JS::MutableHandle aResult, - ErrorResult& aRv, - nsresult aUpdateError) -{ - if (NS_FAILED(aUpdateError)) { - aRv.Throw(aUpdateError); - return; - } - - JS::Rooted map(aCx, aMap); - JS::Rooted result(aCx); - if (!Method(aCx, map, &result)) { - aRv.Throw(NS_ERROR_FAILURE); - return; - } - - aResult.set(&result.toObject()); -} - -void -MediaKeyStatusMap::Keys(JSContext* aCx, - JS::MutableHandle aResult, - ErrorResult& aRv) const -{ - CallMapMethod(aCx, mMap, aResult, aRv, mUpdateError); -} - -void -MediaKeyStatusMap::Values(JSContext* aCx, - JS::MutableHandle aResult, - ErrorResult& aRv) const -{ - CallMapMethod(aCx, mMap, aResult, aRv, mUpdateError); -} -void -MediaKeyStatusMap::Entries(JSContext* aCx, - JS::MutableHandle aResult, - ErrorResult& aRv) const -{ - CallMapMethod(aCx, mMap, aResult, aRv, mUpdateError); -} - -uint32_t -MediaKeyStatusMap::GetSize(JSContext* aCx, ErrorResult& aRv) const -{ - if (NS_FAILED(mUpdateError)) { - aRv.Throw(mUpdateError); - return 0; - } - JS::Rooted map(aCx, mMap); - return JS::MapSize(aCx, map); -} - -static MediaKeyStatus -ToMediaKeyStatus(GMPMediaKeyStatus aStatus) { - switch (aStatus) { - case kGMPUsable: return MediaKeyStatus::Usable; - case kGMPExpired: return MediaKeyStatus::Expired; - case kGMPOutputDownscaled: return MediaKeyStatus::Output_downscaled; - case kGMPOutputNotAllowed: return MediaKeyStatus::Output_not_allowed; - case kGMPInternalError: return MediaKeyStatus::Internal_error; - default: return MediaKeyStatus::Internal_error; - } -} - -static bool -ToJSString(JSContext* aCx, GMPMediaKeyStatus aStatus, - JS::MutableHandle aResult) -{ - auto val = uint32_t(ToMediaKeyStatus(aStatus)); - MOZ_ASSERT(val < ArrayLength(MediaKeyStatusValues::strings)); - JSString* str = JS_NewStringCopyN(aCx, - MediaKeyStatusValues::strings[val].value, - MediaKeyStatusValues::strings[val].length); - if (!str) { - return false; - } - aResult.setString(str); - return true; -} - -nsresult -MediaKeyStatusMap::UpdateInternal(const nsTArray& keys) -{ - AutoJSAPI jsapi; - if (NS_WARN_IF(!jsapi.Init(mParent))) { - return NS_ERROR_FAILURE; - } - - jsapi.TakeOwnershipOfErrorReporting(); - JSContext* cx = jsapi.cx(); - JS::Rooted map(cx, mMap); - if (!JS::MapClear(cx, map)) { - return NS_ERROR_FAILURE; - } - - for (size_t i = 0; i < keys.Length(); i++) { - const auto& ks = keys[i]; - JS::Rooted key(cx); - JS::Rooted val(cx); - if (!ToJSValue(cx, TypedArrayCreator(ks.mId), &key) || - !ToJSString(cx, ks.mStatus, &val) || - !JS::MapSet(cx, map, key, val)) { - return NS_ERROR_OUT_OF_MEMORY; - } - } - - return NS_OK; -} - -void -MediaKeyStatusMap::Update(const nsTArray& keys) -{ - // Since we can't leave the map in a partial update state, we need - // to remember the error and throw it next time the interface methods - // are called. - mUpdateError = UpdateInternal(keys); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeyStatusMap.h b/dom/media/eme/MediaKeyStatusMap.h deleted file mode 100644 index 8fc3f590e4..0000000000 --- a/dom/media/eme/MediaKeyStatusMap.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_MediaKeyStatuses_h -#define mozilla_dom_MediaKeyStatuses_h - -#include "mozilla/ErrorResult.h" -#include "mozilla/Attributes.h" -#include "nsCycleCollectionParticipant.h" -#include "nsWrapperCache.h" - -#include "mozilla/dom/TypedArray.h" -#include "mozilla/dom/MediaKeyStatusMapBinding.h" -#include "mozilla/CDMCaps.h" - -class nsPIDOMWindow; - -namespace mozilla { -namespace dom { - -class ArrayBufferViewOrArrayBuffer; - -class MediaKeyStatusMap final : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaKeyStatusMap) - -public: - explicit MediaKeyStatusMap(JSContext* aCx, - nsPIDOMWindow* aParent, - ErrorResult& aRv); - -protected: - ~MediaKeyStatusMap(); - -public: - nsPIDOMWindow* GetParentObject() const; - - virtual JSObject* WrapObject(JSContext* aCx) override; - - MediaKeyStatus Get(JSContext* aCx, - const ArrayBufferViewOrArrayBuffer& aKey, - ErrorResult& aRv) const; - - bool Has(JSContext* aCx, - const ArrayBufferViewOrArrayBuffer& aKey, - ErrorResult& aRv) const; - - void Keys(JSContext* aCx, - JS::MutableHandle aResult, - ErrorResult& aRv) const; - - void Values(JSContext* aCx, - JS::MutableHandle aResult, - ErrorResult& aRv) const; - - void Entries(JSContext* aCx, - JS::MutableHandle aResult, - ErrorResult& aRv) const; - - uint32_t GetSize(JSContext* aCx, ErrorResult& aRv) const; - - void Update(const nsTArray& keys); - -private: - nsresult UpdateInternal(const nsTArray& keys); - - nsCOMPtr mParent; - JS::Heap mMap; - nsresult mUpdateError; -}; - -} // namespace dom -} // namespace mozilla - -#endif diff --git a/dom/media/eme/MediaKeySystemAccess.cpp b/dom/media/eme/MediaKeySystemAccess.cpp deleted file mode 100644 index 28a10b00cd..0000000000 --- a/dom/media/eme/MediaKeySystemAccess.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/MediaKeySystemAccess.h" -#include "mozilla/dom/MediaKeySystemAccessBinding.h" -#include "mozilla/Preferences.h" -#include "nsContentTypeParser.h" -#ifdef MOZ_FMP4 -#include "MP4Decoder.h" -#endif -#ifdef XP_WIN -#include "mozilla/WindowsVersion.h" -#include "WMFDecoderModule.h" -#endif -#include "nsContentCID.h" -#include "nsServiceManagerUtils.h" -#include "mozIGoannaMediaPluginService.h" -#include "VideoUtils.h" -#include "mozilla/Services.h" -#include "nsIObserverService.h" -#include "mozilla/EMEUtils.h" -#include "GMPUtils.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaKeySystemAccess, - mParent) -NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaKeySystemAccess) -NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaKeySystemAccess) -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaKeySystemAccess) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -MediaKeySystemAccess::MediaKeySystemAccess(nsPIDOMWindow* aParent, - const nsAString& aKeySystem) - : mParent(aParent) - , mKeySystem(aKeySystem) -{ -} - -MediaKeySystemAccess::~MediaKeySystemAccess() -{ -} - -JSObject* -MediaKeySystemAccess::WrapObject(JSContext* aCx) -{ - return MediaKeySystemAccessBinding::Wrap(aCx, this); -} - -nsPIDOMWindow* -MediaKeySystemAccess::GetParentObject() const -{ - return mParent; -} - -void -MediaKeySystemAccess::GetKeySystem(nsString& aRetVal) const -{ - aRetVal = mKeySystem; -} - -already_AddRefed -MediaKeySystemAccess::CreateMediaKeys(ErrorResult& aRv) -{ - nsRefPtr keys(new MediaKeys(mParent, mKeySystem)); - return keys->Init(aRv); -} - -static bool -HaveGMPFor(mozIGoannaMediaPluginService* aGMPService, - const nsCString& aKeySystem, - const nsCString& aAPI, - const nsCString& aTag = EmptyCString()) -{ - nsTArray tags; - tags.AppendElement(aKeySystem); - if (!aTag.IsEmpty()) { - tags.AppendElement(aTag); - } - bool hasPlugin = false; - if (NS_FAILED(aGMPService->HasPluginForAPI(aAPI, - &tags, - &hasPlugin))) { - return false; - } - return hasPlugin; -} - -static MediaKeySystemStatus -EnsureMinCDMVersion(mozIGoannaMediaPluginService* aGMPService, - const nsAString& aKeySystem, - int32_t aMinCdmVersion) -{ - if (aMinCdmVersion == NO_CDM_VERSION) { - return MediaKeySystemStatus::Available; - } - - nsTArray tags; - tags.AppendElement(NS_ConvertUTF16toUTF8(aKeySystem)); - nsAutoCString versionStr; - if (NS_FAILED(aGMPService->GetPluginVersionForAPI(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR), - &tags, - versionStr)) && - // XXX to be removed later in bug 1147692 - NS_FAILED(aGMPService->GetPluginVersionForAPI(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR_COMPAT), - &tags, - versionStr))) { - return MediaKeySystemStatus::Error; - } - - nsresult rv; - int32_t version = versionStr.ToInteger(&rv); - if (NS_FAILED(rv) || version < 0 || aMinCdmVersion > version) { - return MediaKeySystemStatus::Cdm_insufficient_version; - } - - return MediaKeySystemStatus::Available; -} - -/* static */ -MediaKeySystemStatus -MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem, - int32_t aMinCdmVersion) -{ - MOZ_ASSERT(Preferences::GetBool("media.eme.enabled", false)); - nsCOMPtr mps = - do_GetService("@mozilla.org/goanna-media-plugin-service;1"); - if (NS_WARN_IF(!mps)) { - return MediaKeySystemStatus::Error; - } - - if (aKeySystem.EqualsLiteral("org.w3.clearkey")) { - if (!Preferences::GetBool("media.eme.clearkey.enabled", true)) { - return MediaKeySystemStatus::Cdm_disabled; - } - if (!HaveGMPFor(mps, - NS_LITERAL_CSTRING("org.w3.clearkey"), - NS_LITERAL_CSTRING(GMP_API_DECRYPTOR))) { - return MediaKeySystemStatus::Cdm_not_installed; - } - return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion); - } - -#ifdef XP_WIN - if ((aKeySystem.EqualsLiteral("com.adobe.access") || - aKeySystem.EqualsLiteral("com.adobe.primetime"))) { - // Win Vista and later only. - if (!IsVistaOrLater()) { - return MediaKeySystemStatus::Cdm_not_supported; - } - if (!Preferences::GetBool("media.gmp-eme-adobe.enabled", false)) { - return MediaKeySystemStatus::Cdm_disabled; - } - if ((!WMFDecoderModule::HasH264() || !WMFDecoderModule::HasAAC()) || - !EMEVoucherFileExists()) { - // The system doesn't have the codecs that Adobe EME relies - // on installed, or doesn't have a voucher for the plugin-container. - // Adobe EME isn't going to work, so don't advertise that it will. - return MediaKeySystemStatus::Cdm_not_supported; - } - if (!HaveGMPFor(mps, - NS_ConvertUTF16toUTF8(aKeySystem), - NS_LITERAL_CSTRING(GMP_API_DECRYPTOR)) && - // XXX to be removed later in bug 1147692 - !HaveGMPFor(mps, - NS_ConvertUTF16toUTF8(aKeySystem), - NS_LITERAL_CSTRING(GMP_API_DECRYPTOR_COMPAT))) { - return MediaKeySystemStatus::Cdm_not_installed; - } - return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion); - } -#endif - - return MediaKeySystemStatus::Cdm_not_supported; -} - -static bool -IsPlayableWithGMP(mozIGoannaMediaPluginService* aGMPS, - const nsAString& aKeySystem, - const nsAString& aContentType) -{ -#ifdef MOZ_FMP4 - nsContentTypeParser parser(aContentType); - nsAutoString mimeType; - nsresult rv = parser.GetType(mimeType); - if (NS_FAILED(rv)) { - return false; - } - - if (!mimeType.EqualsLiteral("audio/mp4") && - !mimeType.EqualsLiteral("audio/x-m4a") && - !mimeType.EqualsLiteral("video/mp4")) { - return false; - } - - nsAutoString codecs; - parser.GetParameter("codecs", codecs); - - NS_ConvertUTF16toUTF8 mimeTypeUTF8(mimeType); - bool hasAAC = false; - bool hasH264 = false; - bool hasMP3 = false; - if (!MP4Decoder::CanHandleMediaType(mimeTypeUTF8, - codecs, - hasAAC, - hasH264, - hasMP3) || - hasMP3) { - return false; - } - return (!hasAAC || - !(HaveGMPFor(aGMPS, - NS_ConvertUTF16toUTF8(aKeySystem), - NS_LITERAL_CSTRING(GMP_API_DECRYPTOR), - NS_LITERAL_CSTRING("aac")) || - // XXX remove later in bug 1147692 - HaveGMPFor(aGMPS, - NS_ConvertUTF16toUTF8(aKeySystem), - NS_LITERAL_CSTRING(GMP_API_DECRYPTOR_COMPAT), - NS_LITERAL_CSTRING("aac")))) && - (!hasH264 || - !(HaveGMPFor(aGMPS, - NS_ConvertUTF16toUTF8(aKeySystem), - NS_LITERAL_CSTRING(GMP_API_DECRYPTOR), - NS_LITERAL_CSTRING("h264")) || - // XXX remove later in bug 1147692 - HaveGMPFor(aGMPS, - NS_ConvertUTF16toUTF8(aKeySystem), - NS_LITERAL_CSTRING(GMP_API_DECRYPTOR_COMPAT), - NS_LITERAL_CSTRING("h264")))); -#else - return false; -#endif -} - -/* static */ -bool -MediaKeySystemAccess::IsSupported(const nsAString& aKeySystem, - const Sequence& aOptions) -{ - nsCOMPtr mps = - do_GetService("@mozilla.org/goanna-media-plugin-service;1"); - if (NS_WARN_IF(!mps)) { - return false; - } - - for (size_t i = 0; i < aOptions.Length(); i++) { - const MediaKeySystemOptions& options = aOptions[i]; - if (!options.mInitDataType.EqualsLiteral("cenc")) { - continue; - } - if (!options.mAudioCapability.IsEmpty() || - !options.mVideoCapability.IsEmpty()) { - // Don't support any capabilites until we know we have a CDM with - // capabilities... - continue; - } - if (!options.mAudioType.IsEmpty() && - !IsPlayableWithGMP(mps, aKeySystem, options.mAudioType)) { - continue; - } - if (!options.mVideoType.IsEmpty() && - !IsPlayableWithGMP(mps, aKeySystem, options.mVideoType)) { - continue; - } - - // Our sandbox provides an origin specific unique identifier, and the - // ability to persist data. We don't yet have a way to turn those off - // and on for specific GMPs/CDMs, so we don't check the uniqueidentifier - // and stateful attributes here. - - return true; - } - return false; -} - -/* static */ -void -MediaKeySystemAccess::NotifyObservers(nsIDOMWindow* aWindow, - const nsAString& aKeySystem, - MediaKeySystemStatus aStatus) -{ - RequestMediaKeySystemAccessNotification data; - data.mKeySystem = aKeySystem; - data.mStatus = aStatus; - nsAutoString json; - data.ToJSON(json); - nsCOMPtr obs = services::GetObserverService(); - if (obs) { - obs->NotifyObservers(aWindow, "mediakeys-request", json.get()); - } -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeySystemAccess.h b/dom/media/eme/MediaKeySystemAccess.h deleted file mode 100644 index 1e51df28c6..0000000000 --- a/dom/media/eme/MediaKeySystemAccess.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_MediaKeySystemAccess_h -#define mozilla_dom_MediaKeySystemAccess_h - -#include "mozilla/Attributes.h" -#include "mozilla/ErrorResult.h" -#include "nsCycleCollectionParticipant.h" -#include "nsWrapperCache.h" - -#include "mozilla/dom/Promise.h" -#include "mozilla/dom/MediaKeySystemAccessBinding.h" -#include "mozilla/dom/MediaKeysRequestStatusBinding.h" - -#include "js/TypeDecls.h" - -namespace mozilla { -namespace dom { - -class MediaKeySystemAccess final : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaKeySystemAccess) - -public: - explicit MediaKeySystemAccess(nsPIDOMWindow* aParent, - const nsAString& aKeySystem); - -protected: - ~MediaKeySystemAccess(); - -public: - nsPIDOMWindow* GetParentObject() const; - - virtual JSObject* WrapObject(JSContext* aCx) override; - - void GetKeySystem(nsString& aRetVal) const; - - already_AddRefed CreateMediaKeys(ErrorResult& aRv); - - static MediaKeySystemStatus GetKeySystemStatus(const nsAString& aKeySystem, - int32_t aMinCdmVersion); - - static bool IsSupported(const nsAString& aKeySystem, - const Sequence& aOptions); - - static void NotifyObservers(nsIDOMWindow* aWindow, - const nsAString& aKeySystem, - MediaKeySystemStatus aStatus); - -private: - nsCOMPtr mParent; - const nsString mKeySystem; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_MediaKeySystemAccess_h diff --git a/dom/media/eme/MediaKeySystemAccessManager.cpp b/dom/media/eme/MediaKeySystemAccessManager.cpp deleted file mode 100644 index 480cb88a9b..0000000000 --- a/dom/media/eme/MediaKeySystemAccessManager.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public -* License, v. 2.0. If a copy of the MPL was not distributed with this -* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "MediaKeySystemAccessManager.h" -#include "mozilla/Preferences.h" -#include "mozilla/EMEUtils.h" -#include "nsServiceManagerUtils.h" -#include "nsComponentManagerUtils.h" -#include "nsIObserverService.h" -#include "mozilla/Services.h" - -namespace mozilla { -namespace dom { - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaKeySystemAccessManager) - NS_INTERFACE_MAP_ENTRY(nsISupports) - NS_INTERFACE_MAP_ENTRY(nsIObserver) -NS_INTERFACE_MAP_END - -NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaKeySystemAccessManager) -NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaKeySystemAccessManager) - -NS_IMPL_CYCLE_COLLECTION_CLASS(MediaKeySystemAccessManager) - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MediaKeySystemAccessManager) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow) - for (size_t i = 0; i < tmp->mRequests.Length(); i++) { - tmp->mRequests[i].RejectPromise(); - tmp->mRequests[i].CancelTimer(); - NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequests[i].mPromise) - } - tmp->mRequests.Clear(); -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(MediaKeySystemAccessManager) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow) - for (size_t i = 0; i < tmp->mRequests.Length(); i++) { - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequests[i].mPromise) - } -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -MediaKeySystemAccessManager::MediaKeySystemAccessManager(nsPIDOMWindow* aWindow) - : mWindow(aWindow) - , mAddedObservers(false) -{ -} - -MediaKeySystemAccessManager::~MediaKeySystemAccessManager() -{ - Shutdown(); -} - -void -MediaKeySystemAccessManager::Request(Promise* aPromise, - const nsAString& aKeySystem, - const Optional>& aOptions) -{ - if (aKeySystem.IsEmpty() || (aOptions.WasPassed() && aOptions.Value().IsEmpty())) { - aPromise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); - return; - } - Sequence optionsNotPassed; - const auto& options = aOptions.WasPassed() ? aOptions.Value() : optionsNotPassed; - Request(aPromise, aKeySystem, options, RequestType::Initial); -} - -void -MediaKeySystemAccessManager::Request(Promise* aPromise, - const nsAString& aKeySystem, - const Sequence& aOptions, - RequestType aType) -{ - EME_LOG("MediaKeySystemAccessManager::Request %s", NS_ConvertUTF16toUTF8(aKeySystem).get()); - if (!Preferences::GetBool("media.eme.enabled", false)) { - // EME disabled by user, send notification to chrome so UI can - // inform user. - MediaKeySystemAccess::NotifyObservers(mWindow, - aKeySystem, - MediaKeySystemStatus::Api_disabled); - aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return; - } - - // Parse keysystem, split it out into keySystem prefix, and version suffix. - nsAutoString keySystem; - int32_t minCdmVersion = NO_CDM_VERSION; - if (!ParseKeySystem(aKeySystem, - keySystem, - minCdmVersion)) { - // Invalid keySystem string, or unsupported keySystem. Send notification - // to chrome to show a failure notice. - MediaKeySystemAccess::NotifyObservers(mWindow, aKeySystem, MediaKeySystemStatus::Cdm_not_supported); - aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return; - } - - MediaKeySystemStatus status = MediaKeySystemAccess::GetKeySystemStatus(keySystem, minCdmVersion); - if ((status == MediaKeySystemStatus::Cdm_not_installed || - status == MediaKeySystemStatus::Cdm_insufficient_version) && - keySystem.EqualsLiteral("com.adobe.primetime")) { - // These are cases which could be resolved by downloading a new(er) CDM. - // When we send the status to chrome, chrome's GMPProvider will attempt to - // download or update the CDM. In AwaitInstall() we add listeners to wait - // for the update to complete, and we'll call this function again with - // aType==Subsequent once the download has completed and the GMPService - // has had a new plugin added. AwaitInstall() sets a timer to fail if the - // update/download takes too long or fails. - if (aType == RequestType::Initial && - AwaitInstall(aPromise, aKeySystem, aOptions)) { - // Notify chrome that we're going to wait for the CDM to download/update. - // Note: If we're re-trying, we don't re-send the notificaiton, - // as chrome is already displaying the "we can't play, updating" - // notification. - MediaKeySystemAccess::NotifyObservers(mWindow, keySystem, status); - } else { - // We waited or can't wait for an update and we still can't service - // the request. Give up. Chrome will still be showing a "I can't play, - // updating" notification. - aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - } - return; - } - if (status != MediaKeySystemStatus::Available) { - if (status != MediaKeySystemStatus::Error) { - // Failed due to user disabling something, send a notification to - // chrome, so we can show some UI to explain how the user can rectify - // the situation. - MediaKeySystemAccess::NotifyObservers(mWindow, keySystem, status); - } - aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return; - } - - if (aOptions.IsEmpty() || - MediaKeySystemAccess::IsSupported(keySystem, aOptions)) { - nsRefPtr access(new MediaKeySystemAccess(mWindow, keySystem)); - aPromise->MaybeResolve(access); - return; - } - - aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR); -} - -MediaKeySystemAccessManager::PendingRequest::PendingRequest(Promise* aPromise, - const nsAString& aKeySystem, - const Sequence& aOptions, - nsITimer* aTimer) - : mPromise(aPromise) - , mKeySystem(aKeySystem) - , mOptions(aOptions) - , mTimer(aTimer) -{ - MOZ_COUNT_CTOR(MediaKeySystemAccessManager::PendingRequest); -} - -MediaKeySystemAccessManager::PendingRequest::PendingRequest(const PendingRequest& aOther) - : mPromise(aOther.mPromise) - , mKeySystem(aOther.mKeySystem) - , mOptions(aOther.mOptions) - , mTimer(aOther.mTimer) -{ - MOZ_COUNT_CTOR(MediaKeySystemAccessManager::PendingRequest); -} - -MediaKeySystemAccessManager::PendingRequest::~PendingRequest() -{ - MOZ_COUNT_DTOR(MediaKeySystemAccessManager::PendingRequest); -} - -void -MediaKeySystemAccessManager::PendingRequest::CancelTimer() -{ - if (mTimer) { - mTimer->Cancel(); - } -} - -void -MediaKeySystemAccessManager::PendingRequest::RejectPromise() -{ - if (mPromise) { - mPromise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); - } -} - -bool -MediaKeySystemAccessManager::AwaitInstall(Promise* aPromise, - const nsAString& aKeySystem, - const Sequence& aOptions) -{ - EME_LOG("MediaKeySystemAccessManager::AwaitInstall %s", NS_ConvertUTF16toUTF8(aKeySystem).get()); - - if (!EnsureObserversAdded()) { - NS_WARNING("Failed to add pref observer"); - return false; - } - - nsCOMPtr timer(do_CreateInstance("@mozilla.org/timer;1")); - if (!timer || NS_FAILED(timer->Init(this, 60 * 1000, nsITimer::TYPE_ONE_SHOT))) { - NS_WARNING("Failed to create timer to await CDM install."); - return false; - } - - mRequests.AppendElement(PendingRequest(aPromise, aKeySystem, aOptions, timer)); - return true; -} - -void -MediaKeySystemAccessManager::RetryRequest(PendingRequest& aRequest) -{ - aRequest.CancelTimer(); - Request(aRequest.mPromise, aRequest.mKeySystem, aRequest.mOptions, RequestType::Subsequent); -} - -nsresult -MediaKeySystemAccessManager::Observe(nsISupports* aSubject, - const char* aTopic, - const char16_t* aData) -{ - EME_LOG("MediaKeySystemAccessManager::Observe %s", aTopic); - - if (!strcmp(aTopic, "gmp-path-added")) { - nsTArray requests(Move(mRequests)); - // Retry all pending requests, but this time fail if the CDM is not installed. - for (PendingRequest& request : requests) { - RetryRequest(request); - } - } else if (!strcmp(aTopic, "timer-callback")) { - // Find the timer that expired and re-run the request for it. - nsCOMPtr timer(do_QueryInterface(aSubject)); - for (size_t i = 0; i < mRequests.Length(); i++) { - if (mRequests[i].mTimer == timer) { - EME_LOG("MediaKeySystemAccessManager::AwaitInstall resuming request"); - PendingRequest request = mRequests[i]; - mRequests.RemoveElementAt(i); - RetryRequest(request); - break; - } - } - } - return NS_OK; -} - -bool -MediaKeySystemAccessManager::EnsureObserversAdded() -{ - if (mAddedObservers) { - return true; - } - - nsCOMPtr obsService = mozilla::services::GetObserverService(); - if (NS_WARN_IF(!obsService)) { - return false; - } - mAddedObservers = NS_SUCCEEDED(obsService->AddObserver(this, "gmp-path-added", false)); - return mAddedObservers; -} - -void -MediaKeySystemAccessManager::Shutdown() -{ - EME_LOG("MediaKeySystemAccessManager::Shutdown"); - nsTArray requests(Move(mRequests)); - for (PendingRequest& request : requests) { - // Cancel all requests; we're shutting down. - request.CancelTimer(); - request.RejectPromise(); - } - if (mAddedObservers) { - nsCOMPtr obsService = mozilla::services::GetObserverService(); - if (obsService) { - obsService->RemoveObserver(this, "gmp-path-added"); - mAddedObservers = false; - } - } -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeySystemAccessManager.h b/dom/media/eme/MediaKeySystemAccessManager.h deleted file mode 100644 index 66532f7bef..0000000000 --- a/dom/media/eme/MediaKeySystemAccessManager.h +++ /dev/null @@ -1,80 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public -* License, v. 2.0. If a copy of the MPL was not distributed with this -* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_MediaKeySystemAccessManager_h -#define mozilla_dom_MediaKeySystemAccessManager_h - -#include "mozilla/dom/MediaKeySystemAccess.h" -#include "nsIObserver.h" -#include "nsCycleCollectionParticipant.h" -#include "nsISupportsImpl.h" -#include "nsITimer.h" - -namespace mozilla { -namespace dom { - -class MediaKeySystemAccessManager final : public nsIObserver -{ -public: - - explicit MediaKeySystemAccessManager(nsPIDOMWindow* aWindow); - - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(MediaKeySystemAccessManager, nsIObserver) - NS_DECL_NSIOBSERVER - - void Request(Promise* aPromise, - const nsAString& aKeySystem, - const Optional>& aOptions); - - void Shutdown(); - - struct PendingRequest { - PendingRequest(Promise* aPromise, - const nsAString& aKeySystem, - const Sequence& aOptions, - nsITimer* aTimer); - PendingRequest(const PendingRequest& aOther); - ~PendingRequest(); - void CancelTimer(); - void RejectPromise(); - - nsRefPtr mPromise; - const nsString mKeySystem; - const Sequence mOptions; - nsCOMPtr mTimer; - }; - -private: - - enum RequestType { - Initial, - Subsequent - }; - - void Request(Promise* aPromise, - const nsAString& aKeySystem, - const Sequence& aOptions, - RequestType aType); - - ~MediaKeySystemAccessManager(); - - bool EnsureObserversAdded(); - - bool AwaitInstall(Promise* aPromise, - const nsAString& aKeySystem, - const Sequence& aOptions); - - void RetryRequest(PendingRequest& aRequest); - - nsTArray mRequests; - - nsCOMPtr mWindow; - bool mAddedObservers; -}; - -} // namespace dom -} // namespace mozilla - -#endif diff --git a/dom/media/eme/MediaKeys.cpp b/dom/media/eme/MediaKeys.cpp deleted file mode 100644 index a256286081..0000000000 --- a/dom/media/eme/MediaKeys.cpp +++ /dev/null @@ -1,597 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mozilla/dom/MediaKeys.h" -#include "GMPService.h" -#include "mozilla/EventDispatcher.h" -#include "mozilla/dom/HTMLMediaElement.h" -#include "mozilla/dom/MediaKeysBinding.h" -#include "mozilla/dom/MediaKeyMessageEvent.h" -#include "mozilla/dom/MediaKeyError.h" -#include "mozilla/dom/MediaKeySession.h" -#include "mozilla/dom/DOMException.h" -#include "mozilla/dom/PluginCrashedEvent.h" -#include "mozilla/dom/UnionTypes.h" -#include "mozilla/CDMProxy.h" -#include "mozilla/EMEUtils.h" -#include "nsContentUtils.h" -#include "nsIScriptObjectPrincipal.h" -#include "mozilla/Preferences.h" -#include "nsContentTypeParser.h" -#ifdef MOZ_FMP4 -#include "MP4Decoder.h" -#endif -#ifdef XP_WIN -#include "mozilla/WindowsVersion.h" -#endif -#include "nsContentCID.h" -#include "nsServiceManagerUtils.h" -#include "mozilla/dom/MediaKeySystemAccess.h" -#include "nsPrintfCString.h" - -namespace mozilla { - -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaKeys, - mElement, - mParent, - mKeySessions, - mPromises, - mPendingSessions); -NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaKeys) -NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaKeys) -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaKeys) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -MediaKeys::MediaKeys(nsPIDOMWindow* aParent, const nsAString& aKeySystem) - : mParent(aParent) - , mKeySystem(aKeySystem) - , mCreatePromiseId(0) -{ -} - -static PLDHashOperator -RejectPromises(const uint32_t& aKey, - nsRefPtr& aPromise, - void* aClosure) -{ - aPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - ((MediaKeys*)aClosure)->Release(); - return PL_DHASH_NEXT; -} - -MediaKeys::~MediaKeys() -{ - Shutdown(); -} - -static PLDHashOperator -CopySessions(const nsAString& aKey, - nsRefPtr& aSession, - void* aClosure) -{ - KeySessionHashMap* p = static_cast(aClosure); - p->Put(aSession->GetSessionId(), aSession); - return PL_DHASH_NEXT; -} - -static PLDHashOperator -CloseSessions(const nsAString& aKey, - nsRefPtr& aSession, - void* aClosure) -{ - aSession->OnClosed(); - return PL_DHASH_NEXT; -} - -void -MediaKeys::Terminated() -{ - KeySessionHashMap keySessions; - // Remove entries during iteration will screw it. Make a copy first. - mKeySessions.Enumerate(&CopySessions, &keySessions); - keySessions.Enumerate(&CloseSessions, nullptr); - keySessions.Clear(); - MOZ_ASSERT(mKeySessions.Count() == 0); - - // Notify the element about that CDM has terminated. - if (mElement) { - mElement->DecodeError(); - } - - Shutdown(); -} - -void -MediaKeys::Shutdown() -{ - if (mProxy) { - mProxy->Shutdown(); - mProxy = nullptr; - } - - nsRefPtr kungFuDeathGrip = this; - - mPromises.Enumerate(&RejectPromises, this); - mPromises.Clear(); -} - -nsPIDOMWindow* -MediaKeys::GetParentObject() const -{ - return mParent; -} - -JSObject* -MediaKeys::WrapObject(JSContext* aCx) -{ - return MediaKeysBinding::Wrap(aCx, this); -} - -void -MediaKeys::GetKeySystem(nsString& retval) const -{ - retval = mKeySystem; -} - -already_AddRefed -MediaKeys::SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aCert, ErrorResult& aRv) -{ - nsRefPtr promise(MakePromise(aRv)); - if (aRv.Failed()) { - return nullptr; - } - - if (!mProxy) { - NS_WARNING("Tried to use a MediaKeys without a CDM"); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - return promise.forget(); - } - - nsTArray data; - if (!CopyArrayBufferViewOrArrayBufferData(aCert, data)) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); - return promise.forget(); - } - - mProxy->SetServerCertificate(StorePromise(promise), data); - return promise.forget(); -} - -already_AddRefed -MediaKeys::MakePromise(ErrorResult& aRv) -{ - nsCOMPtr global = do_QueryInterface(GetParentObject()); - if (!global) { - NS_WARNING("Passed non-global to MediaKeys ctor!"); - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - return Promise::Create(global, aRv); -} - -PromiseId -MediaKeys::StorePromise(Promise* aPromise) -{ - static uint32_t sEMEPromiseCount = 1; - MOZ_ASSERT(aPromise); - uint32_t id = sEMEPromiseCount++; - - EME_LOG("MediaKeys[%p]::StorePromise() id=%d", this, id); - - // Keep MediaKeys alive for the lifetime of its promises. Any still-pending - // promises are rejected in Shutdown(). - AddRef(); - - mPromises.Put(id, aPromise); - return id; -} - -already_AddRefed -MediaKeys::RetrievePromise(PromiseId aId) -{ - if (!mPromises.Contains(aId)) { - NS_WARNING(nsPrintfCString("Tried to retrieve a non-existent promise id=%d", aId).get()); - return nullptr; - } - nsRefPtr promise; - mPromises.Remove(aId, getter_AddRefs(promise)); - Release(); - return promise.forget(); -} - -void -MediaKeys::RejectPromise(PromiseId aId, nsresult aExceptionCode) -{ - EME_LOG("MediaKeys[%p]::RejectPromise(%d, 0x%x)", this, aId, aExceptionCode); - - nsRefPtr promise(RetrievePromise(aId)); - if (!promise) { - return; - } - if (mPendingSessions.Contains(aId)) { - // This promise could be a createSession or loadSession promise, - // so we might have a pending session waiting to be resolved into - // the promise on success. We've been directed to reject to promise, - // so we can throw away the corresponding session object. - mPendingSessions.Remove(aId); - } - - MOZ_ASSERT(NS_FAILED(aExceptionCode)); - promise->MaybeReject(aExceptionCode); - - if (mCreatePromiseId == aId) { - // Note: This will probably destroy the MediaKeys object! - Release(); - } -} - -void -MediaKeys::OnSessionIdReady(MediaKeySession* aSession) -{ - if (!aSession) { - NS_WARNING("Invalid MediaKeySession passed to OnSessionIdReady()"); - return; - } - if (mKeySessions.Contains(aSession->GetSessionId())) { - NS_WARNING("MediaKeySession's made ready multiple times!"); - return; - } - if (mPendingSessions.Contains(aSession->Token())) { - NS_WARNING("MediaKeySession made ready when it wasn't waiting to be ready!"); - return; - } - if (aSession->GetSessionId().IsEmpty()) { - NS_WARNING("MediaKeySession with invalid sessionId passed to OnSessionIdReady()"); - return; - } - mKeySessions.Put(aSession->GetSessionId(), aSession); -} - -void -MediaKeys::ResolvePromise(PromiseId aId) -{ - EME_LOG("MediaKeys[%p]::ResolvePromise(%d)", this, aId); - - nsRefPtr promise(RetrievePromise(aId)); - if (!promise) { - return; - } - if (mPendingSessions.Contains(aId)) { - // We should only resolve LoadSession calls via this path, - // not CreateSession() promises. - nsRefPtr session; - if (!mPendingSessions.Get(aId, getter_AddRefs(session)) || - !session || - session->GetSessionId().IsEmpty()) { - NS_WARNING("Received activation for non-existent session!"); - promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); - mPendingSessions.Remove(aId); - return; - } - mPendingSessions.Remove(aId); - mKeySessions.Put(session->GetSessionId(), session); - promise->MaybeResolve(session); - } else { - promise->MaybeResolve(JS::UndefinedHandleValue); - } -} - -already_AddRefed -MediaKeys::Init(ErrorResult& aRv) -{ - nsRefPtr promise(MakePromise(aRv)); - if (aRv.Failed()) { - return nullptr; - } - - mProxy = new CDMProxy(this, mKeySystem); - - // Determine principal (at creation time) of the MediaKeys object. - nsCOMPtr sop = do_QueryInterface(GetParentObject()); - if (!sop) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - return promise.forget(); - } - mPrincipal = sop->GetPrincipal(); - - // Determine principal of the "top-level" window; the principal of the - // page that will display in the URL bar. - nsCOMPtr window = do_QueryInterface(GetParentObject()); - if (!window) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - return promise.forget(); - } - nsCOMPtr topWindow; - window->GetTop(getter_AddRefs(topWindow)); - nsCOMPtr top = do_QueryInterface(topWindow); - if (!top || !top->GetExtantDoc()) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - return promise.forget(); - } - - mTopLevelPrincipal = top->GetExtantDoc()->NodePrincipal(); - - if (!mPrincipal || !mTopLevelPrincipal) { - NS_WARNING("Failed to get principals when creating MediaKeys"); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - return promise.forget(); - } - - nsAutoString origin; - nsresult rv = nsContentUtils::GetUTFOrigin(mPrincipal, origin); - if (NS_FAILED(rv)) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - return promise.forget(); - } - nsAutoString topLevelOrigin; - rv = nsContentUtils::GetUTFOrigin(mTopLevelPrincipal, topLevelOrigin); - if (NS_FAILED(rv)) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - return promise.forget(); - } - - if (!window) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); - return promise.forget(); - } - nsIDocument* doc = window->GetExtantDoc(); - const bool inPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc); - - EME_LOG("MediaKeys[%p]::Create() (%s, %s), %s", - this, - NS_ConvertUTF16toUTF8(origin).get(), - NS_ConvertUTF16toUTF8(topLevelOrigin).get(), - (inPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing")); - - // The CDMProxy's initialization is asynchronous. The MediaKeys is - // refcounted, and its instance is returned to JS by promise once - // it's been initialized. No external refs exist to the MediaKeys while - // we're waiting for the promise to be resolved, so we must hold a - // reference to the new MediaKeys object until it's been created, - // or its creation has failed. Store the id of the promise returned - // here, and hold a self-reference until that promise is resolved or - // rejected. - MOZ_ASSERT(!mCreatePromiseId, "Should only be created once!"); - mCreatePromiseId = StorePromise(promise); - AddRef(); - mProxy->Init(mCreatePromiseId, - origin, - topLevelOrigin, - inPrivateBrowsing); - - return promise.forget(); -} - -class CrashHandler : public gmp::GoannaMediaPluginService::PluginCrashCallback -{ -public: - CrashHandler(const nsACString& aPluginId, - nsPIDOMWindow* aParentWindow, - nsIDocument* aDocument) - : gmp::GoannaMediaPluginService::PluginCrashCallback(aPluginId) - , mParentWindowWeakPtr(do_GetWeakReference(aParentWindow)) - , mDocumentWeakPtr(do_GetWeakReference(aDocument)) - { - } - - virtual void Run(const nsACString& aPluginName, const nsAString& aPluginDumpId) override - { - PluginCrashedEventInit init; - init.mBubbles = true; - init.mCancelable = true; - init.mGmpPlugin = true; - init.mPluginDumpID = aPluginDumpId; - CopyUTF8toUTF16(aPluginName, init.mPluginName); - init.mSubmittedCrashReport = false; - - // The following PluginCrashedEvent fields stay empty: - // init.mBrowserDumpID - // init.mPluginFilename - // TODO: Can/should we fill them? - - nsCOMPtr parentWindow; - nsCOMPtr document; - if (!GetParentWindowAndDocumentIfValid(parentWindow, document)) { - return; - } - - nsRefPtr event = - PluginCrashedEvent::Constructor(document, NS_LITERAL_STRING("PluginCrashed"), init); - event->SetTrusted(true); - event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true; - - EventDispatcher::DispatchDOMEvent(parentWindow, nullptr, event, nullptr, nullptr); - } - - virtual bool IsStillValid() override - { - nsCOMPtr parentWindow; - nsCOMPtr document; - return GetParentWindowAndDocumentIfValid(parentWindow, document); - } - -private: - virtual ~CrashHandler() - { } - - bool - GetParentWindowAndDocumentIfValid(nsCOMPtr& parentWindow, - nsCOMPtr& document) - { - parentWindow = do_QueryReferent(mParentWindowWeakPtr); - if (!parentWindow) { - return false; - } - document = do_QueryReferent(mDocumentWeakPtr); - if (!document) { - return false; - } - nsCOMPtr parentWindowDocument = parentWindow->GetExtantDoc(); - if (!parentWindowDocument || document.get() != parentWindowDocument.get()) { - return false; - } - return true; - } - - nsWeakPtr mParentWindowWeakPtr; - nsWeakPtr mDocumentWeakPtr; -}; - -void -MediaKeys::OnCDMCreated(PromiseId aId, const nsACString& aNodeId, const nsACString& aPluginId) -{ - nsRefPtr promise(RetrievePromise(aId)); - if (!promise) { - return; - } - mNodeId = aNodeId; - nsRefPtr keys(this); - EME_LOG("MediaKeys[%p]::OnCDMCreated() resolve promise id=%d", this, aId); - promise->MaybeResolve(keys); - if (mCreatePromiseId == aId) { - Release(); - } - - MediaKeySystemAccess::NotifyObservers(mParent, - mKeySystem, - MediaKeySystemStatus::Cdm_created); - - if (!aPluginId.IsEmpty()) { - // Prepare plugin crash reporter. - nsRefPtr service = - gmp::GoannaMediaPluginService::GetGoannaMediaPluginService(); - if (NS_WARN_IF(!service)) { - return; - } - if (NS_WARN_IF(!mParent)) { - return; - } - nsCOMPtr doc = mParent->GetExtantDoc(); - if (NS_WARN_IF(!doc)) { - return; - } - service->AddPluginCrashCallback(new CrashHandler(aPluginId, mParent, doc)); - EME_LOG("MediaKeys[%p]::OnCDMCreated() registered crash handler for pluginId '%s'", - this, aPluginId.Data()); - } -} - -already_AddRefed -MediaKeys::CreateSession(JSContext* aCx, - SessionType aSessionType, - ErrorResult& aRv) -{ - if (!mProxy) { - NS_WARNING("Tried to use a MediaKeys which lost its CDM"); - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - return nullptr; - } - - nsRefPtr session = new MediaKeySession(aCx, - GetParentObject(), - this, - mKeySystem, - aSessionType, - aRv); - - if (aRv.Failed()) { - return nullptr; - } - - // Add session to the set of sessions awaiting their sessionId being ready. - mPendingSessions.Put(session->Token(), session); - - return session.forget(); -} - -void -MediaKeys::OnSessionLoaded(PromiseId aId, bool aSuccess) -{ - nsRefPtr promise(RetrievePromise(aId)); - if (!promise) { - return; - } - EME_LOG("MediaKeys[%p]::OnSessionLoaded() resolve promise id=%d", this, aId); - - promise->MaybeResolve(aSuccess); -} - -void -MediaKeys::OnSessionClosed(MediaKeySession* aSession) -{ - nsAutoString id; - aSession->GetSessionId(id); - mKeySessions.Remove(id); -} - -already_AddRefed -MediaKeys::GetSession(const nsAString& aSessionId) -{ - nsRefPtr session; - mKeySessions.Get(aSessionId, getter_AddRefs(session)); - return session.forget(); -} - -already_AddRefed -MediaKeys::GetPendingSession(uint32_t aToken) -{ - nsRefPtr session; - mPendingSessions.Get(aToken, getter_AddRefs(session)); - mPendingSessions.Remove(aToken); - return session.forget(); -} - -const nsCString& -MediaKeys::GetNodeId() const -{ - MOZ_ASSERT(NS_IsMainThread()); - return mNodeId; -} - -bool -MediaKeys::IsBoundToMediaElement() const -{ - MOZ_ASSERT(NS_IsMainThread()); - return mElement != nullptr; -} - -nsresult -MediaKeys::Bind(HTMLMediaElement* aElement) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (IsBoundToMediaElement()) { - return NS_ERROR_FAILURE; - } - - mElement = aElement; - - return NS_OK; -} - -bool -CopyArrayBufferViewOrArrayBufferData(const ArrayBufferViewOrArrayBuffer& aBufferOrView, - nsTArray& aOutData) -{ - if (aBufferOrView.IsArrayBuffer()) { - const ArrayBuffer& buffer = aBufferOrView.GetAsArrayBuffer(); - buffer.ComputeLengthAndData(); - aOutData.AppendElements(buffer.Data(), buffer.Length()); - } else if (aBufferOrView.IsArrayBufferView()) { - const ArrayBufferView& bufferview = aBufferOrView.GetAsArrayBufferView(); - bufferview.ComputeLengthAndData(); - aOutData.AppendElements(bufferview.Data(), bufferview.Length()); - } else { - return false; - } - return true; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeys.h b/dom/media/eme/MediaKeys.h deleted file mode 100644 index c24531d105..0000000000 --- a/dom/media/eme/MediaKeys.h +++ /dev/null @@ -1,151 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef mozilla_dom_mediakeys_h__ -#define mozilla_dom_mediakeys_h__ - -#include "nsIDOMMediaError.h" -#include "nsWrapperCache.h" -#include "nsISupports.h" -#include "mozilla/Attributes.h" -#include "mozilla/RefPtr.h" -#include "nsCOMPtr.h" -#include "nsCycleCollectionParticipant.h" -#include "nsRefPtrHashtable.h" -#include "mozilla/dom/Promise.h" -#include "mozilla/dom/MediaKeysBinding.h" -#include "mozIGoannaMediaPluginService.h" - -namespace mozilla { - -class CDMProxy; - -namespace dom { - -class ArrayBufferViewOrArrayBuffer; -class MediaKeySession; -class HTMLMediaElement; - -typedef nsRefPtrHashtable KeySessionHashMap; -typedef nsRefPtrHashtable PromiseHashMap; -typedef nsRefPtrHashtable PendingKeySessionsHashMap; -typedef uint32_t PromiseId; - -// Helper function to extract data coming in from JS in an -// (ArrayBuffer or ArrayBufferView) IDL typed function argument. -bool -CopyArrayBufferViewOrArrayBufferData(const ArrayBufferViewOrArrayBuffer& aBufferOrView, - nsTArray& aOutData); - -// This class is used on the main thread only. -// Note: it's addref/release is not (and can't be) thread safe! -class MediaKeys final : public nsISupports, - public nsWrapperCache -{ - ~MediaKeys(); - -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaKeys) - - MediaKeys(nsPIDOMWindow* aParentWindow, const nsAString& aKeySystem); - - already_AddRefed Init(ErrorResult& aRv); - - nsPIDOMWindow* GetParentObject() const; - - virtual JSObject* WrapObject(JSContext* aCx) override; - - nsresult Bind(HTMLMediaElement* aElement); - - // Javascript: readonly attribute DOMString keySystem; - void GetKeySystem(nsString& retval) const; - - // JavaScript: MediaKeys.createSession() - already_AddRefed CreateSession(JSContext* aCx, - SessionType aSessionType, - ErrorResult& aRv); - - // JavaScript: MediaKeys.SetServerCertificate() - already_AddRefed SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aServerCertificate, - ErrorResult& aRv); - - already_AddRefed GetSession(const nsAString& aSessionId); - - // Removes and returns MediaKeySession from the set of sessions awaiting - // their sessionId to be assigned. - already_AddRefed GetPendingSession(uint32_t aToken); - - // Called once a Init() operation succeeds. - void OnCDMCreated(PromiseId aId, - const nsACString& aNodeId, const nsACString& aPluginId); - - // Called once the CDM generates a sessionId while servicing a - // MediaKeySession.generateRequest() or MediaKeySession.load() call, - // once the sessionId of a MediaKeySession is known. - void OnSessionIdReady(MediaKeySession* aSession); - - // Called once a LoadSession succeeds. - void OnSessionLoaded(PromiseId aId, bool aSuccess); - - // Called once a session has closed. - void OnSessionClosed(MediaKeySession* aSession); - - CDMProxy* GetCDMProxy() { return mProxy; } - - // Makes a new promise, or nullptr on failure. - already_AddRefed MakePromise(ErrorResult& aRv); - // Stores promise in mPromises, returning an ID that can be used to retrieve - // it later. The ID is passed to the CDM, so that it can signal specific - // promises to be resolved. - PromiseId StorePromise(Promise* aPromise); - - // Reject promise with DOMException corresponding to aExceptionCode. - void RejectPromise(PromiseId aId, nsresult aExceptionCode); - // Resolves promise with "undefined". - void ResolvePromise(PromiseId aId); - - const nsCString& GetNodeId() const; - - void Shutdown(); - - // Called by CDMProxy when CDM crashes or shuts down. It is different from - // Shutdown which is called from the script/dom side. - void Terminated(); - - // Returns true if this MediaKeys has been bound to a media element. - bool IsBoundToMediaElement() const; - -private: - - bool IsInPrivateBrowsing(); - - // Removes promise from mPromises, and returns it. - already_AddRefed RetrievePromise(PromiseId aId); - - // Owning ref to proxy. The proxy has a weak reference back to the MediaKeys, - // and the MediaKeys destructor clears the proxy's reference to the MediaKeys. - nsRefPtr mProxy; - - nsRefPtr mElement; - - nsCOMPtr mParent; - nsString mKeySystem; - nsCString mNodeId; - KeySessionHashMap mKeySessions; - PromiseHashMap mPromises; - PendingKeySessionsHashMap mPendingSessions; - PromiseId mCreatePromiseId; - - nsRefPtr mPrincipal; - nsRefPtr mTopLevelPrincipal; - -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_mediakeys_h__ diff --git a/dom/media/eme/moz.build b/dom/media/eme/moz.build deleted file mode 100644 index 14c5f05258..0000000000 --- a/dom/media/eme/moz.build +++ /dev/null @@ -1,42 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -EXPORTS.mozilla.dom += [ - 'MediaEncryptedEvent.h', - 'MediaKeyError.h', - 'MediaKeyMessageEvent.h', - 'MediaKeys.h', - 'MediaKeySession.h', - 'MediaKeyStatusMap.h', - 'MediaKeySystemAccess.h', - 'MediaKeySystemAccessManager.h', -] - -EXPORTS.mozilla += [ - 'CDMCallbackProxy.h', - 'CDMCaps.h', - 'CDMProxy.h', - 'EMEUtils.h' -] - -UNIFIED_SOURCES += [ - 'CDMCallbackProxy.cpp', - 'CDMCaps.cpp', - 'CDMProxy.cpp', - 'EMEUtils.cpp', - 'MediaEncryptedEvent.cpp', - 'MediaKeyError.cpp', - 'MediaKeyMessageEvent.cpp', - 'MediaKeys.cpp', - 'MediaKeySession.cpp', - 'MediaKeyStatusMap.cpp', - 'MediaKeySystemAccess.cpp', - 'MediaKeySystemAccessManager.cpp', -] - -FINAL_LIBRARY = 'xul' - -FAIL_ON_WARNINGS = True diff --git a/dom/media/fmp4/MP4Decoder.cpp b/dom/media/fmp4/MP4Decoder.cpp index d6c6509aac..97ada8b9e3 100644 --- a/dom/media/fmp4/MP4Decoder.cpp +++ b/dom/media/fmp4/MP4Decoder.cpp @@ -9,9 +9,6 @@ #include "MediaDecoderStateMachine.h" #include "mozilla/Preferences.h" #include "nsCharSeparatedTokenizer.h" -#ifdef MOZ_EME -#include "mozilla/CDMProxy.h" -#endif #include "prlog.h" #ifdef XP_WIN @@ -36,25 +33,6 @@ MediaDecoderStateMachine* MP4Decoder::CreateStateMachine() return new MediaDecoderStateMachine(this, new MP4Reader(this)); } -#ifdef MOZ_EME -nsresult -MP4Decoder::SetCDMProxy(CDMProxy* aProxy) -{ - nsresult rv = MediaDecoder::SetCDMProxy(aProxy); - NS_ENSURE_SUCCESS(rv, rv); - if (aProxy) { - // The MP4Reader can't decrypt EME content until it has a CDMProxy, - // and the CDMProxy knows the capabilities of the CDM. The MP4Reader - // remains in "waiting for resources" state until then. - CDMCaps::AutoLock caps(aProxy->Capabilites()); - nsRefPtr task( - NS_NewRunnableMethod(this, &MediaDecoder::NotifyWaitingForResourcesStatusChanged)); - caps.CallOnMainThreadWhenCapsAvailable(task); - } - return NS_OK; -} -#endif - static bool IsSupportedAudioCodec(const nsAString& aCodec, bool& aOutContainsAAC, diff --git a/dom/media/fmp4/MP4Decoder.h b/dom/media/fmp4/MP4Decoder.h index f166469eba..efc5433238 100644 --- a/dom/media/fmp4/MP4Decoder.h +++ b/dom/media/fmp4/MP4Decoder.h @@ -24,10 +24,6 @@ public: virtual MediaDecoderStateMachine* CreateStateMachine() override; -#ifdef MOZ_EME - virtual nsresult SetCDMProxy(CDMProxy* aProxy) override; -#endif - // Returns true if aMIMEType is a type that we think we can render with the // a MP4 platform decoder backend. If aCodecs is non emtpy, it is filled // with a comma-delimited list of codecs to check support for. Notes in diff --git a/dom/media/fmp4/MP4Reader.cpp b/dom/media/fmp4/MP4Reader.cpp index 9560537a14..c6bc6144d3 100644 --- a/dom/media/fmp4/MP4Reader.cpp +++ b/dom/media/fmp4/MP4Reader.cpp @@ -22,10 +22,6 @@ #include "SharedDecoderManager.h" #include -#ifdef MOZ_EME -#include "mozilla/CDMProxy.h" -#endif - using mozilla::layers::Image; using mozilla::layers::LayerManager; using mozilla::layers::LayersBackend; @@ -263,34 +259,6 @@ MP4Reader::Init(MediaDecoderReader* aCloneDonor) return NS_OK; } -#ifdef MOZ_EME -class DispatchKeyNeededEvent : public nsRunnable { -public: - DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder, - nsTArray& aInitData, - const nsString& aInitDataType) - : mDecoder(aDecoder) - , mInitData(aInitData) - , mInitDataType(aInitDataType) - { - } - NS_IMETHOD Run() { - // Note: Null check the owner, as the decoder could have been shutdown - // since this event was dispatched. - MediaDecoderOwner* owner = mDecoder->GetOwner(); - if (owner) { - owner->DispatchEncrypted(mInitData, mInitDataType); - } - mDecoder = nullptr; - return NS_OK; - } -private: - nsRefPtr mDecoder; - nsTArray mInitData; - nsString mInitDataType; -}; -#endif - void MP4Reader::RequestCodecResource() { if (mVideo.mDecoder) { mVideo.mDecoder->AllocateMediaResources(); @@ -302,29 +270,8 @@ bool MP4Reader::IsWaitingOnCodecResource() { } bool MP4Reader::IsWaitingOnCDMResource() { -#ifdef MOZ_EME - nsRefPtr proxy; - { - ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); - if (!mIsEncrypted) { - // Not encrypted, no need to wait for CDMProxy. - return false; - } - proxy = mDecoder->GetCDMProxy(); - if (!proxy) { - // We're encrypted, we need a CDMProxy to decrypt file. - return true; - } - } - // We'll keep waiting if the CDM hasn't informed Goanna of its capabilities. - { - CDMCaps::AutoLock caps(proxy->Capabilites()); - LOG("capsKnown=%d", caps.AreCapsKnown()); - return !caps.AreCapsKnown(); - } -#else + // EME Stub return false; -#endif } bool MP4Reader::IsWaitingMediaResources() @@ -411,42 +358,8 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo, } if (mDemuxer->Crypto().valid) { -#ifdef MOZ_EME - // We have encrypted audio or video. We'll need a CDM to decrypt and - // possibly decode this. Wait until we've received a CDM from the - // JavaScript player app. Note: we still go through the motions here - // even if EME is disabled, so that if script tries and fails to create - // a CDM, we can detect that and notify chrome and show some UI explaining - // that we failed due to EME being disabled. - nsRefPtr proxy; - nsTArray initData; - ExtractCryptoInitData(initData); - if (initData.Length() == 0) { - return NS_ERROR_FAILURE; - } - if (!mInitDataEncountered.Contains(initData)) { - mInitDataEncountered.AppendElement(initData); - NS_DispatchToMainThread(new DispatchKeyNeededEvent(mDecoder, initData, NS_LITERAL_STRING("cenc"))); - } - if (IsWaitingMediaResources()) { - return NS_OK; - } - MOZ_ASSERT(!IsWaitingMediaResources()); - - { - ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); - proxy = mDecoder->GetCDMProxy(); - } - MOZ_ASSERT(proxy); - - mPlatform = PlatformDecoderModule::CreateCDMWrapper(proxy, - HasAudio(), - HasVideo()); - NS_ENSURE_TRUE(mPlatform, NS_ERROR_FAILURE); -#else // EME not supported. return NS_ERROR_FAILURE; -#endif } else { mPlatform = PlatformDecoderModule::Create(); NS_ENSURE_TRUE(mPlatform, NS_ERROR_FAILURE); diff --git a/dom/media/fmp4/PlatformDecoderModule.cpp b/dom/media/fmp4/PlatformDecoderModule.cpp index 1c81b03c51..2d86a9ad14 100644 --- a/dom/media/fmp4/PlatformDecoderModule.cpp +++ b/dom/media/fmp4/PlatformDecoderModule.cpp @@ -25,10 +25,6 @@ #include "GMPDecoderModule.h" #include "mozilla/Preferences.h" -#ifdef MOZ_EME -#include "EMEDecoderModule.h" -#include "mozilla/CDMProxy.h" -#endif #include "SharedThreadPool.h" #include "MediaTaskQueue.h" @@ -81,40 +77,6 @@ PlatformDecoderModule::Init() #endif } -#ifdef MOZ_EME -/* static */ -already_AddRefed -PlatformDecoderModule::CreateCDMWrapper(CDMProxy* aProxy, - bool aHasAudio, - bool aHasVideo) -{ - bool cdmDecodesAudio; - bool cdmDecodesVideo; - { - CDMCaps::AutoLock caps(aProxy->Capabilites()); - cdmDecodesAudio = caps.CanDecryptAndDecodeAudio(); - cdmDecodesVideo = caps.CanDecryptAndDecodeVideo(); - } - - nsRefPtr pdm; - if ((!cdmDecodesAudio && aHasAudio) || (!cdmDecodesVideo && aHasVideo)) { - // The CDM itself can't decode. We need to wrap a PDM to decode the - // decrypted output of the CDM. - pdm = Create(); - if (!pdm) { - return nullptr; - } - } - - nsRefPtr emepdm( - new AVCCDecoderModule(new EMEDecoderModule(aProxy, - pdm, - cdmDecodesAudio, - cdmDecodesVideo))); - return emepdm.forget(); -} -#endif - /* static */ already_AddRefed PlatformDecoderModule::Create() diff --git a/dom/media/fmp4/PlatformDecoderModule.h b/dom/media/fmp4/PlatformDecoderModule.h index 836d939ff8..e7830d0cdc 100644 --- a/dom/media/fmp4/PlatformDecoderModule.h +++ b/dom/media/fmp4/PlatformDecoderModule.h @@ -74,18 +74,6 @@ public: // This is called on the decode task queue. virtual nsresult Startup() { return NS_OK; }; -#ifdef MOZ_EME - // Creates a PlatformDecoderModule that uses a CDMProxy to decrypt or - // decrypt-and-decode EME encrypted content. If the CDM only decrypts and - // does not decode, we create a PDM and use that to create MediaDataDecoders - // that we use on on aTaskQueue to decode the decrypted stream. - // This is called on the decode task queue. - static already_AddRefed - CreateCDMWrapper(CDMProxy* aProxy, - bool aHasAudio, - bool aHasVideo); -#endif - // Creates an H.264 decoder. The layers backend is passed in so that // decoders can determine whether hardware accelerated decoding can be used. // Asynchronous decoding of video should be done in runnables dispatched diff --git a/dom/media/fmp4/eme/EMEAudioDecoder.cpp b/dom/media/fmp4/eme/EMEAudioDecoder.cpp deleted file mode 100644 index 5bd85f8b35..0000000000 --- a/dom/media/fmp4/eme/EMEAudioDecoder.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "EMEAudioDecoder.h" -#include "mozilla/CDMProxy.h" - -namespace mozilla { - -void -EMEAudioCallbackAdapter::Error(GMPErr aErr) -{ - if (aErr == GMPNoKeyErr) { - // The GMP failed to decrypt a frame due to not having a key. This can - // happen if a key expires or a session is closed during playback. - NS_WARNING("GMP failed to decrypt due to lack of key"); - return; - } - AudioCallbackAdapter::Error(aErr); -} - -void -EMEAudioDecoder::InitTags(nsTArray& aTags) -{ - GMPAudioDecoder::InitTags(aTags); - aTags.AppendElement(NS_ConvertUTF16toUTF8(mProxy->KeySystem())); -} - -nsCString -EMEAudioDecoder::GetNodeId() -{ - return mProxy->GetNodeId(); -} - -} // namespace mozilla diff --git a/dom/media/fmp4/eme/EMEAudioDecoder.h b/dom/media/fmp4/eme/EMEAudioDecoder.h deleted file mode 100644 index 3f3669c5cd..0000000000 --- a/dom/media/fmp4/eme/EMEAudioDecoder.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef EMEAudioDecoder_h_ -#define EMEAudioDecoder_h_ - -#include "GMPAudioDecoder.h" -#include "PlatformDecoderModule.h" - -namespace mozilla { - -class EMEAudioCallbackAdapter : public AudioCallbackAdapter { -public: - explicit EMEAudioCallbackAdapter(MediaDataDecoderCallbackProxy* aCallback) - : AudioCallbackAdapter(aCallback) - {} - - virtual void Error(GMPErr aErr) override; -}; - -class EMEAudioDecoder : public GMPAudioDecoder { -public: - EMEAudioDecoder(CDMProxy* aProxy, - const mp4_demuxer::AudioDecoderConfig& aConfig, - MediaTaskQueue* aTaskQueue, - MediaDataDecoderCallbackProxy* aCallback) - : GMPAudioDecoder(aConfig, aTaskQueue, aCallback, new EMEAudioCallbackAdapter(aCallback)) - , mProxy(aProxy) - { - } - -private: - virtual void InitTags(nsTArray& aTags) override; - virtual nsCString GetNodeId() override; - - nsRefPtr mProxy; -}; - -} // namespace mozilla - -#endif diff --git a/dom/media/fmp4/eme/EMEDecoderModule.cpp b/dom/media/fmp4/eme/EMEDecoderModule.cpp deleted file mode 100644 index 59583f826b..0000000000 --- a/dom/media/fmp4/eme/EMEDecoderModule.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "EMEDecoderModule.h" -#include "EMEAudioDecoder.h" -#include "EMEVideoDecoder.h" -#include "MediaDataDecoderProxy.h" -#include "mozIGoannaMediaPluginService.h" -#include "mozilla/CDMProxy.h" -#include "mozilla/unused.h" -#include "nsServiceManagerUtils.h" - -namespace mozilla { - -class EMEDecryptor : public MediaDataDecoder { - typedef mp4_demuxer::MP4Sample MP4Sample; - -public: - - EMEDecryptor(MediaDataDecoder* aDecoder, - MediaDataDecoderCallback* aCallback, - CDMProxy* aProxy) - : mDecoder(aDecoder) - , mCallback(aCallback) - , mTaskQueue(CreateFlushableMediaDecodeTaskQueue()) - , mProxy(aProxy) - , mSamplesWaitingForKey(new SamplesWaitingForKey(this, mTaskQueue, mProxy)) -#ifdef DEBUG - , mIsShutdown(false) -#endif - { - } - - virtual nsresult Init() override { - MOZ_ASSERT(!mIsShutdown); - nsresult rv = mTaskQueue->SyncDispatch( - NS_NewRunnableMethod(mDecoder, &MediaDataDecoder::Init)); - unused << NS_WARN_IF(NS_FAILED(rv)); - return rv; - } - - class DeliverDecrypted : public DecryptionClient { - public: - DeliverDecrypted(EMEDecryptor* aDecryptor, FlushableMediaTaskQueue* aTaskQueue) - : mDecryptor(aDecryptor) - , mTaskQueue(aTaskQueue) - {} - virtual void Decrypted(GMPErr aResult, - mp4_demuxer::MP4Sample* aSample) override { - if (aResult == GMPNoKeyErr) { - RefPtr task; - task = NS_NewRunnableMethodWithArg(mDecryptor, - &EMEDecryptor::Input, - aSample); - mTaskQueue->Dispatch(task.forget()); - } else if (GMP_FAILED(aResult)) { - if (mDecryptor->mCallback) { - mDecryptor->mCallback->Error(); - } - MOZ_ASSERT(!aSample); - } else { - RefPtr task; - task = NS_NewRunnableMethodWithArg(mDecryptor, - &EMEDecryptor::Decrypted, - aSample); - mTaskQueue->Dispatch(task.forget()); - } - mTaskQueue = nullptr; - mDecryptor = nullptr; - } - private: - nsRefPtr mDecryptor; - nsRefPtr mTaskQueue; - }; - - virtual nsresult Input(MP4Sample* aSample) override { - MOZ_ASSERT(!mIsShutdown); - // We run the PDM on its own task queue. We can't run it on the decode - // task queue, because that calls into Input() in a loop and waits until - // output is delivered. We need to defer some Input() calls while we wait - // for keys to become usable, and once they do we need to dispatch an event - // to run the PDM on the same task queue, but since the decode task queue - // is waiting in MP4Reader::Decode() for output our task would never run. - // So we dispatch tasks to make all calls into the wrapped decoder. - if (mSamplesWaitingForKey->WaitIfKeyNotUsable(aSample)) { - return NS_OK; - } - - mProxy->GetSessionIdsForKeyId(aSample->crypto.key, - aSample->crypto.session_ids); - - mProxy->Decrypt(aSample, new DeliverDecrypted(this, mTaskQueue)); - return NS_OK; - } - - void Decrypted(mp4_demuxer::MP4Sample* aSample) { - MOZ_ASSERT(!mIsShutdown); - nsresult rv = mTaskQueue->Dispatch( - NS_NewRunnableMethodWithArg( - mDecoder, - &MediaDataDecoder::Input, - aSample)); - unused << NS_WARN_IF(NS_FAILED(rv)); - } - - virtual nsresult Flush() override { - MOZ_ASSERT(!mIsShutdown); - nsresult rv = mTaskQueue->SyncDispatch( - NS_NewRunnableMethod( - mDecoder, - &MediaDataDecoder::Flush)); - unused << NS_WARN_IF(NS_FAILED(rv)); - mSamplesWaitingForKey->Flush(); - return rv; - } - - virtual nsresult Drain() override { - MOZ_ASSERT(!mIsShutdown); - nsresult rv = mTaskQueue->Dispatch( - NS_NewRunnableMethod( - mDecoder, - &MediaDataDecoder::Drain)); - unused << NS_WARN_IF(NS_FAILED(rv)); - return rv; - } - - virtual nsresult Shutdown() override { - MOZ_ASSERT(!mIsShutdown); -#ifdef DEBUG - mIsShutdown = true; -#endif - nsresult rv = mTaskQueue->SyncDispatch( - NS_NewRunnableMethod( - mDecoder, - &MediaDataDecoder::Shutdown)); - unused << NS_WARN_IF(NS_FAILED(rv)); - mSamplesWaitingForKey->BreakCycles(); - mSamplesWaitingForKey = nullptr; - mDecoder = nullptr; - mTaskQueue->BeginShutdown(); - mTaskQueue->AwaitShutdownAndIdle(); - mTaskQueue = nullptr; - mProxy = nullptr; - mCallback = nullptr; - return rv; - } - -private: - - nsRefPtr mDecoder; - MediaDataDecoderCallback* mCallback; - nsRefPtr mTaskQueue; - nsRefPtr mProxy; - nsRefPtr mSamplesWaitingForKey; -#ifdef DEBUG - bool mIsShutdown; -#endif -}; - -class EMEMediaDataDecoderProxy : public MediaDataDecoderProxy { -public: - EMEMediaDataDecoderProxy(nsIThread* aProxyThread, MediaDataDecoderCallback* aCallback, CDMProxy* aProxy, FlushableMediaTaskQueue* aTaskQueue) - : MediaDataDecoderProxy(aProxyThread, aCallback) - , mSamplesWaitingForKey(new SamplesWaitingForKey(this, aTaskQueue, aProxy)) - , mProxy(aProxy) - { - } - - virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) override; - virtual nsresult Shutdown() override; - -private: - nsRefPtr mSamplesWaitingForKey; - nsRefPtr mProxy; -}; - -nsresult -EMEMediaDataDecoderProxy::Input(mp4_demuxer::MP4Sample* aSample) -{ - if (mSamplesWaitingForKey->WaitIfKeyNotUsable(aSample)) { - return NS_OK; - } - - mProxy->GetSessionIdsForKeyId(aSample->crypto.key, - aSample->crypto.session_ids); - - return MediaDataDecoderProxy::Input(aSample); -} - -nsresult -EMEMediaDataDecoderProxy::Shutdown() -{ - nsresult rv = MediaDataDecoderProxy::Shutdown(); - - mSamplesWaitingForKey->BreakCycles(); - mSamplesWaitingForKey = nullptr; - mProxy = nullptr; - - return rv; -} - -EMEDecoderModule::EMEDecoderModule(CDMProxy* aProxy, - PlatformDecoderModule* aPDM, - bool aCDMDecodesAudio, - bool aCDMDecodesVideo) - : mProxy(aProxy) - , mPDM(aPDM) - , mCDMDecodesAudio(aCDMDecodesAudio) - , mCDMDecodesVideo(aCDMDecodesVideo) -{ -} - -EMEDecoderModule::~EMEDecoderModule() -{ -} - -static already_AddRefed -CreateDecoderWrapper(MediaDataDecoderCallback* aCallback, CDMProxy* aProxy, FlushableMediaTaskQueue* aTaskQueue) -{ - nsCOMPtr gmpService = do_GetService("@mozilla.org/goanna-media-plugin-service;1"); - if (!gmpService) { - return nullptr; - } - - nsCOMPtr thread; - nsresult rv = gmpService->GetThread(getter_AddRefs(thread)); - if (NS_FAILED(rv)) { - return nullptr; - } - - nsRefPtr decoder(new EMEMediaDataDecoderProxy(thread, aCallback, aProxy, aTaskQueue)); - return decoder.forget(); -} - -already_AddRefed -EMEDecoderModule::CreateVideoDecoder(const VideoDecoderConfig& aConfig, - layers::LayersBackend aLayersBackend, - layers::ImageContainer* aImageContainer, - FlushableMediaTaskQueue* aVideoTaskQueue, - MediaDataDecoderCallback* aCallback) -{ - if (mCDMDecodesVideo && aConfig.crypto.valid) { - nsRefPtr wrapper = CreateDecoderWrapper(aCallback, mProxy, aVideoTaskQueue); - wrapper->SetProxyTarget(new EMEVideoDecoder(mProxy, - aConfig, - aLayersBackend, - aImageContainer, - aVideoTaskQueue, - wrapper->Callback())); - return wrapper.forget(); - } - - nsRefPtr decoder(mPDM->CreateVideoDecoder(aConfig, - aLayersBackend, - aImageContainer, - aVideoTaskQueue, - aCallback)); - if (!decoder) { - return nullptr; - } - - if (!aConfig.crypto.valid) { - return decoder.forget(); - } - - nsRefPtr emeDecoder(new EMEDecryptor(decoder, - aCallback, - mProxy)); - return emeDecoder.forget(); -} - -already_AddRefed -EMEDecoderModule::CreateAudioDecoder(const AudioDecoderConfig& aConfig, - FlushableMediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) -{ - if (mCDMDecodesAudio && aConfig.crypto.valid) { - nsRefPtr wrapper = CreateDecoderWrapper(aCallback, mProxy, aAudioTaskQueue); - wrapper->SetProxyTarget(new EMEAudioDecoder(mProxy, - aConfig, - aAudioTaskQueue, - wrapper->Callback())); - return wrapper.forget(); - } - - nsRefPtr decoder(mPDM->CreateAudioDecoder(aConfig, - aAudioTaskQueue, - aCallback)); - if (!decoder) { - return nullptr; - } - - if (!aConfig.crypto.valid) { - return decoder.forget(); - } - - nsRefPtr emeDecoder(new EMEDecryptor(decoder, - aCallback, - mProxy)); - return emeDecoder.forget(); -} - -bool -EMEDecoderModule::DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig) -{ - return mCDMDecodesVideo && aConfig.crypto.valid; -} - -} // namespace mozilla diff --git a/dom/media/fmp4/eme/EMEDecoderModule.h b/dom/media/fmp4/eme/EMEDecoderModule.h deleted file mode 100644 index e83d5576b0..0000000000 --- a/dom/media/fmp4/eme/EMEDecoderModule.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#if !defined(EMEDecoderModule_h_) -#define EMEDecoderModule_h_ - -#include "PlatformDecoderModule.h" -#include "gmp-decryption.h" - -namespace mozilla { - -class CDMProxy; -class FlushableMediaTaskQueue; - -class EMEDecoderModule : public PlatformDecoderModule { -private: - typedef mp4_demuxer::AudioDecoderConfig AudioDecoderConfig; - typedef mp4_demuxer::VideoDecoderConfig VideoDecoderConfig; - -public: - EMEDecoderModule(CDMProxy* aProxy, - PlatformDecoderModule* aPDM, - bool aCDMDecodesAudio, - bool aCDMDecodesVideo); - - virtual ~EMEDecoderModule(); - - // Decode thread. - virtual already_AddRefed - CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig, - layers::LayersBackend aLayersBackend, - layers::ImageContainer* aImageContainer, - FlushableMediaTaskQueue* aVideoTaskQueue, - MediaDataDecoderCallback* aCallback) override; - - // Decode thread. - virtual already_AddRefed - CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, - FlushableMediaTaskQueue* aAudioTaskQueue, - MediaDataDecoderCallback* aCallback) override; - - virtual bool - DecoderNeedsAVCC(const mp4_demuxer::VideoDecoderConfig& aConfig) override; - -private: - nsRefPtr mProxy; - // Will be null if CDM has decoding capability. - nsRefPtr mPDM; - // We run the PDM on its own task queue. - nsRefPtr mTaskQueue; - bool mCDMDecodesAudio; - bool mCDMDecodesVideo; - -}; - -} // namespace mozilla - -#endif // EMEDecoderModule_h_ diff --git a/dom/media/fmp4/eme/EMEVideoDecoder.cpp b/dom/media/fmp4/eme/EMEVideoDecoder.cpp deleted file mode 100644 index 7694ee466e..0000000000 --- a/dom/media/fmp4/eme/EMEVideoDecoder.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "EMEVideoDecoder.h" -#include "GMPVideoEncodedFrameImpl.h" -#include "mozilla/CDMProxy.h" - -namespace mozilla { - -void -EMEVideoCallbackAdapter::Error(GMPErr aErr) -{ - if (aErr == GMPNoKeyErr) { - // The GMP failed to decrypt a frame due to not having a key. This can - // happen if a key expires or a session is closed during playback. - NS_WARNING("GMP failed to decrypt due to lack of key"); - return; - } - VideoCallbackAdapter::Error(aErr); -} - -void -EMEVideoDecoder::InitTags(nsTArray& aTags) -{ - GMPVideoDecoder::InitTags(aTags); - aTags.AppendElement(NS_ConvertUTF16toUTF8(mProxy->KeySystem())); -} - -nsCString -EMEVideoDecoder::GetNodeId() -{ - return mProxy->GetNodeId(); -} - -GMPUnique::Ptr -EMEVideoDecoder::CreateFrame(mp4_demuxer::MP4Sample* aSample) -{ - GMPUnique::Ptr frame = GMPVideoDecoder::CreateFrame(aSample); - if (frame && aSample->crypto.valid) { - static_cast(frame.get())->InitCrypto(aSample->crypto); - } - return frame; -} - -} // namespace mozilla diff --git a/dom/media/fmp4/eme/EMEVideoDecoder.h b/dom/media/fmp4/eme/EMEVideoDecoder.h deleted file mode 100644 index 7a925328b1..0000000000 --- a/dom/media/fmp4/eme/EMEVideoDecoder.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef EMEVideoDecoder_h_ -#define EMEVideoDecoder_h_ - -#include "GMPVideoDecoder.h" -#include "PlatformDecoderModule.h" - -namespace mozilla { - -class CDMProxy; -class MediaTaskQueue; - -class EMEVideoCallbackAdapter : public VideoCallbackAdapter { -public: - EMEVideoCallbackAdapter(MediaDataDecoderCallbackProxy* aCallback, - VideoInfo aVideoInfo, - layers::ImageContainer* aImageContainer) - : VideoCallbackAdapter(aCallback, aVideoInfo, aImageContainer) - {} - - virtual void Error(GMPErr aErr) override; -}; - -class EMEVideoDecoder : public GMPVideoDecoder { -public: - EMEVideoDecoder(CDMProxy* aProxy, - const mp4_demuxer::VideoDecoderConfig& aConfig, - layers::LayersBackend aLayersBackend, - layers::ImageContainer* aImageContainer, - MediaTaskQueue* aTaskQueue, - MediaDataDecoderCallbackProxy* aCallback) - : GMPVideoDecoder(aConfig, aLayersBackend, aImageContainer, aTaskQueue, aCallback, - new EMEVideoCallbackAdapter(aCallback, VideoInfo(aConfig.display_width, - aConfig.display_height), aImageContainer)) - , mProxy(aProxy) - { - } - -private: - virtual void InitTags(nsTArray& aTags) override; - virtual nsCString GetNodeId() override; - virtual GMPUnique::Ptr CreateFrame(mp4_demuxer::MP4Sample* aSample) override; - - nsRefPtr mProxy; -}; - -} - -#endif // EMEVideoDecoder_h_ diff --git a/dom/media/fmp4/eme/SamplesWaitingForKey.cpp b/dom/media/fmp4/eme/SamplesWaitingForKey.cpp deleted file mode 100644 index 55128327a9..0000000000 --- a/dom/media/fmp4/eme/SamplesWaitingForKey.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "SamplesWaitingForKey.h" -#include "mozilla/CDMProxy.h" -#include "mozilla/CDMCaps.h" - -namespace mozilla { - -SamplesWaitingForKey::SamplesWaitingForKey(MediaDataDecoder* aDecoder, - MediaTaskQueue* aTaskQueue, - CDMProxy* aProxy) - : mMutex("SamplesWaitingForKey") - , mDecoder(aDecoder) - , mTaskQueue(aTaskQueue) - , mProxy(aProxy) -{ -} - -SamplesWaitingForKey::~SamplesWaitingForKey() -{ -} - -bool -SamplesWaitingForKey::WaitIfKeyNotUsable(MP4Sample* aSample) -{ - if (!aSample || !aSample->crypto.valid || !mProxy) { - return false; - } - CDMCaps::AutoLock caps(mProxy->Capabilites()); - const auto& keyid = aSample->crypto.key; - if (!caps.IsKeyUsable(keyid)) { - { - MutexAutoLock lock(mMutex); - mSamples.AppendElement(aSample); - } - caps.NotifyWhenKeyIdUsable(aSample->crypto.key, this); - return true; - } - return false; -} - -void -SamplesWaitingForKey::NotifyUsable(const CencKeyId& aKeyId) -{ - MutexAutoLock lock(mMutex); - size_t i = 0; - while (i < mSamples.Length()) { - if (aKeyId == mSamples[i]->crypto.key) { - RefPtr task; - task = NS_NewRunnableMethodWithArg(mDecoder, - &MediaDataDecoder::Input, - mSamples[i].forget()); - mSamples.RemoveElementAt(i); - mTaskQueue->Dispatch(task.forget()); - } else { - i++; - } - } -} - -void -SamplesWaitingForKey::Flush() -{ - MutexAutoLock lock(mMutex); - mSamples.Clear(); -} - -void -SamplesWaitingForKey::BreakCycles() -{ - MutexAutoLock lock(mMutex); - mDecoder = nullptr; - mTaskQueue = nullptr; - mProxy = nullptr; - mSamples.Clear(); -} - -} // namespace mozilla diff --git a/dom/media/fmp4/eme/SamplesWaitingForKey.h b/dom/media/fmp4/eme/SamplesWaitingForKey.h deleted file mode 100644 index c19b6385dc..0000000000 --- a/dom/media/fmp4/eme/SamplesWaitingForKey.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim:set ts=2 sw=2 sts=2 et cindent: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef SamplesWaitingForKey_h_ -#define SamplesWaitingForKey_h_ - -#include "mp4_demuxer/DecoderData.h" -#include "MediaTaskQueue.h" -#include "PlatformDecoderModule.h" - -namespace mozilla { - -typedef nsTArray CencKeyId; - -class CDMProxy; - -// Encapsulates the task of waiting for the CDMProxy to have the necessary -// keys to decypt a given sample. -class SamplesWaitingForKey { - typedef mp4_demuxer::MP4Sample MP4Sample; -public: - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SamplesWaitingForKey) - - explicit SamplesWaitingForKey(MediaDataDecoder* aDecoder, - MediaTaskQueue* aTaskQueue, - CDMProxy* aProxy); - - // Returns true if we need to wait for a key to become usable. - // Will callback MediaDataDecoder::Input(aSample) on mDecoder once the - // sample is ready to be decrypted. The order of input samples is - // preserved. - bool WaitIfKeyNotUsable(MP4Sample* aSample); - - void NotifyUsable(const CencKeyId& aKeyId); - - void Flush(); - - void BreakCycles(); - -protected: - ~SamplesWaitingForKey(); - -private: - Mutex mMutex; - nsRefPtr mDecoder; - nsRefPtr mTaskQueue; - nsRefPtr mProxy; - nsTArray> mSamples; -}; - -} // namespace mozilla - -#endif // SamplesWaitingForKey_h_ diff --git a/dom/media/fmp4/eme/moz.build b/dom/media/fmp4/eme/moz.build deleted file mode 100644 index 57224c1ef0..0000000000 --- a/dom/media/fmp4/eme/moz.build +++ /dev/null @@ -1,28 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -EXPORTS += [ - 'EMEAudioDecoder.h', - 'EMEDecoderModule.h', - 'EMEVideoDecoder.h', - 'SamplesWaitingForKey.h', -] - -UNIFIED_SOURCES += [ - 'EMEAudioDecoder.cpp', - 'EMEDecoderModule.cpp', - 'EMEVideoDecoder.cpp', - 'SamplesWaitingForKey.cpp', -] - -include('/ipc/chromium/chromium-config.mozbuild') - -FINAL_LIBRARY = 'xul' - -FAIL_ON_WARNINGS = True - -if CONFIG['OS_ARCH'] == 'WINNT': - DEFINES['NOMINMAX'] = True diff --git a/dom/media/fmp4/moz.build b/dom/media/fmp4/moz.build index 2b74fad737..da776d61a4 100644 --- a/dom/media/fmp4/moz.build +++ b/dom/media/fmp4/moz.build @@ -31,9 +31,6 @@ DIRS += ['gmp'] if CONFIG['MOZ_WMF']: DIRS += [ 'wmf' ]; -if CONFIG['MOZ_EME']: - DIRS += ['eme'] - if CONFIG['MOZ_FFMPEG']: EXPORTS += [ 'ffmpeg/FFmpegRuntimeLinker.h', diff --git a/dom/media/fmp4/wmf/WMFDecoderModule.cpp b/dom/media/fmp4/wmf/WMFDecoderModule.cpp index e33a8b5e84..b6033e951d 100644 --- a/dom/media/fmp4/wmf/WMFDecoderModule.cpp +++ b/dom/media/fmp4/wmf/WMFDecoderModule.cpp @@ -16,6 +16,7 @@ #include "nsComponentManagerUtils.h" #include "nsIGfxInfo.h" #include "GfxDriverInfo.h" +#include "nsServiceManagerUtils.h" // for do_GetService namespace mozilla { diff --git a/dom/media/gtest/TestEME.cpp b/dom/media/gtest/TestEME.cpp deleted file mode 100644 index 8565dcaafe..0000000000 --- a/dom/media/gtest/TestEME.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public -* License, v. 2.0. If a copy of the MPL was not distributed with this -* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "gtest/gtest.h" -#include "mozilla/EMEUtils.h" - -using namespace std; -using namespace mozilla; - -struct ParseKeySystemTestCase { - const char16_t* mInputKeySystemString; - int32_t mOutCDMVersion; - bool mShouldPass; -}; - -const ParseKeySystemTestCase ParseKeySystemTests[] = { - { - MOZ_UTF16("org.w3.clearkey"), - NO_CDM_VERSION, - true, - }, { - MOZ_UTF16("org.w3.clearkey.123"), - 123, - true, - }, { - MOZ_UTF16("org.w3.clearkey.-1"), - NO_CDM_VERSION, - false, - }, { - MOZ_UTF16("org.w3.clearkey.NaN"), - NO_CDM_VERSION, - false, - }, { - MOZ_UTF16("org.w3.clearkey.0"), - 0, - true, - }, { - MOZ_UTF16("org.w3.clearkey.123567890123567890123567890123567890123567890"), - NO_CDM_VERSION, - false, - }, { - MOZ_UTF16("org.w3.clearkey.0.1"), - NO_CDM_VERSION, - false, - } -}; - -TEST(EME, EMEParseKeySystem) { - const nsAutoString clearkey(MOZ_UTF16("org.w3.clearkey")); - for (const ParseKeySystemTestCase& test : ParseKeySystemTests) { - nsAutoString keySystem; - int32_t version; - bool rv = ParseKeySystem(nsDependentString(test.mInputKeySystemString), - keySystem, - version); - EXPECT_EQ(rv, test.mShouldPass) << "parse should succeed if expected to"; - if (!test.mShouldPass) { - continue; - } - EXPECT_TRUE(keySystem.Equals(clearkey)) << NS_ConvertUTF16toUTF8(keySystem).get(); //"should extract expected keysystem" << ; - EXPECT_EQ(test.mOutCDMVersion, version) << "should extract expected version"; - } -} diff --git a/dom/media/gtest/moz.build b/dom/media/gtest/moz.build index bd9de5cb6d..edf81018f7 100644 --- a/dom/media/gtest/moz.build +++ b/dom/media/gtest/moz.build @@ -15,11 +15,6 @@ SOURCES += [ 'TestWebMBuffered.cpp', ] -if CONFIG['MOZ_EME']: - SOURCES += [ - 'TestEME.cpp', - ] - if CONFIG['MOZ_WEBM_ENCODER']: SOURCES += [ 'TestVideoTrackEncoder.cpp', diff --git a/dom/media/mediasource/MediaSourceDecoder.cpp b/dom/media/mediasource/MediaSourceDecoder.cpp index 5e752ea548..4ed1edc84d 100644 --- a/dom/media/mediasource/MediaSourceDecoder.cpp +++ b/dom/media/mediasource/MediaSourceDecoder.cpp @@ -296,19 +296,6 @@ MediaSourceDecoder::GetMozDebugReaderData(nsAString& aString) mReader->GetMozDebugReaderData(aString); } -#ifdef MOZ_EME -nsresult -MediaSourceDecoder::SetCDMProxy(CDMProxy* aProxy) -{ - nsresult rv = MediaDecoder::SetCDMProxy(aProxy); - NS_ENSURE_SUCCESS(rv, rv); - rv = mReader->SetCDMProxy(aProxy); - NS_ENSURE_SUCCESS(rv, rv); - - return NS_OK; -} -#endif - bool MediaSourceDecoder::IsActiveReader(MediaDecoderReader* aReader) { diff --git a/dom/media/mediasource/MediaSourceDecoder.h b/dom/media/mediasource/MediaSourceDecoder.h index b7ecd613e5..eae671581a 100644 --- a/dom/media/mediasource/MediaSourceDecoder.h +++ b/dom/media/mediasource/MediaSourceDecoder.h @@ -72,10 +72,6 @@ public: // registered TrackBuffers essential for initialization. void PrepareReaderInitialization(); -#ifdef MOZ_EME - virtual nsresult SetCDMProxy(CDMProxy* aProxy) override; -#endif - MediaSourceReader* GetReader() { return mReader; } // Returns true if aReader is a currently active audio or video diff --git a/dom/media/mediasource/MediaSourceReader.cpp b/dom/media/mediasource/MediaSourceReader.cpp index b91adae230..f76c4f6b9e 100644 --- a/dom/media/mediasource/MediaSourceReader.cpp +++ b/dom/media/mediasource/MediaSourceReader.cpp @@ -702,9 +702,6 @@ MediaSourceReader::CreateSubDecoder(const nsACString& aType, int64_t aTimestampO MSE_DEBUG("subdecoder %p subreader %p", decoder.get(), reader.get()); decoder->SetReader(reader); -#ifdef MOZ_EME - decoder->SetCDMProxy(mCDMProxy); -#endif return decoder.forget(); } @@ -1233,22 +1230,6 @@ MediaSourceReader::GetMozDebugReaderData(nsAString& aString) aString += NS_ConvertUTF8toUTF16(result); } -#ifdef MOZ_EME -nsresult -MediaSourceReader::SetCDMProxy(CDMProxy* aProxy) -{ - ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); - - mCDMProxy = aProxy; - for (size_t i = 0; i < mTrackBuffers.Length(); i++) { - nsresult rv = mTrackBuffers[i]->SetCDMProxy(aProxy); - NS_ENSURE_SUCCESS(rv, rv); - } - - return NS_OK; -} -#endif - bool MediaSourceReader::IsActiveReader(MediaDecoderReader* aReader) { diff --git a/dom/media/mediasource/MediaSourceReader.h b/dom/media/mediasource/MediaSourceReader.h index cca4b3171c..dfd75469c9 100644 --- a/dom/media/mediasource/MediaSourceReader.h +++ b/dom/media/mediasource/MediaSourceReader.h @@ -143,10 +143,6 @@ public: // Set the duration of the attached mediasource element. void SetMediaSourceDuration(double aDuration /* seconds */); -#ifdef MOZ_EME - nsresult SetCDMProxy(CDMProxy* aProxy); -#endif - virtual bool IsAsync() const override { return (!GetAudioReader() || GetAudioReader()->IsAsync()) && (!GetVideoReader() || GetVideoReader()->IsAsync()); @@ -246,10 +242,6 @@ private: return aType == MediaData::AUDIO_DATA ? mAudioWaitPromise : mVideoWaitPromise; } -#ifdef MOZ_EME - nsRefPtr mCDMProxy; -#endif - // These are read and written on the decode task queue threads. int64_t mLastAudioTime; int64_t mLastVideoTime; diff --git a/dom/media/mediasource/SourceBufferDecoder.h b/dom/media/mediasource/SourceBufferDecoder.h index 3a748662dd..e8d3327a34 100644 --- a/dom/media/mediasource/SourceBufferDecoder.h +++ b/dom/media/mediasource/SourceBufferDecoder.h @@ -11,9 +11,6 @@ #include "MediaDecoderReader.h" #include "SourceBufferResource.h" #include "mozilla/Attributes.h" -#ifdef MOZ_EME -#include "mozilla/CDMProxy.h" -#endif #include "mozilla/ReentrantMonitor.h" namespace mozilla { @@ -99,28 +96,8 @@ public: mReader = nullptr; } mTaskQueue = nullptr; -#ifdef MOZ_EME - mCDMProxy = nullptr; -#endif } -#ifdef MOZ_EME - virtual nsresult SetCDMProxy(CDMProxy* aProxy) override - { - MOZ_ASSERT(NS_IsMainThread()); - ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); - mCDMProxy = aProxy; - return NS_OK; - } - - virtual CDMProxy* GetCDMProxy() override - { - MOZ_ASSERT(OnDecodeThread() || NS_IsMainThread()); - ReentrantMonitorAutoEnter mon(GetReentrantMonitor()); - return mCDMProxy; - } -#endif - // Given a time convert it into an approximate byte offset from the // cached data. Returns -1 if no such value is computable. int64_t ConvertToByteOffset(double aTime); @@ -163,10 +140,6 @@ private: int64_t mRealMediaDuration; // in seconds double mTrimmedOffset; - -#ifdef MOZ_EME - nsRefPtr mCDMProxy; -#endif }; } // namespace mozilla diff --git a/dom/media/mediasource/TrackBuffer.cpp b/dom/media/mediasource/TrackBuffer.cpp index 04051fc20b..cfa304776f 100644 --- a/dom/media/mediasource/TrackBuffer.cpp +++ b/dom/media/mediasource/TrackBuffer.cpp @@ -869,31 +869,6 @@ TrackBuffer::Decoders() return mInitializedDecoders; } -#ifdef MOZ_EME -nsresult -TrackBuffer::SetCDMProxy(CDMProxy* aProxy) -{ - ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor()); - - for (uint32_t i = 0; i < mDecoders.Length(); ++i) { - nsresult rv = mDecoders[i]->SetCDMProxy(aProxy); - NS_ENSURE_SUCCESS(rv, rv); - } - - for (uint32_t i = 0; i < mWaitingDecoders.Length(); ++i) { - CDMCaps::AutoLock caps(aProxy->Capabilites()); - caps.CallOnMainThreadWhenCapsAvailable( - NS_NewRunnableMethodWithArg(this, - &TrackBuffer::QueueInitializeDecoder, - mWaitingDecoders[i])); - } - - mWaitingDecoders.Clear(); - - return NS_OK; -} -#endif - #if defined(DEBUG) void TrackBuffer::Dump(const char* aPath) diff --git a/dom/media/mediasource/TrackBuffer.h b/dom/media/mediasource/TrackBuffer.h index cd6bb90d1d..ffa0b80af8 100644 --- a/dom/media/mediasource/TrackBuffer.h +++ b/dom/media/mediasource/TrackBuffer.h @@ -110,10 +110,6 @@ public: // currently not playable. bool HasOnlyIncompleteMedia(); -#ifdef MOZ_EME - nsresult SetCDMProxy(CDMProxy* aProxy); -#endif - #if defined(DEBUG) void Dump(const char* aPath); #endif diff --git a/dom/media/moz.build b/dom/media/moz.build index fc6a2332ec..5b63d137db 100644 --- a/dom/media/moz.build +++ b/dom/media/moz.build @@ -53,9 +53,6 @@ if CONFIG['MOZ_OMX_DECODER']: DIRS += ['omx'] DIRS += ['omx/mediaresourcemanager'] -if CONFIG['MOZ_EME']: - DIRS += ['eme'] - TEST_DIRS += [ 'compiledtest', 'gtest', diff --git a/dom/media/webaudio/AudioContext.cpp b/dom/media/webaudio/AudioContext.cpp index 591f802855..ccfeb5a5bf 100644 --- a/dom/media/webaudio/AudioContext.cpp +++ b/dom/media/webaudio/AudioContext.cpp @@ -294,12 +294,6 @@ AudioContext::CreateMediaElementSource(HTMLMediaElement& aMediaElement, aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return nullptr; } -#ifdef MOZ_EME - if (aMediaElement.ContainsRestrictedContent()) { - aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return nullptr; - } -#endif nsRefPtr stream = aMediaElement.MozCaptureStream(aRv); if (aRv.Failed()) { return nullptr; diff --git a/dom/webidl/HTMLMediaElement.webidl b/dom/webidl/HTMLMediaElement.webidl index 944b3d0615..42902459e7 100644 --- a/dom/webidl/HTMLMediaElement.webidl +++ b/dom/webidl/HTMLMediaElement.webidl @@ -141,18 +141,3 @@ partial interface HTMLMediaElement { // because of the audiochannel manager. // * onmozinterruptend - called when the interruption is concluded }; - -#ifdef MOZ_EME -// Encrypted Media Extensions -partial interface HTMLMediaElement { - [Pref="media.eme.apiVisible"] - readonly attribute MediaKeys? mediaKeys; - - // void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457 - [Pref="media.eme.apiVisible", NewObject] - Promise setMediaKeys(MediaKeys? mediaKeys); - - [Pref="media.eme.apiVisible"] - attribute EventHandler onencrypted; -}; -#endif diff --git a/dom/webidl/MediaEncryptedEvent.webidl b/dom/webidl/MediaEncryptedEvent.webidl deleted file mode 100644 index 28d7a17b79..0000000000 --- a/dom/webidl/MediaEncryptedEvent.webidl +++ /dev/null @@ -1,23 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - * - * The origin of this IDL file is - * https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html - * - * Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. - * W3C liability, trademark and document use rules apply. - */ - -[Pref="media.eme.apiVisible", Constructor(DOMString type, optional MediaKeyNeededEventInit eventInitDict)] -interface MediaEncryptedEvent : Event { - readonly attribute DOMString initDataType; - [Throws] - readonly attribute ArrayBuffer? initData; -}; - -dictionary MediaKeyNeededEventInit : EventInit { - DOMString initDataType = ""; - ArrayBuffer? initData = null; -}; diff --git a/dom/webidl/MediaKeyError.webidl b/dom/webidl/MediaKeyError.webidl deleted file mode 100644 index d0dde20320..0000000000 --- a/dom/webidl/MediaKeyError.webidl +++ /dev/null @@ -1,19 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - * - * The origin of this IDL file is - * https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html - * - * Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. - * W3C liability, trademark and document use rules apply. - */ - -// According to the spec, "The future of error events and MediaKeyError -// is uncertain." -// https://www.w3.org/Bugs/Public/show_bug.cgi?id=21798 -[Pref="media.eme.apiVisible"] -interface MediaKeyError : Event { - readonly attribute unsigned long systemCode; -}; diff --git a/dom/webidl/MediaKeyMessageEvent.webidl b/dom/webidl/MediaKeyMessageEvent.webidl deleted file mode 100644 index 17bb573ed4..0000000000 --- a/dom/webidl/MediaKeyMessageEvent.webidl +++ /dev/null @@ -1,30 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - * - * The origin of this IDL file is - * https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html - * - * Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. - * W3C liability, trademark and document use rules apply. - */ - -enum MediaKeyMessageType { - "license-request", - "license-renewal", - "license-release", - "individualization-request" -}; - -[Pref="media.eme.apiVisible", Constructor(DOMString type, optional MediaKeyMessageEventInit eventInitDict)] -interface MediaKeyMessageEvent : Event { - readonly attribute MediaKeyMessageType messageType; - [Throws] - readonly attribute ArrayBuffer message; -}; - -dictionary MediaKeyMessageEventInit : EventInit { - MediaKeyMessageType messageType = "license-request"; - ArrayBuffer message; -}; diff --git a/dom/webidl/MediaKeySession.webidl b/dom/webidl/MediaKeySession.webidl deleted file mode 100644 index 2b77e1869a..0000000000 --- a/dom/webidl/MediaKeySession.webidl +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - * - * The origin of this IDL file is - * https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html - * - * Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. - * W3C liability, trademark and document use rules apply. - */ - -[Pref="media.eme.apiVisible"] -interface MediaKeySession : EventTarget { - // error state - readonly attribute MediaKeyError? error; - - // session properties - readonly attribute DOMString keySystem; - readonly attribute DOMString sessionId; - - readonly attribute unrestricted double expiration; - - readonly attribute Promise closed; - - readonly attribute MediaKeyStatusMap keyStatuses; - - [NewObject] - Promise generateRequest(DOMString initDataType, BufferSource initData); - - [NewObject] - Promise load(DOMString sessionId); - - // session operations - [NewObject] - Promise update(BufferSource response); - - [NewObject] - Promise close(); - - [NewObject] - Promise remove(); -}; diff --git a/dom/webidl/MediaKeyStatusMap.webidl b/dom/webidl/MediaKeyStatusMap.webidl deleted file mode 100644 index 4ec865bd5c..0000000000 --- a/dom/webidl/MediaKeyStatusMap.webidl +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - * - * The origin of this IDL file is - * https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html - * - * Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. - * W3C liability, trademark and document use rules apply. - */ - -enum MediaKeyStatus { - "usable", - "expired", - "output-downscaled", - "output-not-allowed", - "internal-error" -}; - -[Pref="media.eme.apiVisible"] -interface MediaKeyStatusMap { - [Throws] - readonly attribute unsigned long size; - - [Throws] - object keys(); - - [Throws] - object values(); - - [Throws] - object entries(); - - // XXX: forEach, @@iterator -}; diff --git a/dom/webidl/MediaKeySystemAccess.webidl b/dom/webidl/MediaKeySystemAccess.webidl deleted file mode 100644 index 33390fef24..0000000000 --- a/dom/webidl/MediaKeySystemAccess.webidl +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - * - * The origin of this IDL file is - * https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html - * - * Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. - * W3C liability, trademark and document use rules apply. - */ - -enum MediaKeysRequirement { - "required", - "optional", - "disallowed" -}; - -dictionary MediaKeySystemOptions { - DOMString initDataType = ""; - DOMString audioType = ""; - DOMString audioCapability = ""; - DOMString videoType = ""; - DOMString videoCapability = ""; - MediaKeysRequirement uniqueidentifier = "optional"; - MediaKeysRequirement stateful = "optional"; -}; - -[Pref="media.eme.apiVisible"] -interface MediaKeySystemAccess { - readonly attribute DOMString keySystem; - [NewObject] - Promise createMediaKeys(); -}; diff --git a/dom/webidl/MediaKeys.webidl b/dom/webidl/MediaKeys.webidl deleted file mode 100644 index ef6622287b..0000000000 --- a/dom/webidl/MediaKeys.webidl +++ /dev/null @@ -1,25 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - * - * The origin of this IDL file is - * https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html - * - * Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. - * W3C liability, trademark and document use rules apply. - */ - -enum IsTypeSupportedResult { "" /* empty string */, "maybe", "probably" }; -enum SessionType { "temporary", "persistent" }; - -[Pref="media.eme.apiVisible"] -interface MediaKeys { - readonly attribute DOMString keySystem; - - [NewObject, Throws] - MediaKeySession createSession(optional SessionType sessionType = "temporary"); - - [NewObject] - Promise setServerCertificate((ArrayBufferView or ArrayBuffer) serverCertificate); -}; diff --git a/dom/webidl/MediaKeysRequestStatus.webidl b/dom/webidl/MediaKeysRequestStatus.webidl deleted file mode 100644 index 1173afedee..0000000000 --- a/dom/webidl/MediaKeysRequestStatus.webidl +++ /dev/null @@ -1,21 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -enum MediaKeySystemStatus { - "available", - "api-disabled", - "cdm-disabled", - "cdm-not-supported", - "cdm-not-installed", - "cdm-insufficient-version", - "cdm-created", - "error" -}; - -dictionary RequestMediaKeySystemAccessNotification { - required DOMString keySystem; - required MediaKeySystemStatus status; -}; diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl index 079a825a68..3bce72e898 100644 --- a/dom/webidl/Navigator.webidl +++ b/dom/webidl/Navigator.webidl @@ -412,15 +412,6 @@ partial interface Navigator { readonly attribute TVManager? tv; }; -#ifdef MOZ_EME -partial interface Navigator { - [Pref="media.eme.apiVisible", NewObject] - Promise - requestMediaKeySystemAccess(DOMString keySystem, - optional sequence supportedConfigurations); -}; -#endif - #ifdef NIGHTLY_BUILD partial interface Navigator { [Func="Navigator::IsE10sEnabled"] diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index e94fb23a93..fd95e3c233 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -808,18 +808,6 @@ if CONFIG['MOZ_BUILD_APP'] in ['browser', 'mobile/android', 'xulrunner']: 'External.webidl', ] -if CONFIG['MOZ_EME']: - WEBIDL_FILES += [ - 'MediaEncryptedEvent.webidl', - 'MediaKeyError.webidl', - 'MediaKeyMessageEvent.webidl', - 'MediaKeys.webidl', - 'MediaKeySession.webidl', - 'MediaKeysRequestStatus.webidl', - 'MediaKeyStatusMap.webidl', - 'MediaKeySystemAccess.webidl', - ] - if CONFIG['MOZ_PAY']: WEBIDL_FILES += [ 'MozPaymentProvider.webidl' diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index f7a9baedd4..a1c9bb6ce6 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -6669,12 +6669,6 @@ nsLayoutUtils::SurfaceFromElement(HTMLVideoElement* aElement, NS_WARN_IF_FALSE((aSurfaceFlags & SFE_PREFER_NO_PREMULTIPLY_ALPHA) == 0, "We can't support non-premultiplied alpha for video!"); -#ifdef MOZ_EME - if (aElement->ContainsRestrictedContent()) { - return result; - } -#endif - uint16_t readyState; if (NS_SUCCEEDED(aElement->GetReadyState(&readyState)) && (readyState == nsIDOMHTMLMediaElement::HAVE_NOTHING ||