diff options
author | Moonchild <moonchild@palemoon.org> | 2023-10-19 18:41:58 +0000 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2023-10-19 18:41:58 +0000 |
commit | 4554cb9929edfe8a62d6352824f27bc9e9a9b89f (patch) | |
tree | 7cc254b4eaa5ae95381737a34133579f4e435ce9 | |
parent | 8f62ed27ebf098888398de741c012b743e6f0ef1 (diff) | |
parent | f2ec6ef34d9f38faed6b0b2f556390976353fef7 (diff) | |
download | uxp-4554cb9929edfe8a62d6352824f27bc9e9a9b89f.tar.gz |
Merge pull request 'Clean up the rest of EME' (#2348) from 2346-EME-cleanup into master
Reviewed-on: https://repo.palemoon.org/MoonchildProductions/UXP/pulls/2348
170 files changed, 12 insertions, 22350 deletions
diff --git a/build/moz.configure/old.configure b/build/moz.configure/old.configure index 0a3b84be7b..492bb94d66 100644 --- a/build/moz.configure/old.configure +++ b/build/moz.configure/old.configure @@ -179,7 +179,6 @@ def old_configure_options(*options): '--enable-directshow', '--enable-dtrace', '--enable-dump-painting', - '--enable-eme', '--enable-elf-hack', '--enable-extensions', '--enable-faststripe', diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 0bf9ccbf45..3a10427b0f 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -91,11 +91,6 @@ #endif #include "mozilla/dom/ContentChild.h" -#ifdef MOZ_EME -#include "mozilla/EMEUtils.h" -#include "mozilla/DetailedPromise.h" -#endif - namespace mozilla { namespace dom { @@ -198,9 +193,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mServiceWorkerContainer) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow) -#ifdef MOZ_EME - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaKeySystemAccessManager) -#endif #ifdef MOZ_GAMEPAD NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGamepadServiceTest) #endif @@ -261,13 +253,6 @@ Navigator::Invalidate() mServiceWorkerContainer = nullptr; -#ifdef MOZ_EME - if (mMediaKeySystemAccessManager) { - mMediaKeySystemAccessManager->Shutdown(); - mMediaKeySystemAccessManager = nullptr; - } -#endif - #ifdef MOZ_GAMEPAD if (mGamepadServiceTest) { mGamepadServiceTest->Shutdown(); @@ -1504,131 +1489,5 @@ Navigator::GetUserAgent(nsPIDOMWindowInner* aWindow, nsIURI* aURI, return siteSpecificUA->GetUserAgentForURIAndWindow(aURI, aWindow, aUserAgent); } -#ifdef MOZ_EME -static nsCString -ToCString(const nsString& aString) -{ - nsCString str("'"); - str.Append(NS_ConvertUTF16toUTF8(aString)); - str.AppendLiteral("'"); - return str; -} - -static nsCString -ToCString(const MediaKeysRequirement aValue) -{ - nsCString str("'"); - str.Append(nsDependentCString(MediaKeysRequirementValues::strings[static_cast<uint32_t>(aValue)].value)); - str.AppendLiteral("'"); - return str; -} - -static nsCString -ToCString(const MediaKeySystemMediaCapability& aValue) -{ - nsCString str; - str.AppendLiteral("{contentType="); - str.Append(ToCString(aValue.mContentType)); - str.AppendLiteral(", robustness="); - str.Append(ToCString(aValue.mRobustness)); - str.AppendLiteral("}"); - return str; -} - -template<class Type> -static nsCString -ToCString(const Sequence<Type>& aSequence) -{ - nsCString str; - str.AppendLiteral("["); - for (size_t i = 0; i < aSequence.Length(); i++) { - if (i != 0) { - str.AppendLiteral(","); - } - str.Append(ToCString(aSequence[i])); - } - str.AppendLiteral("]"); - return str; -} - -template<class Type> -static nsCString -ToCString(const Optional<Sequence<Type>>& aOptional) -{ - nsCString str; - if (aOptional.WasPassed()) { - str.Append(ToCString(aOptional.Value())); - } else { - str.AppendLiteral("[]"); - } - return str; -} - -static nsCString -ToCString(const MediaKeySystemConfiguration& aConfig) -{ - nsCString str; - str.AppendLiteral("{label="); - str.Append(ToCString(aConfig.mLabel)); - - str.AppendLiteral(", initDataTypes="); - str.Append(ToCString(aConfig.mInitDataTypes)); - - str.AppendLiteral(", audioCapabilities="); - str.Append(ToCString(aConfig.mAudioCapabilities)); - - str.AppendLiteral(", videoCapabilities="); - str.Append(ToCString(aConfig.mVideoCapabilities)); - - str.AppendLiteral(", distinctiveIdentifier="); - str.Append(ToCString(aConfig.mDistinctiveIdentifier)); - - str.AppendLiteral(", persistentState="); - str.Append(ToCString(aConfig.mPersistentState)); - - str.AppendLiteral(", sessionTypes="); - str.Append(ToCString(aConfig.mSessionTypes)); - - str.AppendLiteral("}"); - - return str; -} - -static nsCString -RequestKeySystemAccessLogString(const nsAString& aKeySystem, - const Sequence<MediaKeySystemConfiguration>& aConfigs) -{ - nsCString str; - str.AppendPrintf("Navigator::RequestMediaKeySystemAccess(keySystem='%s' options=", - NS_ConvertUTF16toUTF8(aKeySystem).get()); - str.Append(ToCString(aConfigs)); - str.AppendLiteral(")"); - return str; -} - -already_AddRefed<Promise> -Navigator::RequestMediaKeySystemAccess(const nsAString& aKeySystem, - const Sequence<MediaKeySystemConfiguration>& aConfigs, - ErrorResult& aRv) -{ - EME_LOG("%s", RequestKeySystemAccessLogString(aKeySystem, aConfigs).get()); - - nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow); - RefPtr<DetailedPromise> promise = - DetailedPromise::Create(go, aRv, - NS_LITERAL_CSTRING("navigator.requestMediaKeySystemAccess")); - if (aRv.Failed()) { - return nullptr; - } - - if (!mMediaKeySystemAccessManager) { - mMediaKeySystemAccessManager = new MediaKeySystemAccessManager(mWindow); - } - - mMediaKeySystemAccessManager->Request(promise, aKeySystem, aConfigs); - return promise.forget(); -} -#endif - } // namespace dom } // namespace mozilla diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h index 175940e82d..a61ed10e49 100644 --- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h @@ -18,9 +18,6 @@ #include "nsString.h" #include "nsTArray.h" #include "nsWeakPtr.h" -#ifdef MOZ_EME -#include "mozilla/dom/MediaKeySystemAccessManager.h" -#endif class nsPluginArray; class nsMimeTypeArray; @@ -240,15 +237,6 @@ public: // any, else null. static already_AddRefed<nsPIDOMWindowInner> GetWindowFromGlobal(JSObject* aGlobal); -#ifdef MOZ_EME - already_AddRefed<Promise> - RequestMediaKeySystemAccess(const nsAString& aKeySystem, - const Sequence<MediaKeySystemConfiguration>& aConfig, - ErrorResult& aRv); -private: - RefPtr<MediaKeySystemAccessManager> mMediaKeySystemAccessManager; -#endif - private: virtual ~Navigator(); diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 20fbf72983..9b7a8c2721 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -4206,32 +4206,6 @@ nsDocument::SetScopeObject(nsIGlobalObject* aGlobal) } } -#ifdef MOZ_EME -static void -CheckIfContainsEMEContent(nsISupports* aSupports, void* aContainsEME) -{ - nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aSupports)); - if (domMediaElem) { - nsCOMPtr<nsIContent> content(do_QueryInterface(domMediaElem)); - MOZ_ASSERT(content, "aSupports is not a content"); - HTMLMediaElement* mediaElem = static_cast<HTMLMediaElement*>(content.get()); - bool* contains = static_cast<bool*>(aContainsEME); - if (mediaElem->GetMediaKeys()) { - *contains = true; - } - } -} - -bool -nsDocument::ContainsEMEContent() -{ - bool containsEME = false; - EnumerateActivityObservers(CheckIfContainsEMEContent, - static_cast<void*>(&containsEME)); - return containsEME; -} -#endif // MOZ_EME - static void CheckIfContainsMSEContent(nsISupports* aSupports, void* aContainsMSE) { @@ -8036,14 +8010,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 923fb49ae9..767ab845ba 100644 --- a/dom/base/nsDocument.h +++ b/dom/base/nsDocument.h @@ -1104,10 +1104,6 @@ public: js::ExpandoAndGeneration mExpandoAndGeneration; -#ifdef MOZ_EME - bool ContainsEMEContent(); -#endif - bool ContainsMSEContent(); protected: diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index 1e7eab82b2..d1a618744b 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -5012,13 +5012,6 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage, return; } -#ifdef MOZ_EME - if (video->ContainsRestrictedContent()) { - aError.Throw(NS_ERROR_NOT_AVAILABLE); - return; - } -#endif - uint16_t readyState; if (NS_SUCCEEDED(video->GetReadyState(&readyState)) && readyState < nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA) { diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 6774504a43..9b3b725c67 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -12,9 +12,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" @@ -877,9 +874,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(mSelectedVideoStreamTrack) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingPlayPromises) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END @@ -905,9 +899,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(mSelectedVideoStreamTrack) NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingPlayPromises) NS_IMPL_CYCLE_COLLECTION_UNLINK_END @@ -1160,9 +1151,6 @@ void HTMLMediaElement::AbortExistingLoads() mDownloadSuspendedByCache = false; mMediaInfo = MediaInfo(); mIsEncrypted = false; -#ifdef MOZ_EME - mPendingEncryptedInitData.mInitDatas.Clear(); -#endif mWaitingForKey = NOT_WAITING_FOR_KEY; mSourcePointer = nullptr; @@ -1851,20 +1839,6 @@ nsresult HTMLMediaElement::LoadResource() // Set the media element's CORS mode only when loading a resource mCORSMode = AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)); -#ifdef MOZ_EME - bool isBlob = false; - if (mMediaKeys && - Preferences::GetBool("media.eme.mse-only", true) && - // We only want mediaSource URLs, but they are BlobURL, so we have to - // check the schema and abort if they are not MediaStream or real Blob. - (NS_FAILED(mLoadingSrc->SchemeIs(BLOBURI_SCHEME, &isBlob)) || - !isBlob || - IsMediaStreamURI(mLoadingSrc) || - IsBlobURI(mLoadingSrc))) { - return NS_ERROR_DOM_NOT_SUPPORTED_ERR; - } -#endif - HTMLMediaElement* other = LookupMediaElementURITable(mLoadingSrc); if (other && other->mDecoder) { // Clone it. @@ -2780,11 +2754,6 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded, if (!window) { return nullptr; } -#ifdef MOZ_EME - if (ContainsRestrictedContent()) { - return nullptr; - } -#endif if (!mOutputStreams.IsEmpty() && aGraph != mOutputStreams[0].mStream->GetInputStream()->Graph()) { @@ -3981,25 +3950,6 @@ nsresult HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder, ms.mFinishWhenEnded); } -#ifdef MOZ_EME - if (mMediaKeys) { - if (mMediaKeys->GetCDMProxy()) { - mDecoder->SetCDMProxy(mMediaKeys->GetCDMProxy()); - } else { - // CDM must have crashed. - ShutdownDecoder(); - return NS_ERROR_FAILURE; - } - } - - MediaEventSource<void>* waitingForKeyProducer = mDecoder->WaitingForKeyEvent(); - // Not every decoder will produce waitingForKey events, only add ones that can - if (waitingForKeyProducer) { - mWaitingForKeyListener = waitingForKeyProducer->Connect( - AbstractThread::MainThread(), this, &HTMLMediaElement::CannotDecryptWaitingForKey); - } -#endif - if (mChannelLoader) { mChannelLoader->Done(); mChannelLoader = nullptr; @@ -4454,11 +4404,7 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo, SetMediaInfo(*aInfo); - mIsEncrypted = aInfo->IsEncrypted() -#ifdef MOZ_EME - || mPendingEncryptedInitData.IsEncrypted() -#endif - ; + mIsEncrypted = aInfo->IsEncrypted(); mTags = aTags.forget(); mLoadedDataFired = false; ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA); @@ -4483,14 +4429,6 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo, "Encrypted content not supported outside of MSE")); return; } - -#ifdef MOZ_EME - // Dispatch a distinct 'encrypted' event for each initData we have. - for (const auto& initData : mPendingEncryptedInitData.mInitDatas) { - DispatchEncrypted(initData.mInitData, initData.mType); - } - mPendingEncryptedInitData.mInitDatas.Clear(); -#endif } mWatchManager.ManualNotify(&HTMLMediaElement::UpdateReadyStateInternal); @@ -5424,29 +5362,12 @@ void HTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendE UpdateSrcMediaStreamPlaying(); UpdateAudioChannelPlayingState(); if (aPauseElement) { -#ifdef MOZ_EME - // For EME content, we may 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(); } mEventDeliveryPaused = aSuspendEvents; } else { -#ifdef MOZ_EME - MOZ_ASSERT(!mMediaKeys); -#endif if (mDecoder) { mDecoder->Resume(); if (!mPaused && !mDecoder->IsEnded()) { @@ -5483,17 +5404,6 @@ void HTMLMediaElement::NotifyOwnerDocumentActivityChanged() bool pauseElement = ShouldElementBePaused(); SuspendOrResumeElement(pauseElement, !IsActive()); -#ifdef MOZ_EME - // If the owning document has become inactive we should shutdown the CDM. - if (!OwnerDoc()->IsCurrentActiveDocument() && mMediaKeys) { - mMediaKeys->Shutdown(); - mMediaKeys = nullptr; - if (mDecoder) { - ShutdownDecoder(); - } - } -#endif - AddRemoveSelfReference(); } @@ -6254,236 +6164,6 @@ HTMLMediaElement::OnVisibilityChange(Visibility aNewVisibility) } -#ifdef MOZ_EME -MediaKeys* -HTMLMediaElement::GetMediaKeys() const -{ - return mMediaKeys; -} - -bool -HTMLMediaElement::ContainsRestrictedContent() -{ - return GetMediaKeys() != nullptr; -} - -already_AddRefed<Promise> -HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys, - ErrorResult& aRv) -{ - LOG(LogLevel::Debug, ("%p SetMediaKeys(%p) mMediaKeys=%p mDecoder=%p", - this, aMediaKeys, mMediaKeys.get(), mDecoder.get())); - - if (MozAudioCaptured()) { - aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return nullptr; - } - - nsCOMPtr<nsIGlobalObject> global = - do_QueryInterface(OwnerDoc()->GetInnerWindow()); - if (!global) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - RefPtr<DetailedPromise> promise = DetailedPromise::Create(global, aRv, - NS_LITERAL_CSTRING("HTMLMediaElement.setMediaKeys")); - if (aRv.Failed()) { - return nullptr; - } - - // 1. If mediaKeys and the mediaKeys attribute are the same object, - // return a resolved promise. - if (mMediaKeys == aMediaKeys) { - promise->MaybeResolveWithUndefined(); - return promise.forget(); - } - - // Note: Our attaching code is synchronous, so we can skip the following steps. - - // 2. If this object's attaching media keys value is true, return a - // promise rejected with a new DOMException whose name is InvalidStateError. - // 3. Let this object's attaching media keys value be true. - // 4. Let promise be a new promise. - // 5. Run the following steps in parallel: - - // 5.1 If mediaKeys is not null, CDM instance represented by mediaKeys is - // already in use by another media element, and the user agent is unable - // to use it with this element, let this object's attaching media keys - // value be false and reject promise with a new DOMException whose name - // is QuotaExceededError. - if (aMediaKeys && aMediaKeys->IsBoundToMediaElement()) { - promise->MaybeReject(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR, - NS_LITERAL_CSTRING("MediaKeys object is already bound to another HTMLMediaElement")); - return promise.forget(); - } - - // 5.2 If the mediaKeys attribute is not null, run the following steps: - if (mMediaKeys) { - // 5.2.1 If the user agent or CDM do not support removing the association, - // let this object's attaching media keys value be false and reject promise - // with a new DOMException whose name is NotSupportedError. - - // 5.2.2 If the association cannot currently be removed, let this object's - // attaching media keys value be false and reject promise with a new - // DOMException whose name is InvalidStateError. - if (mDecoder) { - // We don't support swapping out the MediaKeys once we've started to - // setup the playback pipeline. Note this also means we don't need to worry - // about handling disassociating the MediaKeys from the MediaDecoder. - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Can't change MediaKeys on HTMLMediaElement after load has started")); - return promise.forget(); - } - - // 5.2.3 Stop using the CDM instance represented by the mediaKeys attribute - // to decrypt media data and remove the association with the media element. - mMediaKeys->Unbind(); - mMediaKeys = nullptr; - - // 5.2.4 If the preceding step failed, let this object's attaching media - // keys value be false and reject promise with a new DOMException whose - // name is the appropriate error name. - } - - // 5.3. If mediaKeys is not null, run the following steps: - if (aMediaKeys) { - if (!aMediaKeys->GetCDMProxy()) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("CDM crashed before binding MediaKeys object to HTMLMediaElement")); - return promise.forget(); - } - - // 5.3.1 Associate the CDM instance represented by mediaKeys with the - // media element for decrypting media data. - if (NS_FAILED(aMediaKeys->Bind(this))) { - // 5.3.2 If the preceding step failed, run the following steps: - // 5.3.2.1 Set the mediaKeys attribute to null. - mMediaKeys = nullptr; - // 5.3.2.2 Let this object's attaching media keys value be false. - // 5.3.2.3 Reject promise with a new DOMException whose name is - // the appropriate error name. - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Failed to bind MediaKeys object to HTMLMediaElement")); - return promise.forget(); - } - // 5.3.3 Queue a task to run the "Attempt to Resume Playback If Necessary" - // algorithm on the media element. - // Note: Setting the CDMProxy on the MediaDecoder will unblock playback. - if (mDecoder) { - mDecoder->SetCDMProxy(aMediaKeys->GetCDMProxy()); - } - } - - // 5.4 Set the mediaKeys attribute to mediaKeys. - mMediaKeys = aMediaKeys; - - // 5.5 Let this object's attaching media keys value be false. - - // 5.6 Resolve promise. - promise->MaybeResolveWithUndefined(); - - // 6. Return promise. - return promise.forget(); -} - -EventHandlerNonNull* -HTMLMediaElement::GetOnencrypted() -{ - return EventTarget::GetEventHandler(nsGkAtoms::onencrypted, EmptyString()); -} - -void -HTMLMediaElement::SetOnencrypted(EventHandlerNonNull* aCallback) -{ - EventTarget::SetEventHandler(nsGkAtoms::onencrypted, EmptyString(), aCallback); -} - -EventHandlerNonNull* -HTMLMediaElement::GetOnwaitingforkey() -{ - return EventTarget::GetEventHandler(nsGkAtoms::onwaitingforkey, EmptyString()); -} - -void -HTMLMediaElement::SetOnwaitingforkey(EventHandlerNonNull* aCallback) -{ - EventTarget::SetEventHandler(nsGkAtoms::onwaitingforkey, EmptyString(), aCallback); -} - -void -HTMLMediaElement::DispatchEncrypted(const nsTArray<uint8_t>& aInitData, - const nsAString& aInitDataType) -{ - LOG(LogLevel::Debug, - ("%p DispatchEncrypted initDataType='%s'", - this, NS_ConvertUTF16toUTF8(aInitDataType).get())); - - if (mReadyState == nsIDOMHTMLMediaElement::HAVE_NOTHING) { - // Ready state not HAVE_METADATA (yet), don't dispatch encrypted now. - // Queueing for later dispatch in MetadataLoaded. - mPendingEncryptedInitData.AddInitData(aInitDataType, aInitData); - return; - } - - RefPtr<MediaEncryptedEvent> event; - if (IsCORSSameOrigin()) { - event = MediaEncryptedEvent::Constructor(this, aInitDataType, aInitData); - } else { - event = MediaEncryptedEvent::Constructor(this); - } - - RefPtr<AsyncEventDispatcher> asyncDispatcher = - new AsyncEventDispatcher(this, event); - asyncDispatcher->PostDOMEvent(); -} - -bool -HTMLMediaElement::IsEventAttributeName(nsIAtom* aName) -{ - return aName == nsGkAtoms::onencrypted || - nsGenericHTMLElement::IsEventAttributeName(aName); -} - -already_AddRefed<nsIPrincipal> -HTMLMediaElement::GetTopLevelPrincipal() -{ - RefPtr<nsIPrincipal> principal; - nsCOMPtr<nsPIDOMWindowInner> window = OwnerDoc()->GetInnerWindow(); - if (!window) { - return nullptr; - } - // XXXkhuey better hope we always have an outer ... - nsCOMPtr<nsPIDOMWindowOuter> top = window->GetOuterWindow()->GetTop(); - if (!top) { - return nullptr; - } - nsIDocument* doc = top->GetExtantDoc(); - if (!doc) { - return nullptr; - } - principal = doc->NodePrincipal(); - return principal.forget(); -} - -void -HTMLMediaElement::CannotDecryptWaitingForKey() -{ - LOG(LogLevel::Debug, ("%p, CannotDecryptWaitingForKey()", this)); - - // http://w3c.github.io/encrypted-media/#wait-for-key - // 7.3.4 Queue a "waitingforkey" Event - // 1. Let the media element be the specified HTMLMediaElement object. - // 2. If the media element's waiting for key value is true, abort these steps. - if (mWaitingForKey == NOT_WAITING_FOR_KEY) { - // 3. Set the media element's waiting for key value to true. - // Note: algorithm continues in UpdateReadyStateInternal() when all decoded - // data enqueued in the MDSM is consumed. - mWaitingForKey = WAITING_FOR_KEY; - UpdateReadyStateInternal(); - } -} -#endif //MOZ_EME - NS_IMETHODIMP HTMLMediaElement::WindowAudioCaptureChanged(bool aCapture) { MOZ_ASSERT(mAudioChannelAgent); diff --git a/dom/html/HTMLMediaElement.h b/dom/html/HTMLMediaElement.h index bda9924a6f..23799b574c 100644 --- a/dom/html/HTMLMediaElement.h +++ b/dom/html/HTMLMediaElement.h @@ -18,9 +18,6 @@ #include "mozilla/dom/TextTrackManager.h" #include "mozilla/WeakPtr.h" #include "MediaDecoder.h" -#ifdef MOZ_EME -#include "mozilla/dom/MediaKeys.h" -#endif #include "mozilla/StateWatching.h" #include "nsGkAtoms.h" #include "PrincipalChangeObserver.h" @@ -616,30 +613,6 @@ public: // XPCOM MozPreservesPitch() is OK -#ifdef MOZ_EME - MediaKeys* GetMediaKeys() const; - - already_AddRefed<Promise> SetMediaKeys(MediaKeys* mediaKeys, - ErrorResult& aRv); - - mozilla::dom::EventHandlerNonNull* GetOnencrypted(); - void SetOnencrypted(mozilla::dom::EventHandlerNonNull* aCallback); - - mozilla::dom::EventHandlerNonNull* GetOnwaitingforkey(); - void SetOnwaitingforkey(mozilla::dom::EventHandlerNonNull* aCallback); - - void DispatchEncrypted(const nsTArray<uint8_t>& 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<nsIPrincipal> GetTopLevelPrincipal(); - - bool ContainsRestrictedContent(); -#endif // MOZ_EME - void CannotDecryptWaitingForKey(); bool MozAutoplayEnabled() const @@ -1474,11 +1447,6 @@ protected: // Timer used for updating progress events. nsCOMPtr<nsITimer> mProgressTimer; -#ifdef MOZ_EME - // Encrypted Media Extension media keys. - RefPtr<MediaKeys> mMediaKeys; -#endif - // Stores the time at the start of the current 'played' range. double mCurrentPlayRangeStart; @@ -1632,11 +1600,6 @@ protected: // Listens for waitingForKey events from the owned decoder. MediaEventListener mWaitingForKeyListener; -#ifdef MOZ_EME - // Init Data that needs to be sent in 'encrypted' events in MetadataLoaded(). - EncryptionInfo mPendingEncryptedInitData; -#endif - // True if the media's channel's download has been suspended. Watchable<bool> mDownloadSuspendedByCache; diff --git a/dom/media/AbstractMediaDecoder.h b/dom/media/AbstractMediaDecoder.h index c6aa997553..108f7a57f7 100644 --- a/dom/media/AbstractMediaDecoder.h +++ b/dom/media/AbstractMediaDecoder.h @@ -32,9 +32,6 @@ class MediaResource; class ReentrantMonitor; class VideoFrameContainer; class MediaDecoderOwner; -#ifdef MOZ_EME -class CDMProxy; -#endif typedef nsDataHashtable<nsCStringHashKey, nsCString> MetadataTags; diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp index 87454a4686..921ec6bfbf 100644 --- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -388,9 +388,6 @@ MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner) , mLogicalPosition(0.0) , mDuration(std::numeric_limits<double>::quiet_NaN()) , mResourceCallback(new ResourceCallback()) -#ifdef MOZ_EME - , mCDMProxyPromise(mCDMProxyPromiseHolder.Ensure(__func__)) -#endif , mIgnoreProgressData(false) , mInfiniteStream(false) , mOwner(aOwner) @@ -475,10 +472,6 @@ MediaDecoder::Shutdown() mResourceCallback->Disconnect(); -#ifdef MOZ_EME - mCDMProxyPromiseHolder.RejectIfExists(true, __func__); -#endif - DiscardOngoingSeekIfExists(); // This changes the decoder state to SHUTDOWN and does other things @@ -1551,23 +1544,6 @@ MediaDecoder::CanPlayThrough() return GetStatistics().CanPlayThrough(); } -#ifdef MOZ_EME -RefPtr<MediaDecoder::CDMProxyPromise> -MediaDecoder::RequestCDMProxy() const -{ - return mCDMProxyPromise; -} - -void -MediaDecoder::SetCDMProxy(CDMProxy* aProxy) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(aProxy); - - mCDMProxyPromiseHolder.ResolveIfExists(aProxy, __func__); -} -#endif - bool MediaDecoder::IsOpusEnabled() { diff --git a/dom/media/MediaDecoder.h b/dom/media/MediaDecoder.h index 95f211e1c5..d54ba30de5 100644 --- a/dom/media/MediaDecoder.h +++ b/dom/media/MediaDecoder.h @@ -8,10 +8,6 @@ #include "mozilla/Atomics.h" -#ifdef MOZ_EME -#include "mozilla/CDMProxy.h" -#endif - #include "mozilla/MozPromise.h" #include "mozilla/ReentrantMonitor.h" #include "mozilla/StateMirroring.h" @@ -437,16 +433,6 @@ private: MediaDecoderOwner* GetOwner() const override; -#ifdef MOZ_EME - typedef MozPromise<RefPtr<CDMProxy>, bool /* aIgnored */, /* IsExclusive = */ true> CDMProxyPromise; - - // Resolved when a CDMProxy is available and the capabilities are known or - // rejected when this decoder is about to shut down. - RefPtr<CDMProxyPromise> RequestCDMProxy() const; - - void SetCDMProxy(CDMProxy* aProxy); -#endif - static bool IsOggEnabled(); static bool IsOpusEnabled(); static bool IsWaveEnabled(); @@ -596,11 +582,6 @@ private: RefPtr<ResourceCallback> mResourceCallback; -#ifdef MOZ_EME - MozPromiseHolder<CDMProxyPromise> mCDMProxyPromiseHolder; - RefPtr<CDMProxyPromise> mCDMProxyPromise; -#endif - protected: // The promise resolving/rejection is queued as a "micro-task" which will be // handled immediately after the current JS task and before any pending JS diff --git a/dom/media/MediaDecoderOwner.h b/dom/media/MediaDecoderOwner.h index 9be4be3d0b..50a29d0951 100644 --- a/dom/media/MediaDecoderOwner.h +++ b/dom/media/MediaDecoderOwner.h @@ -141,14 +141,6 @@ public: // The decoder owner should call Shutdown() on the decoder and drop the // reference to the decoder to prevent further calls into the decoder. virtual void NotifyXPCOMShutdown() = 0; - -#ifdef MOZ_EME - // Dispatches a "encrypted" event to the HTMLMediaElement, with the - // provided init data. Actual dispatch may be delayed until HAVE_METADATA. - // Main thread only. - virtual void DispatchEncrypted(const nsTArray<uint8_t>& aInitData, - const nsAString& aInitDataType) = 0; -#endif }; } // namespace mozilla diff --git a/dom/media/MediaDecoderReader.h b/dom/media/MediaDecoderReader.h index dd406ed90e..3a3e2ceb82 100644 --- a/dom/media/MediaDecoderReader.h +++ b/dom/media/MediaDecoderReader.h @@ -24,9 +24,6 @@ namespace mozilla { -#ifdef MOZ_EME -class CDMProxy; -#endif class MediaDecoderReader; struct WaitForDataRejectValue @@ -188,10 +185,6 @@ public: // when to call SetIdle(). virtual void SetIdle() {} -#ifdef MOZ_EME - virtual void SetCDMProxy(CDMProxy* aProxy) {} -#endif - // Tell the reader that the data decoded are not for direct playback, so it // can accept more files, in particular those which have more channels than // available in the audio output. diff --git a/dom/media/MediaDecoderReaderWrapper.h b/dom/media/MediaDecoderReaderWrapper.h index a0f845538e..c85c93d44f 100644 --- a/dom/media/MediaDecoderReaderWrapper.h +++ b/dom/media/MediaDecoderReaderWrapper.h @@ -112,10 +112,6 @@ public: return mReader->CanonicalBuffered(); } -#ifdef MOZ_EME - void SetCDMProxy(CDMProxy* aProxy) { mReader->SetCDMProxy(aProxy); } -#endif - void SetVideoBlankDecode(bool aIsBlankDecode); private: diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index b84a76d624..dc82e89e34 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -271,7 +271,6 @@ protected: * * Transition to other states when decoding metadata is done: * SHUTDOWN if failing to decode metadata. - * WAIT_FOR_CDM if the media is encrypted and CDM is not available. * DECODING_FIRSTFRAME otherwise. */ class MediaDecoderStateMachine::DecodeMetadataState @@ -342,60 +341,6 @@ private: }; /** - * Purpose: wait for the CDM to start decoding. - * - * Transition to other states when CDM is ready: - * DECODING_FIRSTFRAME otherwise. - */ -class MediaDecoderStateMachine::WaitForCDMState - : public MediaDecoderStateMachine::StateObject -{ -public: - explicit WaitForCDMState(Master* aPtr) : StateObject(aPtr) {} - - void Enter() - { - MOZ_ASSERT(!mMaster->mVideoDecodeSuspended); - } - - void Exit() override - { - // mPendingSeek is either moved in HandleCDMProxyReady() or should be - // rejected here before transition to SHUTDOWN. - mPendingSeek.RejectIfExists(__func__); - } - - State GetState() const override - { - return DECODER_STATE_WAIT_FOR_CDM; - } - - void HandleCDMProxyReady() override; - - RefPtr<MediaDecoder::SeekPromise> HandleSeek(SeekTarget aTarget) override - { - SLOG("Not Enough Data to seek at this stage, queuing seek"); - mPendingSeek.RejectIfExists(__func__); - mPendingSeek.mTarget = aTarget; - return mPendingSeek.mPromise.Ensure(__func__); - } - - void HandleVideoSuspendTimeout() override - { - // Do nothing since no decoders are created yet. - } - - void HandleResumeVideoDecoding() override - { - // We never suspend video decoding in this state. - MOZ_ASSERT(false, "Shouldn't have suspended video decoding."); - } - -private: - SeekJob mPendingSeek; -}; - -/** * Purpose: release decoder resources to save memory and hardware resources. * * Transition to: @@ -1231,33 +1176,14 @@ DecodeMetadataState::OnMetadataRead(MetadataHolder* aMetadata) mMaster->GetAmpleVideoFrames()); } - // In general, we wait until we know the duration before notifying the decoder. - // However, we notify unconditionally in this case without waiting for the start - // time, since the caller might be waiting on metadataloaded to be fired before - // feeding in the CDM, which we need to decode the first frame (and - // thus get the metadata). We could fix this if we could compute the start - // time by demuxing without necessaring decoding. - bool waitingForCDM = -#ifdef MOZ_EME - mMaster->Info().IsEncrypted() && !mMaster->mCDMProxy; -#else - false; -#endif - mMaster->mNotifyMetadataBeforeFirstFrame = - mMaster->mDuration.Ref().isSome() || waitingForCDM; + mMaster->mDuration.Ref().isSome(); if (mMaster->mNotifyMetadataBeforeFirstFrame) { mMaster->EnqueueLoadedMetadataEvent(); } - if (waitingForCDM) { - // Metadata parsing was successful but we're still waiting for CDM caps - // to become available so that we can build the correct decryptor/decoder. - SetState<WaitForCDMState>(); - } else { - SetState<DecodingFirstFrameState>(SeekJob{}); - } + SetState<DecodingFirstFrameState>(SeekJob{}); } void @@ -1266,9 +1192,6 @@ DormantState::HandlePlayStateChanged(MediaDecoder::PlayState aPlayState) { if (aPlayState == MediaDecoder::PLAY_STATE_PLAYING) { // Exit dormant when the user wants to play. -#ifdef MOZ_EME - MOZ_ASSERT(!Info().IsEncrypted() || mMaster->mCDMProxy); -#endif MOZ_ASSERT(mMaster->mSentFirstFrameLoadedEvent); SetState<SeekingState>(Move(mPendingSeek), EventVisibility::Suppressed); } @@ -1276,13 +1199,6 @@ DormantState::HandlePlayStateChanged(MediaDecoder::PlayState aPlayState) void MediaDecoderStateMachine:: -WaitForCDMState::HandleCDMProxyReady() -{ - SetState<DecodingFirstFrameState>(Move(mPendingSeek)); -} - -void -MediaDecoderStateMachine:: DecodingFirstFrameState::Enter(SeekJob aPendingSeek) { // Handle pending seek. @@ -1581,10 +1497,6 @@ ShutdownState::Enter() // dispose of the timer. master->mVideoDecodeSuspendTimer.Reset(); -#ifdef MOZ_EME - master->mCDMProxyPromise.DisconnectIfExists(); -#endif - if (master->IsPlaying()) { master->StopPlayback(); } @@ -2137,13 +2049,6 @@ nsresult MediaDecoderStateMachine::Init(MediaDecoder* aDecoder) mMediaSink = CreateMediaSink(mAudioCaptured); -#ifdef MOZ_EME - mCDMProxyPromise.Begin(aDecoder->RequestCDMProxy()->Then( - OwnerThread(), __func__, this, - &MediaDecoderStateMachine::OnCDMProxyReady, - &MediaDecoderStateMachine::OnCDMProxyNotReady)); -#endif - nsresult rv = mReader->Init(); NS_ENSURE_SUCCESS(rv, rv); @@ -2267,7 +2172,6 @@ MediaDecoderStateMachine::ToStateStr(State aState) { switch (aState) { case DECODER_STATE_DECODING_METADATA: return "DECODING_METADATA"; - case DECODER_STATE_WAIT_FOR_CDM: return "WAIT_FOR_CDM"; case DECODER_STATE_DORMANT: return "DORMANT"; case DECODER_STATE_DECODING_FIRSTFRAME: return "DECODING_FIRSTFRAME"; case DECODER_STATE_DECODING: return "DECODING"; @@ -3118,25 +3022,6 @@ void MediaDecoderStateMachine::OnMediaSinkAudioError(nsresult aResult) DecodeError(MediaResult(NS_ERROR_DOM_MEDIA_MEDIASINK_ERR, __func__)); } -#ifdef MOZ_EME -void -MediaDecoderStateMachine::OnCDMProxyReady(RefPtr<CDMProxy> aProxy) -{ - MOZ_ASSERT(OnTaskQueue()); - mCDMProxyPromise.Complete(); - mCDMProxy = aProxy; - mReader->SetCDMProxy(aProxy); - mStateObj->HandleCDMProxyReady(); -} - -void -MediaDecoderStateMachine::OnCDMProxyNotReady() -{ - MOZ_ASSERT(OnTaskQueue()); - mCDMProxyPromise.Complete(); -} -#endif - void MediaDecoderStateMachine::SetAudioCaptured(bool aCaptured) { diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index 29da56e57d..ba9034e4fa 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -155,7 +155,6 @@ public: // Enumeration for the valid decoding states enum State { DECODER_STATE_DECODING_METADATA, - DECODER_STATE_WAIT_FOR_CDM, DECODER_STATE_DORMANT, DECODER_STATE_DECODING_FIRSTFRAME, DECODER_STATE_DECODING, @@ -263,7 +262,6 @@ public: private: class StateObject; class DecodeMetadataState; - class WaitForCDMState; class DormantState; class DecodingFirstFrameState; class DecodingState; @@ -767,13 +765,6 @@ private: // Playback will not start when audio is offloading. bool mAudioOffloading; -#ifdef MOZ_EME - void OnCDMProxyReady(RefPtr<CDMProxy> aProxy); - void OnCDMProxyNotReady(); - RefPtr<CDMProxy> mCDMProxy; - MozPromiseRequestHolder<MediaDecoder::CDMProxyPromise> mCDMProxyPromise; -#endif - private: // The buffered range. Mirrored from the decoder thread. Mirror<media::TimeIntervals> mBuffered; diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index a658298e2d..17fa29c080 100644 --- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -3,10 +3,6 @@ * 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/. */ -#ifdef MOZ_EME -#include "mozilla/CDMProxy.h" -#endif - #include "mozilla/ClearOnShutdown.h" #include "mozilla/dom/HTMLMediaElement.h" #include "mozilla/Preferences.h" @@ -351,12 +347,7 @@ MediaFormatReader::DecoderFactory::DoCreateDecoder(TrackType aTrack) if (!mOwner->mPlatform) { mOwner->mPlatform = new PDMFactory(); if (mOwner->IsEncrypted()) { -#ifdef MOZ_EME - MOZ_ASSERT(mOwner->mCDMProxy); - mOwner->mPlatform->SetCDMProxy(mOwner->mCDMProxy); -#else return MediaResult(NS_ERROR_DOM_MEDIA_FATAL_ERR, "EME not supported"); -#endif } } @@ -592,56 +583,6 @@ MediaFormatReader::InitInternal() return NS_OK; } -#ifdef MOZ_EME -class DispatchKeyNeededEvent : public Runnable { -public: - DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder, - nsTArray<uint8_t>& aInitData, - const nsString& aInitDataType) - : mDecoder(aDecoder) - , mInitData(aInitData) - , mInitDataType(aInitDataType) - { - } - NS_IMETHOD Run() override { - // 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: - RefPtr<AbstractMediaDecoder> mDecoder; - nsTArray<uint8_t> mInitData; - nsString mInitDataType; -}; - -void -MediaFormatReader::SetCDMProxy(CDMProxy* aProxy) -{ - RefPtr<CDMProxy> proxy = aProxy; - RefPtr<MediaFormatReader> self = this; - nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () { - MOZ_ASSERT(self->OnTaskQueue()); - self->mCDMProxy = proxy; - }); - OwnerThread()->Dispatch(r.forget()); -} -#endif // MOZ_EME - -bool -MediaFormatReader::IsWaitingOnCDMResource() { - MOZ_ASSERT(OnTaskQueue()); -#ifdef MOZ_EME - return IsEncrypted() && !mCDMProxy; -#else - return false; -#endif -} - RefPtr<MediaDecoderReader::MetadataPromise> MediaFormatReader::AsyncReadMetadata() { @@ -677,9 +618,7 @@ MediaFormatReader::OnDemuxerInitDone(nsresult) UniquePtr<MetadataTags> tags(MakeUnique<MetadataTags>()); RefPtr<PDMFactory> platform; - if (!IsWaitingOnCDMResource()) { - platform = new PDMFactory(); - } + platform = new PDMFactory(); // To decode, we need valid video and a place to put it. bool videoActive = !!mDemuxer->GetNumberTracks(TrackInfo::kVideoTrack) && @@ -746,13 +685,6 @@ MediaFormatReader::OnDemuxerInitDone(nsresult) UniquePtr<EncryptionInfo> crypto = mDemuxer->GetCrypto(); if (mDecoder && crypto && crypto->IsEncrypted()) { -#ifdef MOZ_EME - // Try and dispatch 'encrypted'. Won't go if ready state still HAVE_NOTHING. - for (uint32_t i = 0; i < crypto->mInitDatas.Length(); i++) { - NS_DispatchToMainThread( - new DispatchKeyNeededEvent(mDecoder, crypto->mInitDatas[i].mInitData, crypto->mInitDatas[i].mType)); - } -#endif mInfo.mCrypto = *crypto; } diff --git a/dom/media/MediaFormatReader.h b/dom/media/MediaFormatReader.h index ccd43f0e6a..60ee022264 100644 --- a/dom/media/MediaFormatReader.h +++ b/dom/media/MediaFormatReader.h @@ -19,10 +19,6 @@ namespace mozilla { -#ifdef MOZ_EME -class CDMProxy; -#endif - class MediaFormatReader final : public MediaDecoderReader { typedef TrackInfo::TrackType TrackType; @@ -92,10 +88,6 @@ public: return mTrackDemuxersMayBlock; } -#ifdef MOZ_EME - void SetCDMProxy(CDMProxy* aProxy) override; -#endif - // Returns a string describing the state of the decoder data. // Used for debugging purposes. void GetMozDebugReaderData(nsAString& aString); @@ -108,8 +100,6 @@ private: bool HasVideo() const { return mVideo.mTrackDemuxer; } bool HasAudio() const { return mAudio.mTrackDemuxer; } - bool IsWaitingOnCDMResource(); - bool InitDemuxer(); // Notify the demuxer that new data has been received. // The next queued task calling GetBuffered() is guaranteed to have up to date @@ -587,14 +577,6 @@ private: RefPtr<VideoFrameContainer> mVideoFrameContainer; layers::ImageContainer* GetImageContainer(); -#ifdef MOZ_EME - RefPtr<CDMProxy> mCDMProxy; -#endif - -#ifdef MOZ_GMP - RefPtr<GMPCrashHelper> mCrashHelper; -#endif - void SetBlankDecode(TrackType aTrack, bool aIsBlankDecode); class DecoderFactory; diff --git a/dom/media/MediaPrefs.h b/dom/media/MediaPrefs.h index 675518ba62..40d0971d80 100644 --- a/dom/media/MediaPrefs.h +++ b/dom/media/MediaPrefs.h @@ -102,9 +102,6 @@ private: DECL_MEDIA_PREF("media.gmp.insecure.allow", GMPAllowInsecure, bool, false); DECL_MEDIA_PREF("media.gmp.async-shutdown-timeout", GMPAsyncShutdownTimeout, uint32_t, GMP_DEFAULT_ASYNC_SHUTDOWN_TIMEOUT); #endif -#ifdef MOZ_EME - DECL_MEDIA_PREF("media.eme.enabled", EMEEnabled, bool, false); -#endif DECL_MEDIA_PREF("media.use-blank-decoder", PDMUseBlankDecoder, bool, false); DECL_MEDIA_PREF("media.gpu-process-decoder", PDMUseGPUDecoder, bool, false); #ifdef MOZ_FFMPEG diff --git a/dom/media/eme/CDMCaps.cpp b/dom/media/eme/CDMCaps.cpp deleted file mode 100644 index a30fb59ac8..0000000000 --- a/dom/media/eme/CDMCaps.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#include "mozilla/CDMCaps.h" -#include "mozilla/EMEUtils.h" -#include "nsThreadUtils.h" -#include "SamplesWaitingForKey.h" - -namespace mozilla { - -CDMCaps::CDMCaps() - : mMonitor("CDMCaps") -{ -} - -CDMCaps::~CDMCaps() -{ -} - -void -CDMCaps::Lock() -{ - mMonitor.Lock(); -} - -void -CDMCaps::Unlock() -{ - mMonitor.Unlock(); -} - -CDMCaps::AutoLock::AutoLock(CDMCaps& aInstance) - : mData(aInstance) -{ - mData.Lock(); -} - -CDMCaps::AutoLock::~AutoLock() -{ - mData.Unlock(); -} - -// Keys with MediaKeyStatus::Usable, MediaKeyStatus::Output_downscaled, -// or MediaKeyStatus::Output_restricted status can be used by the CDM -// to decrypt or decrypt-and-decode samples. -static bool -IsUsableStatus(dom::MediaKeyStatus aStatus) -{ - return aStatus == dom::MediaKeyStatus::Usable || - aStatus == dom::MediaKeyStatus::Output_restricted || - aStatus == dom::MediaKeyStatus::Output_downscaled; -} - -bool -CDMCaps::AutoLock::IsKeyUsable(const CencKeyId& aKeyId) -{ - mData.mMonitor.AssertCurrentThreadOwns(); - for (const KeyStatus& keyStatus : mData.mKeyStatuses) { - if (keyStatus.mId == aKeyId) { - return IsUsableStatus(keyStatus.mStatus); - } - } - return false; -} - -bool -CDMCaps::AutoLock::SetKeyStatus(const CencKeyId& aKeyId, - const nsString& aSessionId, - const dom::Optional<dom::MediaKeyStatus>& aStatus) -{ - mData.mMonitor.AssertCurrentThreadOwns(); - - if (!aStatus.WasPassed()) { - // Called from ForgetKeyStatus. - // Return true if the element is found to notify key changes. - return mData.mKeyStatuses.RemoveElement(KeyStatus(aKeyId, - aSessionId, - dom::MediaKeyStatus::Internal_error)); - } - - KeyStatus key(aKeyId, aSessionId, aStatus.Value()); - auto index = mData.mKeyStatuses.IndexOf(key); - if (index != mData.mKeyStatuses.NoIndex) { - if (mData.mKeyStatuses[index].mStatus == aStatus.Value()) { - // No change. - return false; - } - auto oldStatus = mData.mKeyStatuses[index].mStatus; - mData.mKeyStatuses[index].mStatus = aStatus.Value(); - // The old key status was one for which we can decrypt media. We don't - // need to do the "notify usable" step below, as it should be impossible - // for us to have anything waiting on this key to become usable, since it - // was already usable. - if (IsUsableStatus(oldStatus)) { - return true; - } - } else { - mData.mKeyStatuses.AppendElement(key); - } - - // Only call NotifyUsable() for a key when we are going from non-usable - // to usable state. - if (!IsUsableStatus(aStatus.Value())) { - 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)); -} - -void -CDMCaps::AutoLock::GetKeyStatusesForSession(const nsAString& aSessionId, - nsTArray<KeyStatus>& aOutKeyStatuses) -{ - for (const KeyStatus& keyStatus : mData.mKeyStatuses) { - if (keyStatus.mSessionId.Equals(aSessionId)) { - aOutKeyStatuses.AppendElement(keyStatus); - } - } -} - -void -CDMCaps::AutoLock::GetSessionIdsForKeyId(const CencKeyId& aKeyId, - nsTArray<nsCString>& aOutSessionIds) -{ - for (const KeyStatus& keyStatus : mData.mKeyStatuses) { - if (keyStatus.mId == aKeyId) { - aOutSessionIds.AppendElement(NS_ConvertUTF16toUTF8(keyStatus.mSessionId)); - } - } -} - -bool -CDMCaps::AutoLock::RemoveKeysForSession(const nsString& aSessionId) -{ - bool changed = false; - nsTArray<KeyStatus> statuses; - GetKeyStatusesForSession(aSessionId, statuses); - for (const KeyStatus& status : statuses) { - changed |= SetKeyStatus(status.mId, - aSessionId, - dom::Optional<dom::MediaKeyStatus>()); - } - return changed; -} - -} // namespace mozilla diff --git a/dom/media/eme/CDMCaps.h b/dom/media/eme/CDMCaps.h deleted file mode 100644 index cb4b5e2910..0000000000 --- a/dom/media/eme/CDMCaps.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#ifndef CDMCaps_h_ -#define CDMCaps_h_ - -#include "gmp-decryption.h" -#include "nsIThread.h" -#include "nsTArray.h" -#include "nsString.h" -#include "SamplesWaitingForKey.h" - -#include "mozilla/Monitor.h" -#include "mozilla/Attributes.h" -#include "mozilla/dom/MediaKeyStatusMapBinding.h" // For MediaKeyStatus -#include "mozilla/dom/BindingDeclarations.h" // For Optional - -namespace mozilla { - -// CDM capabilities; what keys a CDMProxy can use. -// Must be locked to access state. -class CDMCaps { -public: - CDMCaps(); - ~CDMCaps(); - - struct KeyStatus { - KeyStatus(const CencKeyId& aId, - const nsString& aSessionId, - dom::MediaKeyStatus 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; - dom::MediaKeyStatus 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(); - - 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, - const dom::Optional<dom::MediaKeyStatus>& aStatus); - - void GetKeyStatusesForSession(const nsAString& aSessionId, - nsTArray<KeyStatus>& aOutKeyStatuses); - - void GetSessionIdsForKeyId(const CencKeyId& aKeyId, - nsTArray<nsCString>& aOutSessionIds); - - // Ensures all keys for a session are marked as 'unknown', i.e. removed. - // Returns true if a key status was changed. - bool RemoveKeysForSession(const nsString& aSessionId); - - // 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(); - - struct WaitForKeys { - WaitForKeys(const CencKeyId& aKeyId, - SamplesWaitingForKey* aListener) - : mKeyId(aKeyId) - , mListener(aListener) - {} - CencKeyId mKeyId; - RefPtr<SamplesWaitingForKey> mListener; - }; - - Monitor mMonitor; - - nsTArray<KeyStatus> mKeyStatuses; - - nsTArray<WaitForKeys> mWaitForKeys; - - // 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.h b/dom/media/eme/CDMProxy.h deleted file mode 100644 index a9e783f506..0000000000 --- a/dom/media/eme/CDMProxy.h +++ /dev/null @@ -1,278 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#ifndef CDMProxy_h_ -#define CDMProxy_h_ - -#include "mozilla/CDMCaps.h" -#include "mozilla/MozPromise.h" - -#include "mozilla/dom/MediaKeyMessageEvent.h" -#include "mozilla/dom/MediaKeys.h" - -#include "nsIThread.h" - -namespace mozilla { -class MediaRawData; - -enum DecryptStatus { - Ok = 0, - GenericErr = 1, - NoKeyErr = 2, - AbortedErr = 3, -}; - -struct DecryptResult { - DecryptResult(DecryptStatus aStatus, MediaRawData* aSample) - : mStatus(aStatus) - , mSample(aSample) - {} - DecryptStatus mStatus; - RefPtr<MediaRawData> mSample; -}; - -class CDMKeyInfo { -public: - explicit CDMKeyInfo(const nsTArray<uint8_t>& aKeyId) - : mKeyId(aKeyId) - , mStatus() - {} - - CDMKeyInfo(const nsTArray<uint8_t>& aKeyId, - const dom::Optional<dom::MediaKeyStatus>& aStatus) - : mKeyId(aKeyId) - , mStatus(aStatus.Value()) - {} - - // The copy-ctor and copy-assignment operator for Optional<T> are declared as - // delete, so override CDMKeyInfo copy-ctor for nsTArray operations. - CDMKeyInfo(const CDMKeyInfo& aKeyInfo) - { - mKeyId = aKeyInfo.mKeyId; - if (aKeyInfo.mStatus.WasPassed()) { - mStatus.Construct(aKeyInfo.mStatus.Value()); - } - } - - nsTArray<uint8_t> mKeyId; - dom::Optional<dom::MediaKeyStatus> mStatus; -}; - -typedef int64_t UnixTime; - -// Proxies calls 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 { -protected: - typedef dom::PromiseId PromiseId; - typedef dom::MediaKeySessionType MediaKeySessionType; -public: - - NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0; - NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0; - - typedef MozPromise<DecryptResult, DecryptResult, /* IsExclusive = */ true> DecryptPromise; - - // Main thread only. - CDMProxy(dom::MediaKeys* aKeys, - const nsAString& aKeySystem, - bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired) - : mKeys(aKeys) - , mKeySystem(aKeySystem) - , mDistinctiveIdentifierRequired(aDistinctiveIdentifierRequired) - , mPersistentStateRequired(aPersistentStateRequired) - {} - - // Main thread only. - // Loads the CDM corresponding to mKeySystem. - // Calls MediaKeys::OnCDMCreated() when the CDM is created. - virtual void Init(PromiseId aPromiseId, - const nsAString& aOrigin, - const nsAString& aTopLevelOrigin, - const nsAString& aName, - bool aInPrivateBrowsing) = 0; - - virtual void OnSetDecryptorId(uint32_t aId) {} - - // 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. - virtual void CreateSession(uint32_t aCreateSessionToken, - MediaKeySessionType aSessionType, - PromiseId aPromiseId, - const nsAString& aInitDataType, - nsTArray<uint8_t>& aInitData) = 0; - - // Main thread only. - // Uses the CDM to load a presistent session stored on disk. - // Calls MediaKeys::OnSessionActivated() when session is loaded. - virtual void LoadSession(PromiseId aPromiseId, - const nsAString& aSessionId) = 0; - - // 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. - virtual void SetServerCertificate(PromiseId aPromiseId, - nsTArray<uint8_t>& aCert) = 0; - - // 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. - virtual void UpdateSession(const nsAString& aSessionId, - PromiseId aPromiseId, - nsTArray<uint8_t>& aResponse) = 0; - - // 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(). - virtual void CloseSession(const nsAString& aSessionId, - PromiseId aPromiseId) = 0; - - // Main thread only. - // Removes all data for a persisent session. - // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has - // processed the request. - virtual void RemoveSession(const nsAString& aSessionId, - PromiseId aPromiseId) = 0; - - // Main thread only. - virtual void Shutdown() = 0; - - // Main thread only. - virtual void Terminated() = 0; - - // Threadsafe. - virtual const nsCString& GetNodeId() const = 0; - - // Main thread only. - virtual void OnSetSessionId(uint32_t aCreateSessionToken, - const nsAString& aSessionId) = 0; - - // Main thread only. - virtual void OnResolveLoadSessionPromise(uint32_t aPromiseId, - bool aSuccess) = 0; - - // Main thread only. - virtual void OnSessionMessage(const nsAString& aSessionId, - dom::MediaKeyMessageType aMessageType, - nsTArray<uint8_t>& aMessage) = 0; - - // Main thread only. - virtual void OnExpirationChange(const nsAString& aSessionId, - UnixTime aExpiryTime) = 0; - - // Main thread only. - virtual void OnSessionClosed(const nsAString& aSessionId) = 0; - - // Main thread only. - virtual void OnSessionError(const nsAString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsAString& aMsg) = 0; - - // Main thread only. - virtual void OnRejectPromise(uint32_t aPromiseId, - nsresult aDOMException, - const nsCString& aMsg) = 0; - - virtual RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample) = 0; - - // Owner thread only. - virtual void OnDecrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray<uint8_t>& aDecryptedData) = 0; - - // Reject promise with DOMException corresponding to aExceptionCode. - // Can be called from any thread. - virtual void RejectPromise(PromiseId aId, - nsresult aExceptionCode, - const nsCString& aReason) = 0; - - // Resolves promise with "undefined". - // Can be called from any thread. - virtual void ResolvePromise(PromiseId aId) = 0; - - // Threadsafe. - virtual const nsString& KeySystem() const = 0; - - virtual CDMCaps& Capabilites() = 0; - - // Main thread only. - virtual void OnKeyStatusesChange(const nsAString& aSessionId) = 0; - - virtual void GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId, - nsTArray<nsCString>& aSessionIds) = 0; - -#ifdef DEBUG - virtual bool IsOnOwnerThread() = 0; -#endif - - virtual uint32_t GetDecryptorId() { return 0; } - -protected: - virtual ~CDMProxy() {} - - // Helper to enforce that a raw pointer is only accessed on the main thread. - template<class Type> - 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<dom::MediaKeys> mKeys; - - const nsString mKeySystem; - - // Onwer specified thread. e.g. Gecko Media Plugin thread. - // All interactions with the out-of-process EME plugin must come from this thread. - RefPtr<nsIThread> mOwnerThread; - - nsCString mNodeId; - - CDMCaps mCapabilites; - - const bool mDistinctiveIdentifierRequired; - const bool mPersistentStateRequired; -}; - - -} // namespace mozilla - -#endif // CDMProxy_h_ diff --git a/dom/media/eme/DecryptorProxyCallback.h b/dom/media/eme/DecryptorProxyCallback.h deleted file mode 100644 index c1fcb49a4f..0000000000 --- a/dom/media/eme/DecryptorProxyCallback.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#ifndef DecryptorProxyCallback_h_ -#define DecryptorProxyCallback_h_ - -#include "mozilla/dom/MediaKeyStatusMapBinding.h" // For MediaKeyStatus -#include "mozilla/dom/MediaKeyMessageEventBinding.h" // For MediaKeyMessageType -#include "mozilla/CDMProxy.h" - -class DecryptorProxyCallback { -public: - - virtual ~DecryptorProxyCallback() {} - - virtual void SetDecryptorId(uint32_t aId) = 0; - - virtual void SetSessionId(uint32_t aCreateSessionId, - const nsCString& aSessionId) = 0; - - virtual void ResolveLoadSessionPromise(uint32_t aPromiseId, - bool aSuccess) = 0; - - virtual void ResolvePromise(uint32_t aPromiseId) = 0; - - virtual void RejectPromise(uint32_t aPromiseId, - nsresult aException, - const nsCString& aSessionId) = 0; - - virtual void SessionMessage(const nsCString& aSessionId, - mozilla::dom::MediaKeyMessageType aMessageType, - const nsTArray<uint8_t>& aMessage) = 0; - - virtual void ExpirationChange(const nsCString& aSessionId, - mozilla::UnixTime aExpiryTime) = 0; - - virtual void SessionClosed(const nsCString& aSessionId) = 0; - - virtual void SessionError(const nsCString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsCString& aMessage) = 0; - - virtual void Decrypted(uint32_t aId, - mozilla::DecryptStatus aResult, - const nsTArray<uint8_t>& aDecryptedData) = 0; - - virtual void BatchedKeyStatusChanged(const nsCString& aSessionId, - const nsTArray<mozilla::CDMKeyInfo>& aKeyInfos) = 0; -}; - -#endif diff --git a/dom/media/eme/DetailedPromise.cpp b/dom/media/eme/DetailedPromise.cpp deleted file mode 100644 index 1aa83bef5d..0000000000 --- a/dom/media/eme/DetailedPromise.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#include "DetailedPromise.h" -#include "mozilla/dom/DOMException.h" -#include "nsPrintfCString.h" - -namespace mozilla { -namespace dom { - -DetailedPromise::DetailedPromise(nsIGlobalObject* aGlobal, - const nsACString& aName) - : Promise(aGlobal) - , mName(aName) - , mResponded(false) - , mStartTime(TimeStamp::Now()) -{ -} - -DetailedPromise::~DetailedPromise() -{ -} - -void -DetailedPromise::MaybeReject(nsresult aArg, const nsACString& aReason) -{ - nsPrintfCString msg("%s promise rejected 0x%x '%s'", mName.get(), aArg, - PromiseFlatCString(aReason).get()); - EME_LOG(msg.get()); - - LogToBrowserConsole(NS_ConvertUTF8toUTF16(msg)); - - ErrorResult rv; - rv.ThrowDOMException(aArg, aReason); - Promise::MaybeReject(rv); -} - -void -DetailedPromise::MaybeReject(ErrorResult&, const nsACString& aReason) -{ - NS_NOTREACHED("nsresult expected in MaybeReject()"); -} - -/* static */ already_AddRefed<DetailedPromise> -DetailedPromise::Create(nsIGlobalObject* aGlobal, - ErrorResult& aRv, - const nsACString& aName) -{ - RefPtr<DetailedPromise> promise = new DetailedPromise(aGlobal, aName); - promise->CreateWrapper(nullptr, aRv); - return aRv.Failed() ? nullptr : promise.forget(); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/DetailedPromise.h b/dom/media/eme/DetailedPromise.h deleted file mode 100644 index f7f10aa403..0000000000 --- a/dom/media/eme/DetailedPromise.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#ifndef __DetailedPromise_h__ -#define __DetailedPromise_h__ - -#include "mozilla/dom/Promise.h" -#include "EMEUtils.h" - -namespace mozilla { -namespace dom { - -/* - * This is pretty horrible; bug 1160445. - * Extend Promise to add custom DOMException messages on rejection. - * Get rid of this once we've ironed out EME errors in the wild. - */ -class DetailedPromise : public Promise -{ -public: - static already_AddRefed<DetailedPromise> - Create(nsIGlobalObject* aGlobal, - ErrorResult& aRv, - const nsACString& aName); - - template <typename T> - void MaybeResolve(const T& aArg) - { - EME_LOG("%s promise resolved", mName.get()); - Promise::MaybeResolve<T>(aArg); - } - - void MaybeReject(nsresult aArg) = delete; - void MaybeReject(nsresult aArg, const nsACString& aReason); - - void MaybeReject(ErrorResult& aArg) = delete; - void MaybeReject(ErrorResult&, const nsACString& aReason); - -private: - explicit DetailedPromise(nsIGlobalObject* aGlobal, - const nsACString& aName); - - virtual ~DetailedPromise(); - - enum Status { Succeeded, Failed }; - - nsCString mName; - bool mResponded; - TimeStamp mStartTime; -}; - -} // namespace dom -} // namespace mozilla - -#endif // __DetailedPromise_h__ diff --git a/dom/media/eme/EMEUtils.cpp b/dom/media/eme/EMEUtils.cpp deleted file mode 100644 index 68ef52d83e..0000000000 --- a/dom/media/eme/EMEUtils.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#include "mozilla/EMEUtils.h" - -#include "jsfriendapi.h" // for AutoCheckCannotGC -#include "mozilla/dom/UnionTypes.h" - -namespace mozilla { - -LogModule* GetEMELog() { - static LazyLogModule log("EME"); - return log; -} - -LogModule* GetEMEVerboseLog() { - static LazyLogModule log("EMEV"); - return log; -} - -ArrayData -GetArrayBufferViewOrArrayBufferData(const dom::ArrayBufferViewOrArrayBuffer& aBufferOrView) -{ - MOZ_ASSERT(aBufferOrView.IsArrayBuffer() || aBufferOrView.IsArrayBufferView()); - JS::AutoCheckCannotGC nogc; - if (aBufferOrView.IsArrayBuffer()) { - const dom::ArrayBuffer& buffer = aBufferOrView.GetAsArrayBuffer(); - buffer.ComputeLengthAndData(); - return ArrayData(buffer.Data(), buffer.Length()); - } else if (aBufferOrView.IsArrayBufferView()) { - const dom::ArrayBufferView& bufferview = aBufferOrView.GetAsArrayBufferView(); - bufferview.ComputeLengthAndData(); - return ArrayData(bufferview.Data(), bufferview.Length()); - } - return ArrayData(nullptr, 0); -} - -void -CopyArrayBufferViewOrArrayBufferData(const dom::ArrayBufferViewOrArrayBuffer& aBufferOrView, - nsTArray<uint8_t>& aOutData) -{ - JS::AutoCheckCannotGC nogc; - ArrayData data = GetArrayBufferViewOrArrayBufferData(aBufferOrView); - aOutData.Clear(); - if (!data.IsValid()) { - return; - } - aOutData.AppendElements(data.mData, data.mLength); -} - -void CopyArrayBufferViewOrArrayBufferData(const dom::ArrayBuffer& aBuffer, - nsTArray<uint8_t>& aOutData) { - JS::AutoCheckCannotGC nogc; - aBuffer.ComputeLengthAndData(); - aOutData.Clear(); - aOutData.AppendElements(aBuffer.Data(), aBuffer.Length()); -} - -bool -IsClearkeyKeySystem(const nsAString& aKeySystem) -{ - return !CompareUTF8toUTF16(kEMEKeySystemClearkey, aKeySystem); -} - -bool -IsWidevineKeySystem(const nsAString& aKeySystem) -{ - return !CompareUTF8toUTF16(kEMEKeySystemWidevine, aKeySystem); -} - -nsString -KeySystemToGMPName(const nsAString& aKeySystem) -{ - if (IsClearkeyKeySystem(aKeySystem)) { - return NS_LITERAL_STRING("gmp-clearkey"); - } - if (IsWidevineKeySystem(aKeySystem)) { - return NS_LITERAL_STRING("gmp-widevinecdm"); - } - MOZ_ASSERT(false, "We should only call this for known GMPs"); - return EmptyString(); -} - -} // namespace mozilla diff --git a/dom/media/eme/EMEUtils.h b/dom/media/eme/EMEUtils.h deleted file mode 100644 index aef1574829..0000000000 --- a/dom/media/eme/EMEUtils.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#ifndef EME_LOG_H_ -#define EME_LOG_H_ - -#include "VideoUtils.h" -#include "mozilla/Logging.h" -#include "nsString.h" -#include "nsTArray.h" -#include "mozilla/dom/TypedArray.h" - -namespace mozilla { - -namespace dom { -class ArrayBufferViewOrArrayBuffer; -} - -#ifndef EME_LOG - LogModule* GetEMELog(); - #define EME_LOG(...) MOZ_LOG(GetEMELog(), mozilla::LogLevel::Debug, (__VA_ARGS__)) - #define EME_LOG_ENABLED() MOZ_LOG_TEST(GetEMELog(), mozilla::LogLevel::Debug) -#endif - -#ifndef EME_VERBOSE_LOG - LogModule* GetEMEVerboseLog(); - #define EME_VERBOSE_LOG(...) MOZ_LOG(GetEMEVerboseLog(), mozilla::LogLevel::Debug, (__VA_ARGS__)) -#else - #ifndef EME_LOG - #define EME_LOG(...) - #endif - - #ifndef EME_VERBOSE_LOG - #define EME_VERBOSE_LOG(...) - #endif -#endif - -// Helper function to extract a copy of data coming in from JS in an -// (ArrayBuffer or ArrayBufferView) IDL typed function argument. -// -// Only call this on a properly initialized ArrayBufferViewOrArrayBuffer. -void -CopyArrayBufferViewOrArrayBufferData(const dom::ArrayBufferViewOrArrayBuffer& aBufferOrView, - nsTArray<uint8_t>& aOutData); - -// Overload for ArrayBuffer -void CopyArrayBufferViewOrArrayBufferData(const dom::ArrayBuffer& aBufferOrView, - nsTArray<uint8_t>& aOutData); - -struct ArrayData { - explicit ArrayData(const uint8_t* aData, size_t aLength) - : mData(aData) - , mLength(aLength) - { - } - const uint8_t* mData; - const size_t mLength; - bool IsValid() const { - return mData != nullptr && mLength != 0; - } - bool operator== (const nsTArray<uint8_t>& aOther) const { - return mLength == aOther.Length() && - memcmp(mData, aOther.Elements(), mLength) == 0; - } -}; - -// Helper function to extract data coming in from JS in an -// (ArrayBuffer or ArrayBufferView) IDL typed function argument. -// -// Be *very* careful with this! -// -// Only use returned ArrayData inside the lifetime of the -// ArrayBufferViewOrArrayBuffer; the ArrayData struct does not contain -// a copy of the data! -// -// And do *not* call out to anything that could call into JavaScript, -// while the ArrayData is live, as then all bets about the data not changing -// are off! No calls into JS, no calls into JS-implemented WebIDL or XPIDL, -// nothing. Beware! -// -// Only call this on a properly initialized ArrayBufferViewOrArrayBuffer. -ArrayData -GetArrayBufferViewOrArrayBufferData(const dom::ArrayBufferViewOrArrayBuffer& aBufferOrView); - -nsString -KeySystemToGMPName(const nsAString& aKeySystem); - -bool -IsClearkeyKeySystem(const nsAString& aKeySystem); - -bool -IsWidevineKeySystem(const nsAString& aKeySystem); - -enum CDMType { - eClearKey = 0, - eWidevine = 2, - eUnknown = 3 -}; - -} // 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 a9c83291e9..0000000000 --- a/dom/media/eme/MediaEncryptedEvent.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#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; - mozilla::DropJSObjects(this); -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, JS::Handle<JSObject*> aGivenProto) -{ - return MediaEncryptedEventBinding::Wrap(aCx, this, aGivenProto); -} - -already_AddRefed<MediaEncryptedEvent> -MediaEncryptedEvent::Constructor(EventTarget* aOwner) -{ - RefPtr<MediaEncryptedEvent> e = new MediaEncryptedEvent(aOwner); - e->InitEvent(NS_LITERAL_STRING("encrypted"), false, false); - e->SetTrusted(true); - return e.forget(); -} - -already_AddRefed<MediaEncryptedEvent> -MediaEncryptedEvent::Constructor(EventTarget* aOwner, - const nsAString& aInitDataType, - const nsTArray<uint8_t>& aInitData) -{ - RefPtr<MediaEncryptedEvent> 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> -MediaEncryptedEvent::Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyNeededEventInit& aEventInitDict, - ErrorResult& aRv) -{ - nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports()); - RefPtr<MediaEncryptedEvent> 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(); - nsTArray<uint8_t> initData; - CopyArrayBufferViewOrArrayBufferData(a, initData); - e->mInitData = ArrayBuffer::Create(aGlobal.Context(), initData.Length(), - initData.Elements()); - 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<JSObject*> aData, - ErrorResult& aRv) -{ - if (mRawInitData.Length()) { - mInitData = ArrayBuffer::Create(cx, - this, - mRawInitData.Length(), - mRawInitData.Elements()); - if (!mInitData) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return; - } - mRawInitData.Clear(); - } - 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 c2ac560612..0000000000 --- a/dom/media/eme/MediaEncryptedEvent.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#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<JSObject*> mInitData; - -public: - - JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; - - static already_AddRefed<MediaEncryptedEvent> - Constructor(EventTarget* aOwner); - - static already_AddRefed<MediaEncryptedEvent> - Constructor(EventTarget* aOwner, - const nsAString& aInitDataType, - const nsTArray<uint8_t>& aInitData); - - static already_AddRefed<MediaEncryptedEvent> - Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyNeededEventInit& aEventInitDict, - ErrorResult& aRv); - - void GetInitDataType(nsString& aRetVal) const; - - void GetInitData(JSContext* cx, - JS::MutableHandle<JSObject*> aData, - ErrorResult& aRv); -private: - nsTArray<uint8_t> 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 95e544fe76..0000000000 --- a/dom/media/eme/MediaKeyError.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#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, JS::Handle<JSObject*> aGivenProto) -{ - return MediaKeyErrorBinding::Wrap(aCx, this, aGivenProto); -} - - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeyError.h b/dom/media/eme/MediaKeyError.h deleted file mode 100644 index b1e7aad3ee..0000000000 --- a/dom/media/eme/MediaKeyError.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#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(); - - JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) 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 ee13f8d26f..0000000000 --- a/dom/media/eme/MediaKeyMessageEvent.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#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; - mozilla::DropJSObjects(this); -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, JS::Handle<JSObject*> aGivenProto) -{ - return MediaKeyMessageEventBinding::Wrap(aCx, this, aGivenProto); -} - -already_AddRefed<MediaKeyMessageEvent> -MediaKeyMessageEvent::Constructor(EventTarget* aOwner, - MediaKeyMessageType aMessageType, - const nsTArray<uint8_t>& aMessage) -{ - RefPtr<MediaKeyMessageEvent> 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> -MediaKeyMessageEvent::Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyMessageEventInit& aEventInitDict, - ErrorResult& aRv) -{ - nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports()); - RefPtr<MediaKeyMessageEvent> e = new MediaKeyMessageEvent(owner); - bool trusted = e->Init(owner); - e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable); - nsTArray<uint8_t> initData; - CopyArrayBufferViewOrArrayBufferData(aEventInitDict.mMessage, initData); - e->mMessage = ArrayBuffer::Create(aGlobal.Context(), - initData.Length(), - initData.Elements()); - if (!e->mMessage) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return nullptr; - } - e->mMessageType = aEventInitDict.mMessageType; - e->SetTrusted(trusted); - e->SetComposed(aEventInitDict.mComposed); - return e.forget(); -} - -void -MediaKeyMessageEvent::GetMessage(JSContext* cx, - JS::MutableHandle<JSObject*> aMessage, - ErrorResult& aRv) -{ - if (!mMessage) { - mMessage = ArrayBuffer::Create(cx, - this, - mRawMessage.Length(), - mRawMessage.Elements()); - if (!mMessage) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return; - } - mRawMessage.Clear(); - } - 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 2ec50f4f07..0000000000 --- a/dom/media/eme/MediaKeyMessageEvent.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#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<JSObject*> mMessage; - -public: - virtual MediaKeyMessageEvent* AsMediaKeyMessageEvent(); - - JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; - - static already_AddRefed<MediaKeyMessageEvent> - Constructor(EventTarget* aOwner, - MediaKeyMessageType aMessageType, - const nsTArray<uint8_t>& aMessage); - - static already_AddRefed<MediaKeyMessageEvent> - Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyMessageEventInit& aEventInitDict, - ErrorResult& aRv); - - MediaKeyMessageType MessageType() const { return mMessageType; } - - void GetMessage(JSContext* cx, - JS::MutableHandle<JSObject*> aMessage, - ErrorResult& aRv); - -private: - nsTArray<uint8_t> 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 b5f3fe498b..0000000000 --- a/dom/media/eme/MediaKeySession.cpp +++ /dev/null @@ -1,670 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#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 "mozilla/dom/MediaKeySystemAccess.h" -#include "mozilla/dom/KeyIdsInitDataBinding.h" -#include "nsCycleCollectionParticipant.h" -#include "mozilla/CDMProxy.h" -#include "mozilla/AsyncEventDispatcher.h" -#include "mozilla/Move.h" -#include "nsContentUtils.h" -#include "mozilla/EMEUtils.h" -#include "GMPUtils.h" -#include "nsPrintfCString.h" -#include "psshparser/PsshParser.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; - -// Max length of keyId in EME "keyIds" or WebM init data format, as enforced -// by web platform tests. -static const uint32_t MAX_KEY_ID_LENGTH = 512; - -// Max length of CENC PSSH init data tolerated, as enforced by web -// platform tests. -static const uint32_t MAX_CENC_INIT_DATA_LENGTH = 64 * 1024; - - -MediaKeySession::MediaKeySession(JSContext* aCx, - nsPIDOMWindowInner* aParent, - MediaKeys* aKeys, - const nsAString& aKeySystem, - MediaKeySessionType aSessionType, - ErrorResult& aRv) - : DOMEventTargetHelper(aParent) - , mKeys(aKeys) - , mKeySystem(aKeySystem) - , mSessionType(aSessionType) - , mToken(sMediaKeySessionNum++) - , mIsClosed(false) - , mUninitialized(true) - , mKeyStatusMap(new MediaKeyStatusMap(aParent)) - , mExpiration(JS::GenericNaN()) -{ - EME_LOG("MediaKeySession[%p,''] ctor", this); - - MOZ_ASSERT(aParent); - if (aRv.Failed()) { - return; - } - mClosed = MakePromise(aRv, NS_LITERAL_CSTRING("MediaKeys.createSession")); -} - -void MediaKeySession::SetSessionId(const nsAString& aSessionId) -{ - EME_LOG("MediaKeySession[%p,'%s'] session Id set", - this, NS_ConvertUTF16toUTF8(aSessionId).get()); - - if (NS_WARN_IF(!mSessionId.IsEmpty())) { - return; - } - mSessionId = aSessionId; - mKeys->OnSessionIdReady(this); -} - -MediaKeySession::~MediaKeySession() -{ -} - -MediaKeyError* -MediaKeySession::GetError() const -{ - return mMediaKeyError; -} - -void -MediaKeySession::GetKeySystem(nsString& aOutKeySystem) const -{ - aOutKeySystem.Assign(mKeySystem); -} - -void -MediaKeySession::GetSessionId(nsString& aSessionId) const -{ - aSessionId = GetSessionId(); -} - -const nsString& -MediaKeySession::GetSessionId() const -{ - return mSessionId; -} - -JSObject* -MediaKeySession::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) -{ - return MediaKeySessionBinding::Wrap(aCx, this, aGivenProto); -} - -double -MediaKeySession::Expiration() const -{ - return mExpiration; -} - -Promise* -MediaKeySession::Closed() const -{ - return mClosed; -} - -void -MediaKeySession::UpdateKeyStatusMap() -{ - MOZ_ASSERT(!IsClosed()); - if (!mKeys->GetCDMProxy()) { - return; - } - - nsTArray<CDMCaps::KeyStatus> keyStatuses; - { - CDMCaps::AutoLock caps(mKeys->GetCDMProxy()->Capabilites()); - caps.GetKeyStatusesForSession(mSessionId, keyStatuses); - } - - mKeyStatusMap->Update(keyStatuses); - - if (EME_LOG_ENABLED()) { - nsAutoCString message( - nsPrintfCString("MediaKeySession[%p,'%s'] key statuses change {", - this, NS_ConvertUTF16toUTF8(mSessionId).get())); - using IntegerType = typename std::underlying_type<MediaKeyStatus>::type; - for (const CDMCaps::KeyStatus& status : keyStatuses) { - message.Append(nsPrintfCString(" (%s,%s)", ToBase64(status.mId).get(), - MediaKeyStatusValues::strings[static_cast<IntegerType>(status.mStatus)].value)); - } - message.Append(" }"); - EME_LOG(message.get()); - } -} - -MediaKeyStatusMap* -MediaKeySession::KeyStatuses() const -{ - return mKeyStatusMap; -} - -// The user agent MUST thoroughly validate the Initialization Data before -// passing it to the CDM. This includes verifying that the length and -// values of fields are reasonable, verifying that values are within -// reasonable limits, and stripping irrelevant, unsupported, or unknown -// data or fields. It is RECOMMENDED that user agents pre-parse, sanitize, -// and/or generate a fully sanitized version of the Initialization Data. -// If the Initialization Data format specified by initDataType supports -// multiple entries, the user agent SHOULD remove entries that are not -// needed by the CDM. The user agent MUST NOT re-order entries within -// the Initialization Data. -static bool -ValidateInitData(const nsTArray<uint8_t>& aInitData, const nsAString& aInitDataType) -{ - if (aInitDataType.LowerCaseEqualsLiteral("webm")) { - // WebM initData consists of a single keyId. Ensure it's of reasonable length. - return aInitData.Length() <= MAX_KEY_ID_LENGTH; - } else if (aInitDataType.LowerCaseEqualsLiteral("cenc")) { - // Limit initData to less than 64KB. - if (aInitData.Length() > MAX_CENC_INIT_DATA_LENGTH) { - return false; - } - std::vector<std::vector<uint8_t>> keyIds; - return ParseCENCInitData(aInitData.Elements(), aInitData.Length(), keyIds); - } else if (aInitDataType.LowerCaseEqualsLiteral("keyids")) { - if (aInitData.Length() > MAX_KEY_ID_LENGTH) { - return false; - } - // Ensure that init data matches the expected JSON format. - mozilla::dom::KeyIdsInitData keyIds; - nsString json; - nsDependentCSubstring raw(reinterpret_cast<const char*>(aInitData.Elements()), aInitData.Length()); - if (NS_FAILED(nsContentUtils::ConvertStringFromEncoding(NS_LITERAL_CSTRING("UTF-8"), raw, json))) { - return false; - } - if (!keyIds.Init(json)) { - return false; - } - if (keyIds.mKids.Length() == 0) { - return false; - } - for (const auto& kid : keyIds.mKids) { - if (kid.IsEmpty()) { - return false; - } - } - } - return true; -} - -// Generates a license request based on the initData. A message of type -// "license-request" or "individualization-request" will always be queued -// if the algorithm succeeds and the promise is resolved. -already_AddRefed<Promise> -MediaKeySession::GenerateRequest(const nsAString& aInitDataType, - const ArrayBufferViewOrArrayBuffer& aInitData, - ErrorResult& aRv) -{ - RefPtr<DetailedPromise> promise(MakePromise(aRv, - NS_LITERAL_CSTRING("MediaKeySession.generateRequest"))); - if (aRv.Failed()) { - return nullptr; - } - - // If this object is closed, return a promise rejected with an InvalidStateError. - if (IsClosed()) { - EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() failed, closed", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Session is closed in MediaKeySession.generateRequest()")); - return promise.forget(); - } - - // If this object's uninitialized value is false, return a promise rejected - // with an InvalidStateError. - if (!mUninitialized) { - EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() failed, uninitialized", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Session is already initialized in MediaKeySession.generateRequest()")); - return promise.forget(); - } - - // Let this object's uninitialized value be false. - mUninitialized = false; - - // If initDataType is the empty string, return a promise rejected - // with a newly created TypeError. - if (aInitDataType.IsEmpty()) { - promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Empty initDataType passed to MediaKeySession.generateRequest()")); - EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() failed, empty initDataType", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - - // If initData is an empty array, return a promise rejected with - // a newly created TypeError. - nsTArray<uint8_t> data; - CopyArrayBufferViewOrArrayBufferData(aInitData, data); - if (data.IsEmpty()) { - promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Empty initData passed to MediaKeySession.generateRequest()")); - EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() failed, empty initData", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - - // If the Key System implementation represented by this object's - // cdm implementation value does not support initDataType as an - // Initialization Data Type, return a promise rejected with a - // NotSupportedError. String comparison is case-sensitive. - if (!MediaKeySystemAccess::KeySystemSupportsInitDataType(mKeySystem, aInitDataType)) { - promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, - NS_LITERAL_CSTRING("Unsupported initDataType passed to MediaKeySession.generateRequest()")); - EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() failed, unsupported initDataType", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - - // Let init data be a copy of the contents of the initData parameter. - // Note: Handled by the CopyArrayBufferViewOrArrayBufferData call above. - - // Let session type be this object's session type. - - // Let promise be a new promise. - - // Run the following steps in parallel: - - // If the init data is not valid for initDataType, reject promise with - // a newly created TypeError. - if (!ValidateInitData(data, aInitDataType)) { - // If the preceding step failed, reject promise with a newly created TypeError. - promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("initData sanitization failed in MediaKeySession.generateRequest()")); - EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() initData sanitization failed", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - - // Let sanitized init data be a validated and sanitized version of init data. - - // If sanitized init data is empty, reject promise with a NotSupportedError. - - // Note: Remaining steps of generateRequest method continue in CDM. - - // Convert initData to base64 for easier logging. - // Note: CreateSession() Move()s the data out of the array, so we have - // to copy it here. - nsAutoCString base64InitData(ToBase64(data)); - PromiseId pid = mKeys->StorePromise(promise); - mKeys->ConnectPendingPromiseIdWithToken(pid, Token()); - mKeys->GetCDMProxy()->CreateSession(Token(), - mSessionType, - pid, - aInitDataType, data); - - EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() sent, " - "promiseId=%d initData(base64)='%s' initDataType='%s'", - this, - NS_ConvertUTF16toUTF8(mSessionId).get(), - pid, - base64InitData.get(), - NS_ConvertUTF16toUTF8(aInitDataType).get()); - - return promise.forget(); -} - -already_AddRefed<Promise> -MediaKeySession::Load(const nsAString& aSessionId, ErrorResult& aRv) -{ - RefPtr<DetailedPromise> promise(MakePromise(aRv, - NS_LITERAL_CSTRING("MediaKeySession.load"))); - if (aRv.Failed()) { - return nullptr; - } - - // 1. If this object is closed, return a promise rejected with an InvalidStateError. - if (IsClosed()) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Session is closed in MediaKeySession.load()")); - EME_LOG("MediaKeySession[%p,'%s'] Load() failed, closed", - this, NS_ConvertUTF16toUTF8(aSessionId).get()); - return promise.forget(); - } - - // 2.If this object's uninitialized value is false, return a promise rejected - // with an InvalidStateError. - if (!mUninitialized) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Session is already initialized in MediaKeySession.load()")); - EME_LOG("MediaKeySession[%p,'%s'] Load() failed, uninitialized", - this, NS_ConvertUTF16toUTF8(aSessionId).get()); - return promise.forget(); - } - - // 3.Let this object's uninitialized value be false. - mUninitialized = false; - - // 4. If sessionId is the empty string, return a promise rejected with a newly created TypeError. - if (aSessionId.IsEmpty()) { - promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Trying to load a session with empty session ID")); - // "The sessionId parameter is empty." - EME_LOG("MediaKeySession[%p,''] Load() failed, no sessionId", this); - return promise.forget(); - } - - // 5. If the result of running the Is persistent session type? algorithm - // on this object's session type is false, return a promise rejected with - // a newly created TypeError. - if (mSessionType == MediaKeySessionType::Temporary) { - promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Trying to load() into a non-persistent session")); - EME_LOG("MediaKeySession[%p,''] Load() failed, can't load in a non-persistent session", this); - return promise.forget(); - } - - // Note: We don't support persistent sessions in any keysystem, so all calls - // to Load() should reject with a TypeError in the preceding check. Omitting - // implementing the rest of the specified MediaKeySession::Load() algorithm. - - // We now know the sessionId being loaded into this session. Remove the - // session from its owning MediaKey's set of sessions awaiting a sessionId. - RefPtr<MediaKeySession> session(mKeys->GetPendingSession(Token())); - MOZ_ASSERT(session == this, "Session should be awaiting id on its own token"); - - // Associate with the known sessionId. - SetSessionId(aSessionId); - - PromiseId pid = mKeys->StorePromise(promise); - mKeys->GetCDMProxy()->LoadSession(pid, aSessionId); - - EME_LOG("MediaKeySession[%p,'%s'] Load() sent to CDM, promiseId=%d", - this, NS_ConvertUTF16toUTF8(mSessionId).get(), pid); - - return promise.forget(); -} - -already_AddRefed<Promise> -MediaKeySession::Update(const ArrayBufferViewOrArrayBuffer& aResponse, ErrorResult& aRv) -{ - RefPtr<DetailedPromise> promise(MakePromise(aRv, - NS_LITERAL_CSTRING("MediaKeySession.update"))); - if (aRv.Failed()) { - return nullptr; - } - - if (!IsCallable()) { - // If this object's callable value is false, return a promise rejected - // with a new DOMException whose name is InvalidStateError. - EME_LOG("MediaKeySession[%p,''] Update() called before sessionId set by CDM", this); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("MediaKeySession.Update() called before sessionId set by CDM")); - return promise.forget(); - } - - nsTArray<uint8_t> data; - if (IsClosed() || !mKeys->GetCDMProxy()) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Session is closed or was not properly initialized")); - EME_LOG("MediaKeySession[%p,'%s'] Update() failed, session is closed or was not properly initialised.", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - CopyArrayBufferViewOrArrayBufferData(aResponse, data); - if (data.IsEmpty()) { - promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Empty response buffer passed to MediaKeySession.update()")); - EME_LOG("MediaKeySession[%p,'%s'] Update() failed, empty response buffer", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - - - // Convert response to base64 for easier logging. - // Note: UpdateSession() Move()s the data out of the array, so we have - // to copy it here. - nsAutoCString base64Response(ToBase64(data)); - - PromiseId pid = mKeys->StorePromise(promise); - mKeys->GetCDMProxy()->UpdateSession(mSessionId, - pid, - data); - - EME_LOG("MediaKeySession[%p,'%s'] Update() sent to CDM, " - "promiseId=%d Response(base64)='%s'", - this, - NS_ConvertUTF16toUTF8(mSessionId).get(), - pid, - base64Response.get()); - - return promise.forget(); -} - -already_AddRefed<Promise> -MediaKeySession::Close(ErrorResult& aRv) -{ - RefPtr<DetailedPromise> promise(MakePromise(aRv, - NS_LITERAL_CSTRING("MediaKeySession.close"))); - if (aRv.Failed()) { - return nullptr; - } - // 1. Let session be the associated MediaKeySession object. - // 2. If session is closed, return a resolved promise. - if (IsClosed()) { - EME_LOG("MediaKeySession[%p,'%s'] Close() already closed", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - promise->MaybeResolveWithUndefined(); - return promise.forget(); - } - // 3. If session's callable value is false, return a promise rejected - // with an InvalidStateError. - if (!IsCallable()) { - EME_LOG("MediaKeySession[%p,''] Close() called before sessionId set by CDM", this); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("MediaKeySession.Close() called before sessionId set by CDM")); - return promise.forget(); - } - if (!mKeys->GetCDMProxy()) { - EME_LOG("MediaKeySession[%p,'%s'] Close() null CDMProxy", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("MediaKeySession.Close() lost reference to CDM")); - return promise.forget(); - } - // 4. Let promise be a new promise. - PromiseId pid = mKeys->StorePromise(promise); - // 5. Run the following steps in parallel: - // 5.1 Let cdm be the CDM instance represented by session's cdm instance value. - // 5.2 Use cdm to close the session associated with session. - mKeys->GetCDMProxy()->CloseSession(mSessionId, pid); - - EME_LOG("MediaKeySession[%p,'%s'] Close() sent to CDM, promiseId=%d", - this, NS_ConvertUTF16toUTF8(mSessionId).get(), pid); - - // Session Closed algorithm is run when CDM causes us to run OnSessionClosed(). - - // 6. Return promise. - return promise.forget(); -} - -void -MediaKeySession::OnClosed() -{ - if (IsClosed()) { - return; - } - EME_LOG("MediaKeySession[%p,'%s'] session close operation complete.", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - mIsClosed = true; - mKeys->OnSessionClosed(this); - mKeys = nullptr; - mClosed->MaybeResolveWithUndefined(); -} - -bool -MediaKeySession::IsClosed() const -{ - return mIsClosed; -} - -already_AddRefed<Promise> -MediaKeySession::Remove(ErrorResult& aRv) -{ - RefPtr<DetailedPromise> promise(MakePromise(aRv, - NS_LITERAL_CSTRING("MediaKeySession.remove"))); - if (aRv.Failed()) { - return nullptr; - } - if (!IsCallable()) { - // If this object's callable value is false, return a promise rejected - // with a new DOMException whose name is InvalidStateError. - EME_LOG("MediaKeySession[%p,''] Remove() called before sessionId set by CDM", this); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("MediaKeySession.Remove() called before sessionId set by CDM")); - return promise.forget(); - } - if (mSessionType != MediaKeySessionType::Persistent_license) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR, - NS_LITERAL_CSTRING("Calling MediaKeySession.remove() on non-persistent session")); - // "The operation is not supported on session type sessions." - EME_LOG("MediaKeySession[%p,'%s'] Remove() failed, sesion not persisrtent.", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - if (IsClosed() || !mKeys->GetCDMProxy()) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("MediaKeySesison.remove() called but session is not active")); - // "The session is closed." - EME_LOG("MediaKeySession[%p,'%s'] Remove() failed, already session closed.", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - PromiseId pid = mKeys->StorePromise(promise); - mKeys->GetCDMProxy()->RemoveSession(mSessionId, pid); - EME_LOG("MediaKeySession[%p,'%s'] Remove() sent to CDM, promiseId=%d.", - this, NS_ConvertUTF16toUTF8(mSessionId).get(), pid); - - return promise.forget(); -} - -void -MediaKeySession::DispatchKeyMessage(MediaKeyMessageType aMessageType, - const nsTArray<uint8_t>& aMessage) -{ - if (EME_LOG_ENABLED()) { - EME_LOG("MediaKeySession[%p,'%s'] DispatchKeyMessage() type=%s message(base64)='%s'", - this, NS_ConvertUTF16toUTF8(mSessionId).get(), - MediaKeyMessageTypeValues::strings[uint32_t(aMessageType)].value, - ToBase64(aMessage).get()); - } - - RefPtr<MediaKeyMessageEvent> event( - MediaKeyMessageEvent::Constructor(this, aMessageType, aMessage)); - RefPtr<AsyncEventDispatcher> asyncDispatcher = - new AsyncEventDispatcher(this, event); - asyncDispatcher->PostDOMEvent(); -} - -void -MediaKeySession::DispatchKeyError(uint32_t aSystemCode) -{ - EME_LOG("MediaKeySession[%p,'%s'] DispatchKeyError() systemCode=%u.", - this, NS_ConvertUTF16toUTF8(mSessionId).get(), aSystemCode); - - RefPtr<MediaKeyError> event(new MediaKeyError(this, aSystemCode)); - RefPtr<AsyncEventDispatcher> asyncDispatcher = - new AsyncEventDispatcher(this, event); - asyncDispatcher->PostDOMEvent(); -} - -void -MediaKeySession::DispatchKeyStatusesChange() -{ - if (IsClosed()) { - return; - } - - UpdateKeyStatusMap(); - - RefPtr<AsyncEventDispatcher> asyncDispatcher = - new AsyncEventDispatcher(this, NS_LITERAL_STRING("keystatuseschange"), false); - asyncDispatcher->PostDOMEvent(); -} - -uint32_t -MediaKeySession::Token() const -{ - return mToken; -} - -already_AddRefed<DetailedPromise> -MediaKeySession::MakePromise(ErrorResult& aRv, const nsACString& aName) -{ - nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject()); - if (!global) { - NS_WARNING("Passed non-global to MediaKeys ctor!"); - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - return DetailedPromise::Create(global, aRv, aName); -} - -void -MediaKeySession::SetExpiration(double aExpiration) -{ - EME_LOG("MediaKeySession[%p,'%s'] SetExpiry(%lf)", - this, - NS_ConvertUTF16toUTF8(mSessionId).get(), - aExpiration); - mExpiration = aExpiration; -} - -EventHandlerNonNull* -MediaKeySession::GetOnkeystatuseschange() -{ - return GetEventHandler(nsGkAtoms::onkeystatuseschange, EmptyString()); -} - -void -MediaKeySession::SetOnkeystatuseschange(EventHandlerNonNull* aCallback) -{ - SetEventHandler(nsGkAtoms::onkeystatuseschange, EmptyString(), aCallback); -} - -EventHandlerNonNull* -MediaKeySession::GetOnmessage() -{ - return GetEventHandler(nsGkAtoms::onmessage, EmptyString()); -} - -void -MediaKeySession::SetOnmessage(EventHandlerNonNull* aCallback) -{ - SetEventHandler(nsGkAtoms::onmessage, EmptyString(), aCallback); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeySession.h b/dom/media/eme/MediaKeySession.h deleted file mode 100644 index 6b71370469..0000000000 --- a/dom/media/eme/MediaKeySession.h +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#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/DetailedPromise.h" -#include "mozilla/dom/MediaKeySessionBinding.h" -#include "mozilla/dom/MediaKeysBinding.h" -#include "mozilla/dom/MediaKeyMessageEventBinding.h" - -struct JSContext; - -namespace mozilla { -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, - nsPIDOMWindowInner* aParent, - MediaKeys* aKeys, - const nsAString& aKeySystem, - MediaKeySessionType aSessionType, - ErrorResult& aRv); - - void SetSessionId(const nsAString& aSessionId); - - JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) 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<Promise> GenerateRequest(const nsAString& aInitDataType, - const ArrayBufferViewOrArrayBuffer& aInitData, - ErrorResult& aRv); - - already_AddRefed<Promise> Load(const nsAString& aSessionId, - ErrorResult& aRv); - - already_AddRefed<Promise> Update(const ArrayBufferViewOrArrayBuffer& response, - ErrorResult& aRv); - - already_AddRefed<Promise> Close(ErrorResult& aRv); - - already_AddRefed<Promise> Remove(ErrorResult& aRv); - - void DispatchKeyMessage(MediaKeyMessageType aMessageType, - const nsTArray<uint8_t>& aMessage); - - void DispatchKeyError(uint32_t system_code); - - void DispatchKeyStatusesChange(); - - void OnClosed(); - - bool IsClosed() const; - - void SetExpiration(double aExpiry); - - mozilla::dom::EventHandlerNonNull* GetOnkeystatuseschange(); - void SetOnkeystatuseschange(mozilla::dom::EventHandlerNonNull* aCallback); - - mozilla::dom::EventHandlerNonNull* GetOnmessage(); - void SetOnmessage(mozilla::dom::EventHandlerNonNull* aCallback); - - // Process-unique identifier. - uint32_t Token() const; - -private: - ~MediaKeySession(); - - void UpdateKeyStatusMap(); - - bool IsCallable() const { - // The EME spec sets the "callable value" to true whenever the CDM sets - // the sessionId. When the session is initialized, sessionId is empty and - // callable is thus false. - return !mSessionId.IsEmpty(); - } - - already_AddRefed<DetailedPromise> MakePromise(ErrorResult& aRv, - const nsACString& aName); - - RefPtr<DetailedPromise> mClosed; - - RefPtr<MediaKeyError> mMediaKeyError; - RefPtr<MediaKeys> mKeys; - const nsString mKeySystem; - nsString mSessionId; - const MediaKeySessionType mSessionType; - const uint32_t mToken; - bool mIsClosed; - bool mUninitialized; - RefPtr<MediaKeyStatusMap> mKeyStatusMap; - double mExpiration; -}; - -} // namespace dom -} // namespace mozilla - -#endif diff --git a/dom/media/eme/MediaKeyStatusMap.cpp b/dom/media/eme/MediaKeyStatusMap.cpp deleted file mode 100644 index 677fd0db2e..0000000000 --- a/dom/media/eme/MediaKeyStatusMap.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#include "mozilla/dom/MediaKeyStatusMap.h" -#include "nsPIDOMWindow.h" -#include "mozilla/dom/UnionTypes.h" -#include "mozilla/dom/ToJSValue.h" -#include "mozilla/EMEUtils.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_WRAPPERCACHE(MediaKeyStatusMap, mParent) - -MediaKeyStatusMap::MediaKeyStatusMap(nsPIDOMWindowInner* aParent) - : mParent(aParent) -{ -} - -MediaKeyStatusMap::~MediaKeyStatusMap() -{ -} - -JSObject* -MediaKeyStatusMap::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) -{ - return MediaKeyStatusMapBinding::Wrap(aCx, this, aGivenProto); -} - -nsPIDOMWindowInner* -MediaKeyStatusMap::GetParentObject() const -{ - return mParent; -} - -void -MediaKeyStatusMap::Get(JSContext* aCx, - const ArrayBufferViewOrArrayBuffer& aKey, - JS::MutableHandle<JS::Value> aOutValue, - ErrorResult& aOutRv) const -{ - ArrayData keyId = GetArrayBufferViewOrArrayBufferData(aKey); - if (!keyId.IsValid()) { - aOutValue.setUndefined(); - return; - } - for (const KeyStatus& status : mStatuses) { - if (keyId == status.mKeyId) { - bool ok = ToJSValue(aCx, status.mStatus, aOutValue);
- if (!ok) {
- aOutRv.NoteJSContextException(aCx);
- }
- return; - } - } - aOutValue.setUndefined(); -} - -bool -MediaKeyStatusMap::Has(const ArrayBufferViewOrArrayBuffer& aKey) const -{ - ArrayData keyId = GetArrayBufferViewOrArrayBufferData(aKey); - if (!keyId.IsValid()) { - return false; - } - - for (const KeyStatus& status : mStatuses) { - if (keyId == status.mKeyId) { - return true; - } - } - - return false; -} - -uint32_t -MediaKeyStatusMap::GetIterableLength() const -{ - return mStatuses.Length(); -} - -TypedArrayCreator<ArrayBuffer> -MediaKeyStatusMap::GetKeyAtIndex(uint32_t aIndex) const -{ - MOZ_ASSERT(aIndex < GetIterableLength()); - return TypedArrayCreator<ArrayBuffer>(mStatuses[aIndex].mKeyId); -} - -MediaKeyStatus -MediaKeyStatusMap::GetValueAtIndex(uint32_t aIndex) const -{ - MOZ_ASSERT(aIndex < GetIterableLength()); - return mStatuses[aIndex].mStatus; -} - -uint32_t -MediaKeyStatusMap::Size() const -{ - return mStatuses.Length(); -} - -void -MediaKeyStatusMap::Update(const nsTArray<CDMCaps::KeyStatus>& aKeys) -{ - mStatuses.Clear(); - for (const auto& key : aKeys) { - mStatuses.InsertElementSorted(KeyStatus(key.mId, key.mStatus)); - } -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeyStatusMap.h b/dom/media/eme/MediaKeyStatusMap.h deleted file mode 100644 index 8bfbd4d07c..0000000000 --- a/dom/media/eme/MediaKeyStatusMap.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#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 nsPIDOMWindowInner; - -namespace mozilla { -namespace dom { - -class ArrayBufferViewOrArrayBuffer; - -// The MediaKeyStatusMap WebIDL interface; maps a keyId to its status. -// Note that the underlying "map" is stored in an array, since we assume -// that a MediaKeySession won't have many key statuses to report. -class MediaKeyStatusMap final : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaKeyStatusMap) - -public: - explicit MediaKeyStatusMap(nsPIDOMWindowInner* aParent); - -protected: - ~MediaKeyStatusMap(); - -public: - nsPIDOMWindowInner* GetParentObject() const; - - JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; - - void Get(JSContext* aCx, - const ArrayBufferViewOrArrayBuffer& aKey, - JS::MutableHandle<JS::Value> aOutValue, - ErrorResult& aOutRv) const; - bool Has(const ArrayBufferViewOrArrayBuffer& aKey) const; - uint32_t Size() const; - - uint32_t GetIterableLength() const; - TypedArrayCreator<ArrayBuffer> GetKeyAtIndex(uint32_t aIndex) const; - MediaKeyStatus GetValueAtIndex(uint32_t aIndex) const; - - void Update(const nsTArray<CDMCaps::KeyStatus>& keys); - -private: - - nsCOMPtr<nsPIDOMWindowInner> mParent; - - struct KeyStatus { - KeyStatus(const nsTArray<uint8_t>& aKeyId, - MediaKeyStatus aStatus) - : mKeyId(aKeyId) - , mStatus(aStatus) - { - } - bool operator== (const KeyStatus& aOther) const { - return aOther.mKeyId == mKeyId; - } - bool operator<(const KeyStatus& aOther) const { - // Copy chromium and compare keys' bytes. - // Update once https://github.com/w3c/encrypted-media/issues/69 - // is resolved. - const nsTArray<uint8_t>& other = aOther.mKeyId; - const nsTArray<uint8_t>& self = mKeyId; - size_t length = std::min<size_t>(other.Length(), self.Length()); - int cmp = memcmp(self.Elements(), other.Elements(), length); - if (cmp != 0) { - return cmp < 0; - } - return self.Length() <= other.Length(); - } - nsTArray<uint8_t> mKeyId; - MediaKeyStatus mStatus; - }; - - nsTArray<KeyStatus> mStatuses; -}; - -} // namespace dom -} // namespace mozilla - -#endif diff --git a/dom/media/eme/MediaKeySystemAccess.cpp b/dom/media/eme/MediaKeySystemAccess.cpp deleted file mode 100644 index 3c594f9191..0000000000 --- a/dom/media/eme/MediaKeySystemAccess.cpp +++ /dev/null @@ -1,1041 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#include "mozilla/dom/MediaKeySystemAccess.h" -#include "mozilla/dom/MediaKeySystemAccessBinding.h" -#include "mozilla/Preferences.h" -#include "MediaPrefs.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 "mozIGeckoMediaPluginService.h" -#include "VideoUtils.h" -#include "mozilla/Services.h" -#include "nsIObserverService.h" -#include "mozilla/EMEUtils.h" -#include "GMPUtils.h" -#include "nsAppDirectoryServiceDefs.h" -#include "nsDirectoryServiceUtils.h" -#include "nsDirectoryServiceDefs.h" -#include "nsXULAppAPI.h" -#include "gmp-audio-decode.h" -#include "gmp-video-decode.h" -#include "DecoderDoctorDiagnostics.h" -#include "WebMDecoder.h" -#include "mozilla/StaticPtr.h" -#include "mozilla/ClearOnShutdown.h" -#include "nsUnicharUtils.h" -#include "mozilla/dom/MediaSource.h" -#include "DecoderTraits.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(nsPIDOMWindowInner* aParent, - const nsAString& aKeySystem, - const MediaKeySystemConfiguration& aConfig) - : mParent(aParent) - , mKeySystem(aKeySystem) - , mConfig(aConfig) -{ -} - -MediaKeySystemAccess::~MediaKeySystemAccess() -{ -} - -JSObject* -MediaKeySystemAccess::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) -{ - return MediaKeySystemAccessBinding::Wrap(aCx, this, aGivenProto); -} - -nsPIDOMWindowInner* -MediaKeySystemAccess::GetParentObject() const -{ - return mParent; -} - -void -MediaKeySystemAccess::GetKeySystem(nsString& aOutKeySystem) const -{ - aOutKeySystem.Assign(mKeySystem); -} - -void -MediaKeySystemAccess::GetConfiguration(MediaKeySystemConfiguration& aConfig) -{ - aConfig = mConfig; -} - -already_AddRefed<Promise> -MediaKeySystemAccess::CreateMediaKeys(ErrorResult& aRv) -{ - RefPtr<MediaKeys> keys(new MediaKeys(mParent, - mKeySystem, - mConfig)); - return keys->Init(aRv); -} - -static bool -HavePluginForKeySystem(const nsCString& aKeySystem) -{ - bool havePlugin = HaveGMPFor(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR), - { aKeySystem }); - return havePlugin; -} - -static MediaKeySystemStatus -EnsureCDMInstalled(const nsAString& aKeySystem, - nsACString& aOutMessage) -{ - if (!HavePluginForKeySystem(NS_ConvertUTF16toUTF8(aKeySystem))) { - aOutMessage = NS_LITERAL_CSTRING("CDM is not installed"); - return MediaKeySystemStatus::Cdm_not_installed; - } - - return MediaKeySystemStatus::Available; -} - -/* static */ -MediaKeySystemStatus -MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem, - nsACString& aOutMessage) -{ - MOZ_ASSERT(MediaPrefs::EMEEnabled() || IsClearkeyKeySystem(aKeySystem)); - - if (IsClearkeyKeySystem(aKeySystem)) { - return EnsureCDMInstalled(aKeySystem, aOutMessage); - } - - if (IsWidevineKeySystem(aKeySystem)) { - if (Preferences::GetBool("media.gmp-widevinecdm.visible", false)) { - if (!Preferences::GetBool("media.gmp-widevinecdm.enabled", false)) { - aOutMessage = NS_LITERAL_CSTRING("Widevine EME disabled"); - return MediaKeySystemStatus::Cdm_disabled; - } - return EnsureCDMInstalled(aKeySystem, aOutMessage); - } - } - - return MediaKeySystemStatus::Cdm_not_supported; -} - -typedef nsCString EMECodecString; - -static NS_NAMED_LITERAL_CSTRING(EME_CODEC_AAC, "aac"); -static NS_NAMED_LITERAL_CSTRING(EME_CODEC_OPUS, "opus"); -static NS_NAMED_LITERAL_CSTRING(EME_CODEC_VORBIS, "vorbis"); -static NS_NAMED_LITERAL_CSTRING(EME_CODEC_H264, "h264"); -static NS_NAMED_LITERAL_CSTRING(EME_CODEC_VP8, "vp8"); -static NS_NAMED_LITERAL_CSTRING(EME_CODEC_VP9, "vp9"); - -EMECodecString -ToEMEAPICodecString(const nsString& aCodec) -{ - if (IsAACCodecString(aCodec)) { - return EME_CODEC_AAC; - } - if (aCodec.EqualsLiteral("opus")) { - return EME_CODEC_OPUS; - } - if (aCodec.EqualsLiteral("vorbis")) { - return EME_CODEC_VORBIS; - } - if (IsH264CodecString(aCodec)) { - return EME_CODEC_H264; - } - if (IsVP8CodecString(aCodec)) { - return EME_CODEC_VP8; - } - if (IsVP9CodecString(aCodec)) { - return EME_CODEC_VP9; - } - return EmptyCString(); -} - -// A codec can be decrypted-and-decoded by the CDM, or only decrypted -// by the CDM and decoded by Gecko. Not both. -struct KeySystemContainerSupport -{ - bool IsSupported() const - { - return !mCodecsDecoded.IsEmpty() || !mCodecsDecrypted.IsEmpty(); - } - - // CDM decrypts and decodes using a DRM robust decoder, and passes decoded - // samples back to Gecko for rendering. - bool DecryptsAndDecodes(EMECodecString aCodec) const - { - return mCodecsDecoded.Contains(aCodec); - } - - // CDM decrypts and passes the decrypted samples back to Gecko for decoding. - bool Decrypts(EMECodecString aCodec) const - { - return mCodecsDecrypted.Contains(aCodec); - } - - void SetCanDecryptAndDecode(EMECodecString aCodec) - { - // Can't both decrypt and decrypt-and-decode a codec. - MOZ_ASSERT(!Decrypts(aCodec)); - // Prevent duplicates. - MOZ_ASSERT(!DecryptsAndDecodes(aCodec)); - mCodecsDecoded.AppendElement(aCodec); - } - - void SetCanDecrypt(EMECodecString aCodec) - { - // Prevent duplicates. - MOZ_ASSERT(!Decrypts(aCodec)); - // Can't both decrypt and decrypt-and-decode a codec. - MOZ_ASSERT(!DecryptsAndDecodes(aCodec)); - mCodecsDecrypted.AppendElement(aCodec); - } - -private: - nsTArray<EMECodecString> mCodecsDecoded; - nsTArray<EMECodecString> mCodecsDecrypted; -}; - -enum class KeySystemFeatureSupport -{ - Prohibited = 1, - Requestable = 2, - Required = 3, -}; - -struct KeySystemConfig -{ - nsString mKeySystem; - nsTArray<nsString> mInitDataTypes; - KeySystemFeatureSupport mPersistentState = KeySystemFeatureSupport::Prohibited; - KeySystemFeatureSupport mDistinctiveIdentifier = KeySystemFeatureSupport::Prohibited; - nsTArray<MediaKeySessionType> mSessionTypes; - nsTArray<nsString> mVideoRobustness; - nsTArray<nsString> mAudioRobustness; - KeySystemContainerSupport mMP4; - KeySystemContainerSupport mWebM; -}; - -static nsTArray<KeySystemConfig> -GetSupportedKeySystems() -{ - nsTArray<KeySystemConfig> keySystemConfigs; - - { - if (HavePluginForKeySystem(kEMEKeySystemClearkey)) { - KeySystemConfig clearkey; - clearkey.mKeySystem = NS_ConvertUTF8toUTF16(kEMEKeySystemClearkey); - clearkey.mInitDataTypes.AppendElement(NS_LITERAL_STRING("cenc")); - clearkey.mInitDataTypes.AppendElement(NS_LITERAL_STRING("keyids")); - clearkey.mInitDataTypes.AppendElement(NS_LITERAL_STRING("webm")); - clearkey.mPersistentState = KeySystemFeatureSupport::Requestable; - clearkey.mDistinctiveIdentifier = KeySystemFeatureSupport::Prohibited; - clearkey.mSessionTypes.AppendElement(MediaKeySessionType::Temporary); - if (MediaPrefs::ClearKeyPersistentLicenseEnabled()) { - clearkey.mSessionTypes.AppendElement(MediaKeySessionType::Persistent_license); - } -#if defined(XP_WIN) - // Clearkey CDM uses WMF decoders on Windows. - if (WMFDecoderModule::HasAAC()) { - clearkey.mMP4.SetCanDecryptAndDecode(EME_CODEC_AAC); - } else { - clearkey.mMP4.SetCanDecrypt(EME_CODEC_AAC); - } - if (WMFDecoderModule::HasH264()) { - clearkey.mMP4.SetCanDecryptAndDecode(EME_CODEC_H264); - } else { - clearkey.mMP4.SetCanDecrypt(EME_CODEC_H264); - } -#else - clearkey.mMP4.SetCanDecrypt(EME_CODEC_AAC); - clearkey.mMP4.SetCanDecrypt(EME_CODEC_H264); -#endif - clearkey.mWebM.SetCanDecrypt(EME_CODEC_VORBIS); - clearkey.mWebM.SetCanDecrypt(EME_CODEC_OPUS); - clearkey.mWebM.SetCanDecrypt(EME_CODEC_VP8); - clearkey.mWebM.SetCanDecrypt(EME_CODEC_VP9); - keySystemConfigs.AppendElement(Move(clearkey)); - } - } - { - if (HavePluginForKeySystem(kEMEKeySystemWidevine)) { - KeySystemConfig widevine; - widevine.mKeySystem = NS_ConvertUTF8toUTF16(kEMEKeySystemWidevine); - widevine.mInitDataTypes.AppendElement(NS_LITERAL_STRING("cenc")); - widevine.mInitDataTypes.AppendElement(NS_LITERAL_STRING("keyids")); - widevine.mInitDataTypes.AppendElement(NS_LITERAL_STRING("webm")); - widevine.mPersistentState = KeySystemFeatureSupport::Requestable; - widevine.mDistinctiveIdentifier = KeySystemFeatureSupport::Prohibited; - widevine.mSessionTypes.AppendElement(MediaKeySessionType::Temporary); - widevine.mAudioRobustness.AppendElement(NS_LITERAL_STRING("SW_SECURE_CRYPTO")); - widevine.mVideoRobustness.AppendElement(NS_LITERAL_STRING("SW_SECURE_DECODE")); -#if defined(XP_WIN) - // Widevine CDM doesn't include an AAC decoder. So if WMF can't - // decode AAC, and a codec wasn't specified, be conservative - // and reject the MediaKeys request, since our policy is to prevent - // the Adobe GMP's unencrypted AAC decoding path being used to - // decode content decrypted by the Widevine CDM. - if (WMFDecoderModule::HasAAC()) { - widevine.mMP4.SetCanDecrypt(EME_CODEC_AAC); - } -#endif - - widevine.mMP4.SetCanDecryptAndDecode(EME_CODEC_H264); - widevine.mWebM.SetCanDecrypt(EME_CODEC_VORBIS); - widevine.mWebM.SetCanDecrypt(EME_CODEC_OPUS); - widevine.mWebM.SetCanDecryptAndDecode(EME_CODEC_VP8); - widevine.mWebM.SetCanDecryptAndDecode(EME_CODEC_VP9); - keySystemConfigs.AppendElement(Move(widevine)); - } - } - - return keySystemConfigs; -} - -static bool -GetKeySystemConfig(const nsAString& aKeySystem, KeySystemConfig& aOutKeySystemConfig) -{ - for (auto&& config : GetSupportedKeySystems()) { - if (config.mKeySystem.Equals(aKeySystem)) { - aOutKeySystemConfig = mozilla::Move(config); - return true; - } - } - // No matching key system found. - return false; -} - -/* static */ -bool -MediaKeySystemAccess::KeySystemSupportsInitDataType(const nsAString& aKeySystem, - const nsAString& aInitDataType) -{ - KeySystemConfig implementation; - return GetKeySystemConfig(aKeySystem, implementation) && - implementation.mInitDataTypes.Contains(aInitDataType); -} - -enum CodecType -{ - Audio, - Video, - Invalid -}; - -static bool -CanDecryptAndDecode(const nsString& aKeySystem, - const nsString& aContentType, - CodecType aCodecType, - const KeySystemContainerSupport& aContainerSupport, - const nsTArray<EMECodecString>& aCodecs, - DecoderDoctorDiagnostics* aDiagnostics) -{ - MOZ_ASSERT(aCodecType != Invalid); - for (const EMECodecString& codec : aCodecs) { - MOZ_ASSERT(!codec.IsEmpty()); - - if (aContainerSupport.DecryptsAndDecodes(codec)) { - // GMP can decrypt-and-decode this codec. - continue; - } - - if (aContainerSupport.Decrypts(codec) && - NS_SUCCEEDED(MediaSource::IsTypeSupported(aContentType, aDiagnostics))) { - // GMP can decrypt and is allowed to return compressed samples to - // Gecko to decode, and Gecko has a decoder. - continue; - } - - // Neither the GMP nor Gecko can both decrypt and decode. We don't - // support this codec. - -#if defined(XP_WIN) - // Widevine CDM doesn't include an AAC decoder. So if WMF can't - // decode AAC, and a codec wasn't specified, be conservative - // and reject the MediaKeys request, since our policy is to prevent - // the Adobe GMP's unencrypted AAC decoding path being used to - // decode content decrypted by the Widevine CDM. - if (codec == EME_CODEC_AAC && - IsWidevineKeySystem(aKeySystem) && - !WMFDecoderModule::HasAAC()) { - if (aDiagnostics) { - aDiagnostics->SetKeySystemIssue( - DecoderDoctorDiagnostics::eWidevineWithNoWMF); - } - } -#endif - return false; - } - return true; -} - -static bool -ToSessionType(const nsAString& aSessionType, MediaKeySessionType& aOutType) -{ - using MediaKeySessionTypeValues::strings; - const char* temporary = - strings[static_cast<uint32_t>(MediaKeySessionType::Temporary)].value; - if (aSessionType.EqualsASCII(temporary)) { - aOutType = MediaKeySessionType::Temporary; - return true; - } - const char* persistentLicense = - strings[static_cast<uint32_t>(MediaKeySessionType::Persistent_license)].value; - if (aSessionType.EqualsASCII(persistentLicense)) { - aOutType = MediaKeySessionType::Persistent_license; - return true; - } - return false; -} - -// 5.2.1 Is persistent session type? -static bool -IsPersistentSessionType(MediaKeySessionType aSessionType) -{ - return aSessionType == MediaKeySessionType::Persistent_license; -} - -CodecType -GetMajorType(const nsAString& aContentType) -{ - if (CaseInsensitiveFindInReadable(NS_LITERAL_STRING("audio/"), aContentType)) { - return Audio; - } - if (CaseInsensitiveFindInReadable(NS_LITERAL_STRING("video/"), aContentType)) { - return Video; - } - return Invalid; -} - -static CodecType -GetCodecType(const EMECodecString& aCodec) -{ - if (aCodec.Equals(EME_CODEC_AAC) || - aCodec.Equals(EME_CODEC_OPUS) || - aCodec.Equals(EME_CODEC_VORBIS)) { - return Audio; - } - if (aCodec.Equals(EME_CODEC_H264) || - aCodec.Equals(EME_CODEC_VP8) || - aCodec.Equals(EME_CODEC_VP9)) { - return Video; - } - return Invalid; -} - -static bool -AllCodecsOfType(const nsTArray<EMECodecString>& aCodecs, const CodecType aCodecType) -{ - for (const EMECodecString& codec : aCodecs) { - if (GetCodecType(codec) != aCodecType) { - return false; - } - } - return true; -} - -static bool -IsParameterUnrecognized(const nsAString& aContentType) -{ - nsAutoString contentType(aContentType); - contentType.StripWhitespace(); - - nsTArray<nsString> params; - nsAString::const_iterator start, end, semicolon, equalSign; - contentType.BeginReading(start); - contentType.EndReading(end); - semicolon = start; - // Find any substring between ';' & '='. - while (semicolon != end) { - if (FindCharInReadable(';', semicolon, end)) { - equalSign = ++semicolon; - if (FindCharInReadable('=', equalSign, end)) { - params.AppendElement(Substring(semicolon, equalSign)); - semicolon = equalSign; - } - } - } - - for (auto param : params) { - if (!param.LowerCaseEqualsLiteral("codecs") && - !param.LowerCaseEqualsLiteral("profiles")) { - return true; - } - } - return false; -} - -// 3.1.2.3 Get Supported Capabilities for Audio/Video Type -static Sequence<MediaKeySystemMediaCapability> -GetSupportedCapabilities(const CodecType aCodecType, - const nsTArray<MediaKeySystemMediaCapability>& aRequestedCapabilities, - const MediaKeySystemConfiguration& aPartialConfig, - const KeySystemConfig& aKeySystem, - DecoderDoctorDiagnostics* aDiagnostics) -{ - // Let local accumulated configuration be a local copy of partial configuration. - // (Note: It's not necessary for us to maintain a local copy, as we don't need - // to test whether capabilites from previous calls to this algorithm work with - // the capabilities currently being considered in this call. ) - - // Let supported media capabilities be an empty sequence of - // MediaKeySystemMediaCapability dictionaries. - Sequence<MediaKeySystemMediaCapability> supportedCapabilities; - - // For each requested media capability in requested media capabilities: - for (const MediaKeySystemMediaCapability& capabilities : aRequestedCapabilities) { - // Let content type be requested media capability's contentType member. - const nsString& contentType = capabilities.mContentType; - // Let robustness be requested media capability's robustness member. - const nsString& robustness = capabilities.mRobustness; - // If content type is the empty string, return null. - if (contentType.IsEmpty()) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') rejected; " - "audio or video capability has empty contentType.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - return Sequence<MediaKeySystemMediaCapability>(); - } - // If content type is an invalid or unrecognized MIME type, continue - // to the next iteration. - nsAutoString container; - nsTArray<nsString> codecStrings; - if (!ParseMIMETypeString(contentType, container, codecStrings)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "failed to parse contentType as MIME type.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - bool invalid = false; - nsTArray<EMECodecString> codecs; - for (const nsString& codecString : codecStrings) { - EMECodecString emeCodec = ToEMEAPICodecString(codecString); - if (emeCodec.IsEmpty()) { - invalid = true; - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "'%s' is an invalid codec string.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get(), - NS_ConvertUTF16toUTF8(codecString).get()); - break; - } - codecs.AppendElement(emeCodec); - } - if (invalid) { - continue; - } - - // If the user agent does not support container, continue to the next iteration. - // The case-sensitivity of string comparisons is determined by the appropriate RFC. - // (Note: Per RFC 6838 [RFC6838], "Both top-level type and subtype names are - // case-insensitive."'. We're using nsContentTypeParser and that is - // case-insensitive and converts all its parameter outputs to lower case.) - NS_ConvertUTF16toUTF8 container_utf8(container); - const bool isMP4 = DecoderTraits::IsMP4TypeAndEnabled(container_utf8, aDiagnostics); - if (isMP4 && !aKeySystem.mMP4.IsSupported()) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "MP4 requested but unsupported.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - const bool isWebM = DecoderTraits::IsWebMTypeAndEnabled(container_utf8); - if (isWebM && !aKeySystem.mWebM.IsSupported()) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "WebM requested but unsupported.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - if (!isMP4 && !isWebM) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "Unsupported or unrecognized container requested.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - - // Let parameters be the RFC 6381[RFC6381] parameters, if any, specified by - // content type. - // If the user agent does not recognize one or more parameters, continue to - // the next iteration. - if (IsParameterUnrecognized(contentType)) { - continue; - } - - // Let media types be the set of codecs and codec constraints specified by - // parameters. The case-sensitivity of string comparisons is determined by - // the appropriate RFC or other specification. - // (Note: codecs array is 'parameter'). - - // If media types is empty: - if (codecs.IsEmpty()) { - // If container normatively implies a specific set of codecs and codec constraints: - // Let parameters be that set. - if (isMP4) { - if (aCodecType == Audio) { - codecs.AppendElement(EME_CODEC_AAC); - } else if (aCodecType == Video) { - codecs.AppendElement(EME_CODEC_H264); - } - } else if (isWebM) { - if (aCodecType == Audio) { - codecs.AppendElement(EME_CODEC_VORBIS); - } else if (aCodecType == Video) { - codecs.AppendElement(EME_CODEC_VP8); - } - } - // Otherwise: Continue to the next iteration. - // (Note: all containers we support have implied codecs, so don't continue here.) - } - - // If content type is not strictly a audio/video type, continue to the next iteration. - const auto majorType = GetMajorType(container); - if (majorType == Invalid) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "MIME type is not an audio or video MIME type.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - if (majorType != aCodecType || !AllCodecsOfType(codecs, aCodecType)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "MIME type mixes audio codecs in video capabilities " - "or video codecs in audio capabilities.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - // If robustness is not the empty string and contains an unrecognized - // value or a value not supported by implementation, continue to the - // next iteration. String comparison is case-sensitive. - if (!robustness.IsEmpty()) { - if (majorType == Audio && !aKeySystem.mAudioRobustness.Contains(robustness)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "unsupported robustness string.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - if (majorType == Video && !aKeySystem.mVideoRobustness.Contains(robustness)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "unsupported robustness string.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - // Note: specified robustness requirements are satisfied. - } - - // If the user agent and implementation definitely support playback of - // encrypted media data for the combination of container, media types, - // robustness and local accumulated configuration in combination with - // restrictions... - const auto& containerSupport = isMP4 ? aKeySystem.mMP4 : aKeySystem.mWebM; - if (!CanDecryptAndDecode(aKeySystem.mKeySystem, - contentType, - majorType, - containerSupport, - codecs, - aDiagnostics)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "codec unsupported by CDM requested.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - - // ... add requested media capability to supported media capabilities. - if (!supportedCapabilities.AppendElement(capabilities, mozilla::fallible)) { - NS_WARNING("GetSupportedCapabilities: Malloc failure"); - return Sequence<MediaKeySystemMediaCapability>(); - } - - // Note: omitting steps 3.13.2, our robustness is not sophisticated enough - // to require considering all requirements together. - } - return Move(supportedCapabilities); -} - -// "Get Supported Configuration and Consent" algorithm, steps 4-7 for -// distinctive identifier, and steps 8-11 for persistent state. The steps -// are the same for both requirements/features, so we factor them out into -// a single function. -static bool -CheckRequirement(const MediaKeysRequirement aRequirement, - const KeySystemFeatureSupport aFeatureSupport, - MediaKeysRequirement& aOutRequirement) -{ - // Let requirement be the value of candidate configuration's member. - MediaKeysRequirement requirement = aRequirement; - // If requirement is "optional" and feature is not allowed according to - // restrictions, set requirement to "not-allowed". - if (aRequirement == MediaKeysRequirement::Optional && - aFeatureSupport == KeySystemFeatureSupport::Prohibited) { - requirement = MediaKeysRequirement::Not_allowed; - } - - // Follow the steps for requirement from the following list: - switch (requirement) { - case MediaKeysRequirement::Required: { - // If the implementation does not support use of requirement in combination - // with accumulated configuration and restrictions, return NotSupported. - if (aFeatureSupport == KeySystemFeatureSupport::Prohibited) { - return false; - } - break; - } - case MediaKeysRequirement::Optional: { - // Continue with the following steps. - break; - } - case MediaKeysRequirement::Not_allowed: { - // If the implementation requires use of feature in combination with - // accumulated configuration and restrictions, return NotSupported. - if (aFeatureSupport == KeySystemFeatureSupport::Required) { - return false; - } - break; - } - default: { - return false; - } - } - - // Set the requirement member of accumulated configuration to equal - // calculated requirement. - aOutRequirement = requirement; - - return true; -} - -// 3.1.2.2, step 12 -// Follow the steps for the first matching condition from the following list: -// If the sessionTypes member is present in candidate configuration. -// Let session types be candidate configuration's sessionTypes member. -// Otherwise let session types be ["temporary"]. -// Note: This returns an empty array on malloc failure. -static Sequence<nsString> -UnboxSessionTypes(const Optional<Sequence<nsString>>& aSessionTypes) -{ - Sequence<nsString> sessionTypes; - if (aSessionTypes.WasPassed()) { - sessionTypes = aSessionTypes.Value(); - } else { - using MediaKeySessionTypeValues::strings; - const char* temporary = strings[static_cast<uint32_t>(MediaKeySessionType::Temporary)].value; - // Note: fallible. Results in an empty array. - sessionTypes.AppendElement(NS_ConvertUTF8toUTF16(nsDependentCString(temporary)), mozilla::fallible); - } - return sessionTypes; -} - -// 3.1.2.2 Get Supported Configuration and Consent -static bool -GetSupportedConfig(const KeySystemConfig& aKeySystem, - const MediaKeySystemConfiguration& aCandidate, - MediaKeySystemConfiguration& aOutConfig, - DecoderDoctorDiagnostics* aDiagnostics) -{ - // Let accumulated configuration be a new MediaKeySystemConfiguration dictionary. - MediaKeySystemConfiguration config; - // Set the label member of accumulated configuration to equal the label member of - // candidate configuration. - config.mLabel = aCandidate.mLabel; - // If the initDataTypes member of candidate configuration is non-empty, run the - // following steps: - if (!aCandidate.mInitDataTypes.IsEmpty()) { - // Let supported types be an empty sequence of DOMStrings. - nsTArray<nsString> supportedTypes; - // For each value in candidate configuration's initDataTypes member: - for (const nsString& initDataType : aCandidate.mInitDataTypes) { - // Let initDataType be the value. - // If the implementation supports generating requests based on initDataType, - // add initDataType to supported types. String comparison is case-sensitive. - // The empty string is never supported. - if (aKeySystem.mInitDataTypes.Contains(initDataType)) { - supportedTypes.AppendElement(initDataType); - } - } - // If supported types is empty, return NotSupported. - if (supportedTypes.IsEmpty()) { - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "no supported initDataTypes provided.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } - // Set the initDataTypes member of accumulated configuration to supported types. - if (!config.mInitDataTypes.Assign(supportedTypes)) { - return false; - } - } - - if (!CheckRequirement(aCandidate.mDistinctiveIdentifier, - aKeySystem.mDistinctiveIdentifier, - config.mDistinctiveIdentifier)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "distinctiveIdentifier requirement not satisfied.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } - - if (!CheckRequirement(aCandidate.mPersistentState, - aKeySystem.mPersistentState, - config.mPersistentState)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "persistentState requirement not satisfied.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } - - Sequence<nsString> sessionTypes(UnboxSessionTypes(aCandidate.mSessionTypes)); - if (sessionTypes.IsEmpty()) { - // Malloc failure. - return false; - } - - // For each value in session types: - for (const auto& sessionTypeString : sessionTypes) { - // Let session type be the value. - MediaKeySessionType sessionType; - if (!ToSessionType(sessionTypeString, sessionType)) { - // (Assume invalid sessionType is unsupported as per steps below). - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "invalid session type specified.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } - // If accumulated configuration's persistentState value is "not-allowed" - // and the Is persistent session type? algorithm returns true for session - // type return NotSupported. - if (config.mPersistentState == MediaKeysRequirement::Not_allowed && - IsPersistentSessionType(sessionType)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "persistent session requested but keysystem doesn't" - "support persistent state.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } - // If the implementation does not support session type in combination - // with accumulated configuration and restrictions for other reasons, - // return NotSupported. - if (!aKeySystem.mSessionTypes.Contains(sessionType)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "session type '%s' unsupported by keySystem.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get(), - NS_ConvertUTF16toUTF8(sessionTypeString).get()); - return false; - } - // If accumulated configuration's persistentState value is "optional" - // and the result of running the Is persistent session type? algorithm - // on session type is true, change accumulated configuration's - // persistentState value to "required". - if (config.mPersistentState == MediaKeysRequirement::Optional && - IsPersistentSessionType(sessionType)) { - config.mPersistentState = MediaKeysRequirement::Required; - } - } - // Set the sessionTypes member of accumulated configuration to session types. - config.mSessionTypes.Construct(Move(sessionTypes)); - - // If the videoCapabilities and audioCapabilities members in candidate - // configuration are both empty, return NotSupported. - // TODO: Most sites using EME still don't pass capabilities, so we - // can't reject on it yet without breaking them. So add this later. - - // If the videoCapabilities member in candidate configuration is non-empty: - if (!aCandidate.mVideoCapabilities.IsEmpty()) { - // Let video capabilities be the result of executing the Get Supported - // Capabilities for Audio/Video Type algorithm on Video, candidate - // configuration's videoCapabilities member, accumulated configuration, - // and restrictions. - Sequence<MediaKeySystemMediaCapability> caps = - GetSupportedCapabilities(Video, - aCandidate.mVideoCapabilities, - config, - aKeySystem, - aDiagnostics); - // If video capabilities is null, return NotSupported. - if (caps.IsEmpty()) { - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "no supported video capabilities.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } - // Set the videoCapabilities member of accumulated configuration to video capabilities. - config.mVideoCapabilities = Move(caps); - } else { - // Otherwise: - // Set the videoCapabilities member of accumulated configuration to an empty sequence. - } - - // If the audioCapabilities member in candidate configuration is non-empty: - if (!aCandidate.mAudioCapabilities.IsEmpty()) { - // Let audio capabilities be the result of executing the Get Supported Capabilities - // for Audio/Video Type algorithm on Audio, candidate configuration's audioCapabilities - // member, accumulated configuration, and restrictions. - Sequence<MediaKeySystemMediaCapability> caps = - GetSupportedCapabilities(Audio, - aCandidate.mAudioCapabilities, - config, - aKeySystem, - aDiagnostics); - // If audio capabilities is null, return NotSupported. - if (caps.IsEmpty()) { - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "no supported audio capabilities.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } - // Set the audioCapabilities member of accumulated configuration to audio capabilities. - config.mAudioCapabilities = Move(caps); - } else { - // Otherwise: - // Set the audioCapabilities member of accumulated configuration to an empty sequence. - } - - // If accumulated configuration's distinctiveIdentifier value is "optional", follow the - // steps for the first matching condition from the following list: - if (config.mDistinctiveIdentifier == MediaKeysRequirement::Optional) { - // If the implementation requires use Distinctive Identifier(s) or - // Distinctive Permanent Identifier(s) for any of the combinations - // in accumulated configuration - if (aKeySystem.mDistinctiveIdentifier == KeySystemFeatureSupport::Required) { - // Change accumulated configuration's distinctiveIdentifier value to "required". - config.mDistinctiveIdentifier = MediaKeysRequirement::Required; - } else { - // Otherwise, change accumulated configuration's distinctiveIdentifier - // value to "not-allowed". - config.mDistinctiveIdentifier = MediaKeysRequirement::Not_allowed; - } - } - - // If accumulated configuration's persistentState value is "optional", follow the - // steps for the first matching condition from the following list: - if (config.mPersistentState == MediaKeysRequirement::Optional) { - // If the implementation requires persisting state for any of the combinations - // in accumulated configuration - if (aKeySystem.mPersistentState == KeySystemFeatureSupport::Required) { - // Change accumulated configuration's persistentState value to "required". - config.mPersistentState = MediaKeysRequirement::Required; - } else { - // Otherwise, change accumulated configuration's persistentState - // value to "not-allowed". - config.mPersistentState = MediaKeysRequirement::Not_allowed; - } - } - - // Note: Omitting steps 20-22. We don't ask for consent. - -#if defined(XP_WIN) - // Widevine CDM doesn't include an AAC decoder. So if WMF can't decode AAC, - // and a codec wasn't specified, be conservative and reject the MediaKeys request. - if (IsWidevineKeySystem(aKeySystem.mKeySystem) && - (aCandidate.mAudioCapabilities.IsEmpty() || - aCandidate.mVideoCapabilities.IsEmpty()) && - !WMFDecoderModule::HasAAC()) { - if (aDiagnostics) { - aDiagnostics->SetKeySystemIssue( - DecoderDoctorDiagnostics::eWidevineWithNoWMF); - } - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "WMF required for Widevine decoding, but it's not available.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } -#endif - - // Return accumulated configuration. - aOutConfig = config; - - return true; -} - -/* static */ -bool -MediaKeySystemAccess::GetSupportedConfig(const nsAString& aKeySystem, - const Sequence<MediaKeySystemConfiguration>& aConfigs, - MediaKeySystemConfiguration& aOutConfig, - DecoderDoctorDiagnostics* aDiagnostics) -{ - KeySystemConfig implementation; - if (!GetKeySystemConfig(aKeySystem, implementation)) { - return false; - } - for (const MediaKeySystemConfiguration& candidate : aConfigs) { - if (mozilla::dom::GetSupportedConfig(implementation, - candidate, - aOutConfig, - aDiagnostics)) { - return true; - } - } - - return false; -} - - -/* static */ -void -MediaKeySystemAccess::NotifyObservers(nsPIDOMWindowInner* aWindow, - const nsAString& aKeySystem, - MediaKeySystemStatus aStatus) -{ - RequestMediaKeySystemAccessNotification data; - data.mKeySystem = aKeySystem; - data.mStatus = aStatus; - nsAutoString json; - data.ToJSON(json); - EME_LOG("MediaKeySystemAccess::NotifyObservers() %s", NS_ConvertUTF16toUTF8(json).get()); - nsCOMPtr<nsIObserverService> 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 c260e92b5c..0000000000 --- a/dom/media/eme/MediaKeySystemAccess.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#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 { - -class DecoderDoctorDiagnostics; - -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(nsPIDOMWindowInner* aParent, - const nsAString& aKeySystem, - const MediaKeySystemConfiguration& aConfig); - -protected: - ~MediaKeySystemAccess(); - -public: - nsPIDOMWindowInner* GetParentObject() const; - - JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; - - void GetKeySystem(nsString& aRetVal) const; - - void GetConfiguration(MediaKeySystemConfiguration& aConfig); - - already_AddRefed<Promise> CreateMediaKeys(ErrorResult& aRv); - - static MediaKeySystemStatus GetKeySystemStatus(const nsAString& aKeySystem, - nsACString& aOutExceptionMessage); - - static bool IsSupported(const nsAString& aKeySystem, - const Sequence<MediaKeySystemConfiguration>& aConfigs, - DecoderDoctorDiagnostics* aDiagnostics); - - static void NotifyObservers(nsPIDOMWindowInner* aWindow, - const nsAString& aKeySystem, - MediaKeySystemStatus aStatus); - - static bool GetSupportedConfig(const nsAString& aKeySystem, - const Sequence<MediaKeySystemConfiguration>& aConfigs, - MediaKeySystemConfiguration& aOutConfig, - DecoderDoctorDiagnostics* aDiagnostics); - - static bool KeySystemSupportsInitDataType(const nsAString& aKeySystem, - const nsAString& aInitDataType); - -private: - nsCOMPtr<nsPIDOMWindowInner> mParent; - const nsString mKeySystem; - const MediaKeySystemConfiguration mConfig; -}; - -} // 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 ed31059e22..0000000000 --- a/dom/media/eme/MediaKeySystemAccessManager.cpp +++ /dev/null @@ -1,339 +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 "DecoderDoctorDiagnostics.h" -#include "MediaPrefs.h" -#include "mozilla/EMEUtils.h" -#include "nsServiceManagerUtils.h" -#include "nsComponentManagerUtils.h" -#include "nsIObserverService.h" -#include "mozilla/Services.h" -#include "mozilla/DetailedPromise.h" -#ifdef XP_WIN -#include "mozilla/WindowsVersion.h" -#endif -#ifdef XP_MACOSX -#include "nsCocoaFeatures.h" -#endif -#include "nsPrintfCString.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(NS_LITERAL_CSTRING("Promise still outstanding at MediaKeySystemAccessManager GC")); - 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(nsPIDOMWindowInner* aWindow) - : mWindow(aWindow) - , mAddedObservers(false) -{ -} - -MediaKeySystemAccessManager::~MediaKeySystemAccessManager() -{ - Shutdown(); -} - -void -MediaKeySystemAccessManager::Request(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence<MediaKeySystemConfiguration>& aConfigs) -{ - Request(aPromise, aKeySystem, aConfigs, RequestType::Initial); -} - -void -MediaKeySystemAccessManager::Request(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence<MediaKeySystemConfiguration>& aConfigs, - RequestType aType) -{ - EME_LOG("MediaKeySystemAccessManager::Request %s", NS_ConvertUTF16toUTF8(aKeySystem).get()); - - if (aKeySystem.IsEmpty()) { - aPromise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Key system string is empty")); - // Don't notify DecoderDoctor, as there's nothing we or the user can - // do to fix this situation; the site is using the API wrong. - return; - } - if (aConfigs.IsEmpty()) { - aPromise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Candidate MediaKeySystemConfigs is empty")); - // Don't notify DecoderDoctor, as there's nothing we or the user can - // do to fix this situation; the site is using the API wrong. - return; - } - - DecoderDoctorDiagnostics diagnostics; - - // Ensure keysystem is supported. - if (!IsWidevineKeySystem(aKeySystem) && - !IsClearkeyKeySystem(aKeySystem)) { - // Not to inform user, because nothing to do if the keySystem is not - // supported. - aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, - NS_LITERAL_CSTRING("Key system is unsupported")); - diagnostics.StoreMediaKeySystemAccess(mWindow->GetExtantDoc(), - aKeySystem, false, __func__); - return; - } - - if (!MediaPrefs::EMEEnabled() && !IsClearkeyKeySystem(aKeySystem)) { - // EME disabled by user, send notification to chrome so UI can inform user. - // Clearkey is allowed even when EME is disabled because we want the pref - // "media.eme.enabled" only taking effect on proprietary DRMs. - MediaKeySystemAccess::NotifyObservers(mWindow, - aKeySystem, - MediaKeySystemStatus::Api_disabled); - aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, - NS_LITERAL_CSTRING("EME has been preffed off")); - diagnostics.StoreMediaKeySystemAccess(mWindow->GetExtantDoc(), - aKeySystem, false, __func__); - return; - } - - nsAutoCString message; - MediaKeySystemStatus status = - MediaKeySystemAccess::GetKeySystemStatus(aKeySystem, message); - - nsPrintfCString msg("MediaKeySystemAccess::GetKeySystemStatus(%s) " - "result=%s msg='%s'", - NS_ConvertUTF16toUTF8(aKeySystem).get(), - MediaKeySystemStatusValues::strings[(size_t)status].value, - message.get()); - LogToBrowserConsole(NS_ConvertUTF8toUTF16(msg)); - - if (status == MediaKeySystemStatus::Cdm_not_installed && - IsWidevineKeySystem(aKeySystem)) { - // 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, aConfigs)) { - // 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 notification, - // as chrome is already displaying the "we can't play, updating" - // notification. - MediaKeySystemAccess::NotifyObservers(mWindow, aKeySystem, 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, - NS_LITERAL_CSTRING("Gave up while waiting for a CDM update")); - } - diagnostics.StoreMediaKeySystemAccess(mWindow->GetExtantDoc(), - aKeySystem, false, __func__); - return; - } - if (status != MediaKeySystemStatus::Available) { - // 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, aKeySystem, status); - aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, message); - return; - } - - MediaKeySystemConfiguration config; - if (MediaKeySystemAccess::GetSupportedConfig(aKeySystem, aConfigs, config, &diagnostics)) { - RefPtr<MediaKeySystemAccess> access( - new MediaKeySystemAccess(mWindow, aKeySystem, config)); - aPromise->MaybeResolve(access); - diagnostics.StoreMediaKeySystemAccess(mWindow->GetExtantDoc(), - aKeySystem, true, __func__); - return; - } - // Not to inform user, because nothing to do if the corresponding keySystem - // configuration is not supported. - aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, - NS_LITERAL_CSTRING("Key system configuration is not supported")); - diagnostics.StoreMediaKeySystemAccess(mWindow->GetExtantDoc(), - aKeySystem, false, __func__); -} - -MediaKeySystemAccessManager::PendingRequest::PendingRequest(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence<MediaKeySystemConfiguration>& aConfigs, - nsITimer* aTimer) - : mPromise(aPromise) - , mKeySystem(aKeySystem) - , mConfigs(aConfigs) - , mTimer(aTimer) -{ - MOZ_COUNT_CTOR(MediaKeySystemAccessManager::PendingRequest); -} - -MediaKeySystemAccessManager::PendingRequest::PendingRequest(const PendingRequest& aOther) - : mPromise(aOther.mPromise) - , mKeySystem(aOther.mKeySystem) - , mConfigs(aOther.mConfigs) - , 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(const nsCString& aReason) -{ - if (mPromise) { - mPromise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR, aReason); - } -} - -bool -MediaKeySystemAccessManager::AwaitInstall(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence<MediaKeySystemConfiguration>& aConfigs) -{ - EME_LOG("MediaKeySystemAccessManager::AwaitInstall %s", NS_ConvertUTF16toUTF8(aKeySystem).get()); - - if (!EnsureObserversAdded()) { - NS_WARNING("Failed to add pref observer"); - return false; - } - - nsCOMPtr<nsITimer> 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, aConfigs, timer)); - return true; -} - -void -MediaKeySystemAccessManager::RetryRequest(PendingRequest& aRequest) -{ - aRequest.CancelTimer(); - Request(aRequest.mPromise, aRequest.mKeySystem, aRequest.mConfigs, RequestType::Subsequent); -} - -nsresult -MediaKeySystemAccessManager::Observe(nsISupports* aSubject, - const char* aTopic, - const char16_t* aData) -{ - EME_LOG("MediaKeySystemAccessManager::Observe %s", aTopic); - - if (!strcmp(aTopic, "gmp-changed")) { - // Filter out the requests where the CDM's install-status is no longer - // "unavailable". This will be the CDMs which have downloaded since the - // initial request. - // Note: We don't have a way to communicate from chrome that the CDM has - // failed to download, so we'll just let the timeout fail us in that case. - nsTArray<PendingRequest> requests; - for (size_t i = mRequests.Length(); i-- > 0; ) { - PendingRequest& request = mRequests[i]; - nsAutoCString message; - MediaKeySystemStatus status = - MediaKeySystemAccess::GetKeySystemStatus(request.mKeySystem, message); - if (status == MediaKeySystemStatus::Cdm_not_installed) { - // Not yet installed, don't retry. Keep waiting until timeout. - continue; - } - // Status has changed, retry request. - requests.AppendElement(Move(request)); - mRequests.RemoveElementAt(i); - } - // 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<nsITimer> 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<nsIObserverService> obsService = mozilla::services::GetObserverService(); - if (NS_WARN_IF(!obsService)) { - return false; - } - mAddedObservers = NS_SUCCEEDED(obsService->AddObserver(this, "gmp-changed", false)); - return mAddedObservers; -} - -void -MediaKeySystemAccessManager::Shutdown() -{ - EME_LOG("MediaKeySystemAccessManager::Shutdown"); - nsTArray<PendingRequest> requests(Move(mRequests)); - for (PendingRequest& request : requests) { - // Cancel all requests; we're shutting down. - request.CancelTimer(); - request.RejectPromise(NS_LITERAL_CSTRING("Promise still outstanding at MediaKeySystemAccessManager shutdown")); - } - if (mAddedObservers) { - nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService(); - if (obsService) { - obsService->RemoveObserver(this, "gmp-changed"); - 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 9c092248e2..0000000000 --- a/dom/media/eme/MediaKeySystemAccessManager.h +++ /dev/null @@ -1,83 +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 DetailedPromise; -class TestGMPVideoDecoder; - -class MediaKeySystemAccessManager final : public nsIObserver -{ -public: - - explicit MediaKeySystemAccessManager(nsPIDOMWindowInner* aWindow); - - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(MediaKeySystemAccessManager, nsIObserver) - NS_DECL_NSIOBSERVER - - void Request(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence<MediaKeySystemConfiguration>& aConfig); - - void Shutdown(); - - struct PendingRequest { - PendingRequest(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence<MediaKeySystemConfiguration>& aConfig, - nsITimer* aTimer); - PendingRequest(const PendingRequest& aOther); - ~PendingRequest(); - void CancelTimer(); - void RejectPromise(const nsCString& aReason); - - RefPtr<DetailedPromise> mPromise; - const nsString mKeySystem; - const Sequence<MediaKeySystemConfiguration> mConfigs; - nsCOMPtr<nsITimer> mTimer; - }; - -private: - - enum RequestType { - Initial, - Subsequent - }; - - void Request(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence<MediaKeySystemConfiguration>& aConfig, - RequestType aType); - - ~MediaKeySystemAccessManager(); - - bool EnsureObserversAdded(); - - bool AwaitInstall(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence<MediaKeySystemConfiguration>& aConfig); - - void RetryRequest(PendingRequest& aRequest); - - nsTArray<PendingRequest> mRequests; - - nsCOMPtr<nsPIDOMWindowInner> 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 8621007579..0000000000 --- a/dom/media/eme/MediaKeys.cpp +++ /dev/null @@ -1,579 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#include "mozilla/dom/MediaKeys.h" -#include "GMPService.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/UnionTypes.h" -#include "GMPCDMProxy.h" -#include "mozilla/EMEUtils.h" -#include "nsContentUtils.h" -#include "nsIScriptObjectPrincipal.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(nsPIDOMWindowInner* aParent, - const nsAString& aKeySystem, - const MediaKeySystemConfiguration& aConfig) - : mParent(aParent) - , mKeySystem(aKeySystem) - , mCreatePromiseId(0) - , mConfig(aConfig) -{ - EME_LOG("MediaKeys[%p] constructed keySystem=%s", - this, NS_ConvertUTF16toUTF8(mKeySystem).get()); -} - -MediaKeys::~MediaKeys() -{ - Shutdown(); - EME_LOG("MediaKeys[%p] destroyed", this); -} - -void -MediaKeys::Terminated() -{ - EME_LOG("MediaKeys[%p] CDM crashed unexpectedly", this); - - KeySessionHashMap keySessions; - // Remove entries during iteration will screw it. Make a copy first. - for (auto iter = mKeySessions.Iter(); !iter.Done(); iter.Next()) { - RefPtr<MediaKeySession>& session = iter.Data(); - keySessions.Put(session->GetSessionId(), session); - } - for (auto iter = keySessions.Iter(); !iter.Done(); iter.Next()) { - RefPtr<MediaKeySession>& session = iter.Data(); - session->OnClosed(); - } - keySessions.Clear(); - MOZ_ASSERT(mKeySessions.Count() == 0); - - // Notify the element about that CDM has terminated. - if (mElement) { - mElement->DecodeError(NS_ERROR_DOM_MEDIA_CDM_ERR); - } - - Shutdown(); -} - -void -MediaKeys::Shutdown() -{ - if (mProxy) { - mProxy->Shutdown(); - mProxy = nullptr; - } - - RefPtr<MediaKeys> kungFuDeathGrip = this; - - for (auto iter = mPromises.Iter(); !iter.Done(); iter.Next()) { - RefPtr<dom::DetailedPromise>& promise = iter.Data(); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Promise still outstanding at MediaKeys shutdown")); - Release(); - } - mPromises.Clear(); -} - -nsPIDOMWindowInner* -MediaKeys::GetParentObject() const -{ - return mParent; -} - -JSObject* -MediaKeys::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) -{ - return MediaKeysBinding::Wrap(aCx, this, aGivenProto); -} - -void -MediaKeys::GetKeySystem(nsString& aOutKeySystem) const -{ - aOutKeySystem.Assign(mKeySystem); -} - -already_AddRefed<DetailedPromise> -MediaKeys::SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aCert, ErrorResult& aRv) -{ - RefPtr<DetailedPromise> promise(MakePromise(aRv, - NS_LITERAL_CSTRING("MediaKeys.setServerCertificate"))); - 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, - NS_LITERAL_CSTRING("Null CDM in MediaKeys.setServerCertificate()")); - return promise.forget(); - } - - nsTArray<uint8_t> data; - CopyArrayBufferViewOrArrayBufferData(aCert, data); - if (data.IsEmpty()) { - promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Empty certificate passed to MediaKeys.setServerCertificate()")); - return promise.forget(); - } - - mProxy->SetServerCertificate(StorePromise(promise), data); - return promise.forget(); -} - -already_AddRefed<DetailedPromise> -MediaKeys::MakePromise(ErrorResult& aRv, const nsACString& aName) -{ - nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject()); - if (!global) { - NS_WARNING("Passed non-global to MediaKeys ctor!"); - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - return DetailedPromise::Create(global, aRv, aName); -} - -PromiseId -MediaKeys::StorePromise(DetailedPromise* 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(); - -#ifdef DEBUG - // We should not have already stored this promise! - for (auto iter = mPromises.ConstIter(); !iter.Done(); iter.Next()) { - MOZ_ASSERT(iter.Data() != aPromise); - } -#endif - - mPromises.Put(id, aPromise); - return id; -} - -void -MediaKeys::ConnectPendingPromiseIdWithToken(PromiseId aId, uint32_t aToken) -{ - // Should only be called from MediaKeySession::GenerateRequest. - mPromiseIdToken.Put(aId, aToken); - EME_LOG("MediaKeys[%p]::ConnectPendingPromiseIdWithToken() id=%u => token(%u)", - this, aId, aToken); -} - -already_AddRefed<DetailedPromise> -MediaKeys::RetrievePromise(PromiseId aId) -{ - if (!mPromises.Contains(aId)) { - NS_WARNING(nsPrintfCString("Tried to retrieve a non-existent promise id=%d", aId).get()); - return nullptr; - } - RefPtr<DetailedPromise> promise; - mPromises.Remove(aId, getter_AddRefs(promise)); - Release(); - return promise.forget(); -} - -void -MediaKeys::RejectPromise(PromiseId aId, nsresult aExceptionCode, - const nsCString& aReason) -{ - EME_LOG("MediaKeys[%p]::RejectPromise(%d, 0x%x)", this, aId, aExceptionCode); - - RefPtr<DetailedPromise> promise(RetrievePromise(aId)); - if (!promise) { - return; - } - - // 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. - uint32_t token = 0; - if (mPromiseIdToken.Get(aId, &token)) { - MOZ_ASSERT(mPendingSessions.Contains(token)); - mPendingSessions.Remove(token); - mPromiseIdToken.Remove(aId); - } - - MOZ_ASSERT(NS_FAILED(aExceptionCode)); - promise->MaybeReject(aExceptionCode, aReason); - - 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); - - RefPtr<DetailedPromise> promise(RetrievePromise(aId)); - MOZ_ASSERT(!mPromises.Contains(aId)); - if (!promise) { - return; - } - - uint32_t token = 0; - if (!mPromiseIdToken.Get(aId, &token)) { - promise->MaybeResolveWithUndefined(); - return; - } else if (!mPendingSessions.Contains(token)) { - // Pending session for CreateSession() should be removed when sessionId - // is ready. - promise->MaybeResolveWithUndefined(); - mPromiseIdToken.Remove(aId); - return; - } - mPromiseIdToken.Remove(aId); - - // We should only resolve LoadSession calls via this path, - // not CreateSession() promises. - RefPtr<MediaKeySession> session; - mPendingSessions.Remove(token, getter_AddRefs(session)); - if (!session || session->GetSessionId().IsEmpty()) { - NS_WARNING("Received activation for non-existent session!"); - promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR, - NS_LITERAL_CSTRING("CDM LoadSession() returned a different session ID than requested")); - return; - } - mKeySessions.Put(session->GetSessionId(), session); - promise->MaybeResolve(session); -} - -class MediaKeysGMPCrashHelper : public GMPCrashHelper -{ -public: - explicit MediaKeysGMPCrashHelper(MediaKeys* aMediaKeys) - : mMediaKeys(aMediaKeys) - { - MOZ_ASSERT(NS_IsMainThread()); // WeakPtr isn't thread safe. - } - already_AddRefed<nsPIDOMWindowInner> - GetPluginCrashedEventTarget() override - { - MOZ_ASSERT(NS_IsMainThread()); // WeakPtr isn't thread safe. - EME_LOG("MediaKeysGMPCrashHelper::GetPluginCrashedEventTarget()"); - return (mMediaKeys && mMediaKeys->GetParentObject()) ? - do_AddRef(mMediaKeys->GetParentObject()) : nullptr; - } -private: - WeakPtr<MediaKeys> mMediaKeys; -}; - -already_AddRefed<CDMProxy> -MediaKeys::CreateCDMProxy() -{ - RefPtr<CDMProxy> proxy; - { - proxy = new GMPCDMProxy(this, - mKeySystem, - new MediaKeysGMPCrashHelper(this), - mConfig.mDistinctiveIdentifier == MediaKeysRequirement::Required, - mConfig.mPersistentState == MediaKeysRequirement::Required); - } - return proxy.forget(); -} - -already_AddRefed<DetailedPromise> -MediaKeys::Init(ErrorResult& aRv) -{ - RefPtr<DetailedPromise> promise(MakePromise(aRv, - NS_LITERAL_CSTRING("MediaKeys::Init()"))); - if (aRv.Failed()) { - return nullptr; - } - - mProxy = CreateCDMProxy(); - - // Determine principal (at creation time) of the MediaKeys object. - nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(GetParentObject()); - if (!sop) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get script principal in MediaKeys::Init")); - 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<nsPIDOMWindowInner> window = GetParentObject(); - if (!window) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get top-level window in MediaKeys::Init")); - return promise.forget(); - } - nsCOMPtr<nsPIDOMWindowOuter> top = window->GetOuterWindow()->GetTop(); - if (!top || !top->GetExtantDoc()) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get document in MediaKeys::Init")); - 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, - NS_LITERAL_CSTRING("Couldn't get principal(s) in MediaKeys::Init")); - return promise.forget(); - } - - nsAutoCString origin; - nsresult rv = mPrincipal->GetOrigin(origin); - if (NS_FAILED(rv)) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get principal origin string in MediaKeys::Init")); - return promise.forget(); - } - nsAutoCString topLevelOrigin; - rv = mTopLevelPrincipal->GetOrigin(topLevelOrigin); - if (NS_FAILED(rv)) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get top-level principal origin string in MediaKeys::Init")); - return promise.forget(); - } - - nsIDocument* doc = window->GetExtantDoc(); - const bool inPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc); - - EME_LOG("MediaKeys[%p]::Create() (%s, %s), %s", - this, - origin.get(), - 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, - NS_ConvertUTF8toUTF16(origin), - NS_ConvertUTF8toUTF16(topLevelOrigin), - KeySystemToGMPName(mKeySystem), - inPrivateBrowsing); - - return promise.forget(); -} - -void -MediaKeys::OnCDMCreated(PromiseId aId, const nsACString& aNodeId, const uint32_t aPluginId) -{ - RefPtr<DetailedPromise> promise(RetrievePromise(aId)); - if (!promise) { - return; - } - mNodeId = aNodeId; - RefPtr<MediaKeys> 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); - -} - -static bool -IsSessionTypeSupported(const MediaKeySessionType aSessionType, - const MediaKeySystemConfiguration& aConfig) -{ - if (aSessionType == MediaKeySessionType::Temporary) { - // Temporary is always supported. - return true; - } - if (!aConfig.mSessionTypes.WasPassed()) { - // No other session types supported. - return false; - } - using MediaKeySessionTypeValues::strings; - const char* sessionType = strings[static_cast<uint32_t>(aSessionType)].value; - for (const nsString& s : aConfig.mSessionTypes.Value()) { - if (s.EqualsASCII(sessionType)) { - return true; - } - } - return false; -} - -already_AddRefed<MediaKeySession> -MediaKeys::CreateSession(JSContext* aCx, - MediaKeySessionType aSessionType, - ErrorResult& aRv) -{ - if (!IsSessionTypeSupported(aSessionType, mConfig)) { - EME_LOG("MediaKeys[%p,'%s'] CreateSession() failed, unsupported session type", this); - aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return nullptr; - } - - if (!mProxy) { - NS_WARNING("Tried to use a MediaKeys which lost its CDM"); - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - return nullptr; - } - - EME_LOG("MediaKeys[%p] Creating session", this); - - RefPtr<MediaKeySession> 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) -{ - RefPtr<DetailedPromise> 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<MediaKeySession> -MediaKeys::GetSession(const nsAString& aSessionId) -{ - RefPtr<MediaKeySession> session; - mKeySessions.Get(aSessionId, getter_AddRefs(session)); - return session.forget(); -} - -already_AddRefed<MediaKeySession> -MediaKeys::GetPendingSession(uint32_t aToken) -{ - RefPtr<MediaKeySession> 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; -} - -void -MediaKeys::Unbind() -{ - MOZ_ASSERT(NS_IsMainThread()); - mElement = nullptr; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeys.h b/dom/media/eme/MediaKeys.h deleted file mode 100644 index 4919639342..0000000000 --- a/dom/media/eme/MediaKeys.h +++ /dev/null @@ -1,167 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#ifndef mozilla_dom_mediakeys_h__ -#define mozilla_dom_mediakeys_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 "mozilla/dom/MediaKeySystemAccessBinding.h" -#include "mozIGeckoMediaPluginService.h" -#include "mozilla/DetailedPromise.h" -#include "mozilla/WeakPtr.h" - -namespace mozilla { - -class CDMProxy; - -namespace dom { - -class ArrayBufferViewOrArrayBuffer; -class MediaKeySession; -class HTMLMediaElement; - -typedef nsRefPtrHashtable<nsStringHashKey, MediaKeySession> KeySessionHashMap; -typedef nsRefPtrHashtable<nsUint32HashKey, dom::DetailedPromise> PromiseHashMap; -typedef nsRefPtrHashtable<nsUint32HashKey, MediaKeySession> PendingKeySessionsHashMap; -typedef nsDataHashtable<nsUint32HashKey, uint32_t> PendingPromiseIdTokenHashMap; -typedef uint32_t PromiseId; - -// This class is used on the main thread only. -// Note: its addref/release is not (and can't be) thread safe! -class MediaKeys final : public nsISupports, - public nsWrapperCache, - public SupportsWeakPtr<MediaKeys> -{ - ~MediaKeys(); - -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaKeys) - MOZ_DECLARE_WEAKREFERENCE_TYPENAME(MediaKeys) - - MediaKeys(nsPIDOMWindowInner* aParentWindow, - const nsAString& aKeySystem, - const MediaKeySystemConfiguration& aConfig); - - already_AddRefed<DetailedPromise> Init(ErrorResult& aRv); - - nsPIDOMWindowInner* GetParentObject() const; - - JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; - - nsresult Bind(HTMLMediaElement* aElement); - void Unbind(); - - // Javascript: readonly attribute DOMString keySystem; - void GetKeySystem(nsString& retval) const; - - // JavaScript: MediaKeys.createSession() - already_AddRefed<MediaKeySession> CreateSession(JSContext* aCx, - MediaKeySessionType aSessionType, - ErrorResult& aRv); - - // JavaScript: MediaKeys.SetServerCertificate() - already_AddRefed<DetailedPromise> - SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aServerCertificate, - ErrorResult& aRv); - - already_AddRefed<MediaKeySession> GetSession(const nsAString& aSessionId); - - // Removes and returns MediaKeySession from the set of sessions awaiting - // their sessionId to be assigned. - already_AddRefed<MediaKeySession> GetPendingSession(uint32_t aToken); - - // Called once a Init() operation succeeds. - void OnCDMCreated(PromiseId aId, - const nsACString& aNodeId, const uint32_t 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<DetailedPromise> MakePromise(ErrorResult& aRv, - const nsACString& aName); - // 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(DetailedPromise* aPromise); - - // Stores a map from promise id to pending session token. Using this - // mapping, when a promise is rejected via its ID, we can check if the - // promise corresponds to a pending session and retrieve that session - // via the mapped-to token, and remove the pending session from the - // list of sessions awaiting a session id. - void ConnectPendingPromiseIdWithToken(PromiseId aId, uint32_t aToken); - - // Reject promise with DOMException corresponding to aExceptionCode. - void RejectPromise(PromiseId aId, nsresult aExceptionCode, - const nsCString& aReason); - // 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: - - // Instantiate CDMProxy instance. - // It could be MediaDrmCDMProxy (Widevine on Fennec) or GMPCDMProxy (the rest). - already_AddRefed<CDMProxy> CreateCDMProxy(); - - // Removes promise from mPromises, and returns it. - already_AddRefed<DetailedPromise> 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. - RefPtr<CDMProxy> mProxy; - - RefPtr<HTMLMediaElement> mElement; - - nsCOMPtr<nsPIDOMWindowInner> mParent; - const nsString mKeySystem; - nsCString mNodeId; - KeySessionHashMap mKeySessions; - PromiseHashMap mPromises; - PendingKeySessionsHashMap mPendingSessions; - PromiseId mCreatePromiseId; - - RefPtr<nsIPrincipal> mPrincipal; - RefPtr<nsIPrincipal> mTopLevelPrincipal; - - const MediaKeySystemConfiguration mConfig; - - PendingPromiseIdTokenHashMap mPromiseIdToken; -}; - -} // 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 31ab9ffd87..0000000000 --- a/dom/media/eme/moz.build +++ /dev/null @@ -1,41 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# 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 += [ - 'CDMCaps.h', - 'CDMProxy.h', - 'DecryptorProxyCallback.h', - 'DetailedPromise.h', - 'EMEUtils.h', -] - -UNIFIED_SOURCES += [ - 'CDMCaps.cpp', - 'DetailedPromise.cpp', - 'EMEUtils.cpp', - 'MediaEncryptedEvent.cpp', - 'MediaKeyError.cpp', - 'MediaKeyMessageEvent.cpp', - 'MediaKeys.cpp', - 'MediaKeySession.cpp', - 'MediaKeyStatusMap.cpp', - 'MediaKeySystemAccess.cpp', - 'MediaKeySystemAccessManager.cpp', -] - -include('/ipc/chromium/chromium-config.mozbuild') - -FINAL_LIBRARY = 'xul' diff --git a/dom/media/fmp4/MP4Decoder.cpp b/dom/media/fmp4/MP4Decoder.cpp index 3cfe5b1374..ed212992c0 100644 --- a/dom/media/fmp4/MP4Decoder.cpp +++ b/dom/media/fmp4/MP4Decoder.cpp @@ -9,9 +9,6 @@ #include "MP4Demuxer.h" #include "mozilla/Preferences.h" #include "nsCharSeparatedTokenizer.h" -#ifdef MOZ_EME -#include "mozilla/CDMProxy.h" -#endif #include "mozilla/Logging.h" #include "mozilla/SharedThreadPool.h" #include "nsMimeTypes.h" diff --git a/dom/media/gmp/GMPCDMCallbackProxy.cpp b/dom/media/gmp/GMPCDMCallbackProxy.cpp deleted file mode 100644 index a0b490849a..0000000000 --- a/dom/media/gmp/GMPCDMCallbackProxy.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#include "GMPCDMCallbackProxy.h" -#include "mozilla/CDMProxy.h" -#include "nsString.h" -#include "mozilla/dom/MediaKeys.h" -#include "mozilla/dom/MediaKeySession.h" -#include "mozIGeckoMediaPluginService.h" -#include "nsContentCID.h" -#include "nsServiceManagerUtils.h" -#include "MainThreadUtils.h" -#include "mozilla/EMEUtils.h" - -namespace mozilla { - -GMPCDMCallbackProxy::GMPCDMCallbackProxy(CDMProxy* aProxy) - : mProxy(aProxy) -{} - -void -GMPCDMCallbackProxy::SetDecryptorId(uint32_t aId) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr<CDMProxy> proxy = mProxy; - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, aId] () - { - proxy->OnSetDecryptorId(aId); - }) - );} - -void -GMPCDMCallbackProxy::SetSessionId(uint32_t aToken, - const nsCString& aSessionId) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr<CDMProxy> proxy = mProxy; - auto sid = NS_ConvertUTF8toUTF16(aSessionId); - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, - aToken, - sid] () - { - proxy->OnSetSessionId(aToken, sid); - }) - ); -} - -void -GMPCDMCallbackProxy::ResolveLoadSessionPromise(uint32_t aPromiseId, - bool aSuccess) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr<CDMProxy> proxy = mProxy; - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, aPromiseId, aSuccess] () - { - proxy->OnResolveLoadSessionPromise(aPromiseId, aSuccess); - }) - ); -} - -void -GMPCDMCallbackProxy::ResolvePromise(uint32_t aPromiseId) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - // Note: CDMProxy proxies this from non-main threads to main thread. - mProxy->ResolvePromise(aPromiseId); -} - -void -GMPCDMCallbackProxy::RejectPromise(uint32_t aPromiseId, - nsresult aException, - const nsCString& aMessage) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr<CDMProxy> proxy = mProxy; - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, - aPromiseId, - aException, - aMessage] () - { - proxy->OnRejectPromise(aPromiseId, aException, aMessage); - }) - ); -} - -void -GMPCDMCallbackProxy::SessionMessage(const nsCString& aSessionId, - dom::MediaKeyMessageType aMessageType, - const nsTArray<uint8_t>& aMessage) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr<CDMProxy> proxy = mProxy; - auto sid = NS_ConvertUTF8toUTF16(aSessionId); - nsTArray<uint8_t> msg(aMessage); - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, - sid, - aMessageType, - msg] () mutable - { - proxy->OnSessionMessage(sid, aMessageType, msg); - }) - ); -} - -void -GMPCDMCallbackProxy::ExpirationChange(const nsCString& aSessionId, - GMPTimestamp aExpiryTime) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr<CDMProxy> proxy = mProxy; - auto sid = NS_ConvertUTF8toUTF16(aSessionId); - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, - sid, - aExpiryTime] () - { - proxy->OnExpirationChange(sid, aExpiryTime); - }) - ); -} - -void -GMPCDMCallbackProxy::SessionClosed(const nsCString& aSessionId) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - bool keyStatusesChange = false; - auto sid = NS_ConvertUTF8toUTF16(aSessionId); - { - CDMCaps::AutoLock caps(mProxy->Capabilites()); - keyStatusesChange = caps.RemoveKeysForSession(NS_ConvertUTF8toUTF16(aSessionId)); - } - if (keyStatusesChange) { - RefPtr<CDMProxy> proxy = mProxy; - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, sid] () - { - proxy->OnKeyStatusesChange(sid); - }) - ); - } - - RefPtr<CDMProxy> proxy = mProxy; - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, sid] () - { - proxy->OnSessionClosed(sid); - }) - ); -} - -void -GMPCDMCallbackProxy::SessionError(const nsCString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsCString& aMessage) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr<CDMProxy> proxy = mProxy; - auto sid = NS_ConvertUTF8toUTF16(aSessionId); - auto msg = NS_ConvertUTF8toUTF16(aMessage); - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, - sid, - aException, - aSystemCode, - msg] () - { - proxy->OnSessionError(sid, - aException, - aSystemCode, - msg); - }) - ); -} - -void -GMPCDMCallbackProxy::BatchedKeyStatusChanged(const nsCString& aSessionId, - const nsTArray<CDMKeyInfo>& aKeyInfos) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - BatchedKeyStatusChangedInternal(aSessionId, aKeyInfos); -} - -void -GMPCDMCallbackProxy::BatchedKeyStatusChangedInternal(const nsCString& aSessionId, - const nsTArray<CDMKeyInfo>& aKeyInfos) -{ - bool keyStatusesChange = false; - { - CDMCaps::AutoLock caps(mProxy->Capabilites()); - for (size_t i = 0; i < aKeyInfos.Length(); i++) { - keyStatusesChange |= - caps.SetKeyStatus(aKeyInfos[i].mKeyId, - NS_ConvertUTF8toUTF16(aSessionId), - aKeyInfos[i].mStatus); - } - } - if (keyStatusesChange) { - RefPtr<CDMProxy> proxy = mProxy; - auto sid = NS_ConvertUTF8toUTF16(aSessionId); - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, sid] () - { - proxy->OnKeyStatusesChange(sid); - }) - ); - } -} - -void -GMPCDMCallbackProxy::Decrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray<uint8_t>& aDecryptedData) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - mProxy->OnDecrypted(aId, aResult, aDecryptedData); -} - -void -GMPCDMCallbackProxy::Terminated() -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr<CDMProxy> proxy = mProxy; - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy] () - { - proxy->Terminated(); - }) - ); -} - -} // namespace mozilla diff --git a/dom/media/gmp/GMPCDMCallbackProxy.h b/dom/media/gmp/GMPCDMCallbackProxy.h deleted file mode 100644 index d2cc806825..0000000000 --- a/dom/media/gmp/GMPCDMCallbackProxy.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#ifndef GMPCDMCallbackProxy_h_ -#define GMPCDMCallbackProxy_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 GMPCDMCallbackProxy : public GMPDecryptorProxyCallback { -public: - - void SetDecryptorId(uint32_t aId) override; - - void SetSessionId(uint32_t aCreateSessionToken, - const nsCString& aSessionId) override; - - void ResolveLoadSessionPromise(uint32_t aPromiseId, - bool aSuccess) override; - - void ResolvePromise(uint32_t aPromiseId) override; - - void RejectPromise(uint32_t aPromiseId, - nsresult aException, - const nsCString& aSessionId) override; - - void SessionMessage(const nsCString& aSessionId, - dom::MediaKeyMessageType aMessageType, - const nsTArray<uint8_t>& aMessage) override; - - void ExpirationChange(const nsCString& aSessionId, - UnixTime aExpiryTime) override; - - void SessionClosed(const nsCString& aSessionId) override; - - void SessionError(const nsCString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsCString& aMessage) override; - - void Decrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray<uint8_t>& aDecryptedData) override; - - void BatchedKeyStatusChanged(const nsCString& aSessionId, - const nsTArray<CDMKeyInfo>& aKeyInfos) override; - - void Terminated() override; - - ~GMPCDMCallbackProxy() {} - -private: - friend class GMPCDMProxy; - explicit GMPCDMCallbackProxy(CDMProxy* aProxy); - - void BatchedKeyStatusChangedInternal(const nsCString& aSessionId, - const nsTArray<CDMKeyInfo>& aKeyInfos); - // Warning: Weak ref. - CDMProxy* mProxy; -}; - -} // namespace mozilla - -#endif // GMPCDMCallbackProxy_h_ diff --git a/dom/media/gmp/GMPCDMProxy.cpp b/dom/media/gmp/GMPCDMProxy.cpp deleted file mode 100644 index 0f19586321..0000000000 --- a/dom/media/gmp/GMPCDMProxy.cpp +++ /dev/null @@ -1,798 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#include "GMPCDMProxy.h" -#include "mozilla/EMEUtils.h" -#include "mozilla/PodOperations.h" - -#include "mozilla/dom/MediaKeys.h" -#include "mozilla/dom/MediaKeySession.h" - -#include "mozIGeckoMediaPluginService.h" -#include "nsContentCID.h" -#include "nsIConsoleService.h" -#include "nsPrintfCString.h" -#include "nsServiceManagerUtils.h" -#include "nsString.h" -#include "prenv.h" -#include "GMPCDMCallbackProxy.h" -#include "GMPService.h" -#include "MainThreadUtils.h" -#include "MediaData.h" - -namespace mozilla { - -GMPCDMProxy::GMPCDMProxy(dom::MediaKeys* aKeys, - const nsAString& aKeySystem, - GMPCrashHelper* aCrashHelper, - bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired) - : CDMProxy(aKeys, - aKeySystem, - aDistinctiveIdentifierRequired, - aPersistentStateRequired) - , mCrashHelper(aCrashHelper) - , mCDM(nullptr) - , mDecryptionJobCount(0) - , mShutdownCalled(false) - , mDecryptorId(0) - , mCreatePromiseId(0) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_COUNT_CTOR(GMPCDMProxy); -} - -GMPCDMProxy::~GMPCDMProxy() -{ - MOZ_COUNT_DTOR(GMPCDMProxy); -} - -void -GMPCDMProxy::Init(PromiseId aPromiseId, - const nsAString& aOrigin, - const nsAString& aTopLevelOrigin, - const nsAString& aGMPName, - bool aInPrivateBrowsing) -{ - MOZ_ASSERT(NS_IsMainThread()); - NS_ENSURE_TRUE_VOID(!mKeys.IsNull()); - - EME_LOG("GMPCDMProxy::Init (%s, %s) %s", - NS_ConvertUTF16toUTF8(aOrigin).get(), - NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(), - (aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing")); - - nsCString pluginVersion; - if (!mOwnerThread) { - nsCOMPtr<mozIGeckoMediaPluginService> mps = - do_GetService("@mozilla.org/gecko-media-plugin-service;1"); - if (!mps) { - RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get MediaPluginService in GMPCDMProxy::Init")); - return; - } - mps->GetThread(getter_AddRefs(mOwnerThread)); - if (!mOwnerThread) { - RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get GMP thread GMPCDMProxy::Init")); - return; - } - } - - if (aGMPName.IsEmpty()) { - RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - nsPrintfCString("Unknown GMP for keysystem '%s'", NS_ConvertUTF16toUTF8(mKeySystem).get())); - return; - } - - nsAutoPtr<InitData> data(new InitData()); - data->mPromiseId = aPromiseId; - data->mOrigin = aOrigin; - data->mTopLevelOrigin = aTopLevelOrigin; - data->mGMPName = aGMPName; - data->mInPrivateBrowsing = aInPrivateBrowsing; - data->mCrashHelper = mCrashHelper; - nsCOMPtr<nsIRunnable> task( - NewRunnableMethod<nsAutoPtr<InitData>>(this, - &GMPCDMProxy::gmp_Init, - Move(data))); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -#ifdef DEBUG -bool -GMPCDMProxy::IsOnOwnerThread() -{ - return NS_GetCurrentThread() == mOwnerThread; -} -#endif - -void -GMPCDMProxy::gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData) -{ - EME_LOG("GMPCDMProxy::gmp_InitDone"); - if (mShutdownCalled) { - if (aCDM) { - aCDM->Close(); - } - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("GMPCDMProxy was shut down before init could complete")); - return; - } - if (!aCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("GetGMPDecryptor failed to return a CDM")); - return; - } - - mCDM = aCDM; - mCallback = new GMPCDMCallbackProxy(this); - mCDM->Init(mCallback, - mDistinctiveIdentifierRequired, - mPersistentStateRequired); - - // Await the OnSetDecryptorId callback. - mCreatePromiseId = aData->mPromiseId; -} - -void GMPCDMProxy::OnSetDecryptorId(uint32_t aId) -{ - MOZ_ASSERT(mCreatePromiseId); - mDecryptorId = aId; - nsCOMPtr<nsIRunnable> task( - NewRunnableMethod<uint32_t>(this, - &GMPCDMProxy::OnCDMCreated, - mCreatePromiseId)); - NS_DispatchToMainThread(task); -} - -class gmp_InitDoneCallback : public GetGMPDecryptorCallback -{ -public: - gmp_InitDoneCallback(GMPCDMProxy* aGMPCDMProxy, - nsAutoPtr<GMPCDMProxy::InitData>&& aData) - : mGMPCDMProxy(aGMPCDMProxy), - mData(Move(aData)) - { - } - - void Done(GMPDecryptorProxy* aCDM) - { - mGMPCDMProxy->gmp_InitDone(aCDM, Move(mData)); - } - -private: - RefPtr<GMPCDMProxy> mGMPCDMProxy; - nsAutoPtr<GMPCDMProxy::InitData> mData; -}; - -class gmp_InitGetGMPDecryptorCallback : public GetNodeIdCallback -{ -public: - gmp_InitGetGMPDecryptorCallback(GMPCDMProxy* aGMPCDMProxy, - nsAutoPtr<GMPCDMProxy::InitData>&& aData) - : mGMPCDMProxy(aGMPCDMProxy), - mData(aData) - { - } - - void Done(nsresult aResult, const nsACString& aNodeId) - { - mGMPCDMProxy->gmp_InitGetGMPDecryptor(aResult, aNodeId, Move(mData)); - } - -private: - RefPtr<GMPCDMProxy> mGMPCDMProxy; - nsAutoPtr<GMPCDMProxy::InitData> mData; -}; - -void -GMPCDMProxy::gmp_Init(nsAutoPtr<InitData>&& aData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - - nsCOMPtr<mozIGeckoMediaPluginService> mps = - do_GetService("@mozilla.org/gecko-media-plugin-service;1"); - if (!mps) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get MediaPluginService in GMPCDMProxy::gmp_Init")); - return; - } - - // Make a copy before we transfer ownership of aData to the - // gmp_InitGetGMPDecryptorCallback. - InitData data(*aData); - UniquePtr<GetNodeIdCallback> callback( - new gmp_InitGetGMPDecryptorCallback(this, Move(aData))); - nsresult rv = mps->GetNodeId(data.mOrigin, - data.mTopLevelOrigin, - data.mGMPName, - data.mInPrivateBrowsing, - Move(callback)); - if (NS_FAILED(rv)) { - RejectPromise(data.mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Call to GetNodeId() failed early")); - } -} - -void -GMPCDMProxy::gmp_InitGetGMPDecryptor(nsresult aResult, - const nsACString& aNodeId, - nsAutoPtr<InitData>&& aData) -{ - uint32_t promiseID = aData->mPromiseId; - if (NS_FAILED(aResult)) { - RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("GetNodeId() called back, but with a failure result")); - return; - } - - mNodeId = aNodeId; - MOZ_ASSERT(!GetNodeId().IsEmpty()); - - nsCOMPtr<mozIGeckoMediaPluginService> mps = - do_GetService("@mozilla.org/gecko-media-plugin-service;1"); - if (!mps) { - RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get MediaPluginService in GMPCDMProxy::gmp_InitGetGMPDecryptor")); - return; - } - - EME_LOG("GMPCDMProxy::gmp_Init (%s, %s) %s NodeId=%s", - NS_ConvertUTF16toUTF8(aData->mOrigin).get(), - NS_ConvertUTF16toUTF8(aData->mTopLevelOrigin).get(), - (aData->mInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"), - GetNodeId().get()); - - nsTArray<nsCString> tags; - tags.AppendElement(NS_ConvertUTF16toUTF8(mKeySystem)); - - // Note: must capture helper refptr here, before the Move() - // when we create the GetGMPDecryptorCallback below. - RefPtr<GMPCrashHelper> crashHelper = Move(aData->mCrashHelper); - UniquePtr<GetGMPDecryptorCallback> callback(new gmp_InitDoneCallback(this, - Move(aData))); - nsresult rv = mps->GetGMPDecryptor(crashHelper, - &tags, - GetNodeId(), - Move(callback)); - if (NS_FAILED(rv)) { - RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Call to GetGMPDecryptor() failed early")); - } -} - -void -GMPCDMProxy::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, - NS_LITERAL_CSTRING("Null CDM in OnCDMCreated()")); - } -} - -void -GMPCDMProxy::CreateSession(uint32_t aCreateSessionToken, - dom::MediaKeySessionType aSessionType, - PromiseId aPromiseId, - const nsAString& aInitDataType, - nsTArray<uint8_t>& aInitData) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mOwnerThread); - - nsAutoPtr<CreateSessionData> data(new CreateSessionData()); - data->mSessionType = aSessionType; - data->mCreateSessionToken = aCreateSessionToken; - data->mPromiseId = aPromiseId; - data->mInitDataType = NS_ConvertUTF16toUTF8(aInitDataType); - data->mInitData = Move(aInitData); - - nsCOMPtr<nsIRunnable> task( - NewRunnableMethod<nsAutoPtr<CreateSessionData>>(this, &GMPCDMProxy::gmp_CreateSession, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -GMPSessionType -ToGMPSessionType(dom::MediaKeySessionType aSessionType) { - switch (aSessionType) { - case dom::MediaKeySessionType::Temporary: return kGMPTemporySession; - case dom::MediaKeySessionType::Persistent_license: return kGMPPersistentSession; - default: return kGMPTemporySession; - }; -}; - -void -GMPCDMProxy::gmp_CreateSession(nsAutoPtr<CreateSessionData> aData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Null CDM in gmp_CreateSession")); - return; - } - mCDM->CreateSession(aData->mCreateSessionToken, - aData->mPromiseId, - aData->mInitDataType, - aData->mInitData, - ToGMPSessionType(aData->mSessionType)); -} - -void -GMPCDMProxy::LoadSession(PromiseId aPromiseId, - const nsAString& aSessionId) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mOwnerThread); - - nsAutoPtr<SessionOpData> data(new SessionOpData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - nsCOMPtr<nsIRunnable> task( - NewRunnableMethod<nsAutoPtr<SessionOpData>>(this, &GMPCDMProxy::gmp_LoadSession, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -GMPCDMProxy::gmp_LoadSession(nsAutoPtr<SessionOpData> aData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Null CDM in gmp_LoadSession")); - return; - } - mCDM->LoadSession(aData->mPromiseId, aData->mSessionId); -} - -void -GMPCDMProxy::SetServerCertificate(PromiseId aPromiseId, - nsTArray<uint8_t>& aCert) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mOwnerThread); - - nsAutoPtr<SetServerCertificateData> data(new SetServerCertificateData()); - data->mPromiseId = aPromiseId; - data->mCert = Move(aCert); - nsCOMPtr<nsIRunnable> task( - NewRunnableMethod<nsAutoPtr<SetServerCertificateData>>(this, &GMPCDMProxy::gmp_SetServerCertificate, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -GMPCDMProxy::gmp_SetServerCertificate(nsAutoPtr<SetServerCertificateData> aData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Null CDM in gmp_SetServerCertificate")); - return; - } - mCDM->SetServerCertificate(aData->mPromiseId, aData->mCert); -} - -void -GMPCDMProxy::UpdateSession(const nsAString& aSessionId, - PromiseId aPromiseId, - nsTArray<uint8_t>& aResponse) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mOwnerThread); - NS_ENSURE_TRUE_VOID(!mKeys.IsNull()); - - nsAutoPtr<UpdateSessionData> data(new UpdateSessionData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - data->mResponse = Move(aResponse); - nsCOMPtr<nsIRunnable> task( - NewRunnableMethod<nsAutoPtr<UpdateSessionData>>(this, &GMPCDMProxy::gmp_UpdateSession, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -GMPCDMProxy::gmp_UpdateSession(nsAutoPtr<UpdateSessionData> aData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Null CDM in gmp_UpdateSession")); - return; - } - mCDM->UpdateSession(aData->mPromiseId, - aData->mSessionId, - aData->mResponse); -} - -void -GMPCDMProxy::CloseSession(const nsAString& aSessionId, - PromiseId aPromiseId) -{ - MOZ_ASSERT(NS_IsMainThread()); - NS_ENSURE_TRUE_VOID(!mKeys.IsNull()); - - nsAutoPtr<SessionOpData> data(new SessionOpData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - nsCOMPtr<nsIRunnable> task( - NewRunnableMethod<nsAutoPtr<SessionOpData>>(this, &GMPCDMProxy::gmp_CloseSession, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -GMPCDMProxy::gmp_CloseSession(nsAutoPtr<SessionOpData> aData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Null CDM in gmp_CloseSession")); - return; - } - mCDM->CloseSession(aData->mPromiseId, aData->mSessionId); -} - -void -GMPCDMProxy::RemoveSession(const nsAString& aSessionId, - PromiseId aPromiseId) -{ - MOZ_ASSERT(NS_IsMainThread()); - NS_ENSURE_TRUE_VOID(!mKeys.IsNull()); - - nsAutoPtr<SessionOpData> data(new SessionOpData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - nsCOMPtr<nsIRunnable> task( - NewRunnableMethod<nsAutoPtr<SessionOpData>>(this, &GMPCDMProxy::gmp_RemoveSession, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -GMPCDMProxy::gmp_RemoveSession(nsAutoPtr<SessionOpData> aData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Null CDM in gmp_RemoveSession")); - return; - } - mCDM->RemoveSession(aData->mPromiseId, aData->mSessionId); -} - -void -GMPCDMProxy::Shutdown() -{ - MOZ_ASSERT(NS_IsMainThread()); - mKeys.Clear(); - // Note: This may end up being the last owning reference to the GMPCDMProxy. - nsCOMPtr<nsIRunnable> task(NewRunnableMethod(this, &GMPCDMProxy::gmp_Shutdown)); - if (mOwnerThread) { - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); - } -} - -void -GMPCDMProxy::gmp_Shutdown() -{ - MOZ_ASSERT(IsOnOwnerThread()); - - mShutdownCalled = true; - - // 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->PostResult(AbortedErr); - } - mDecryptionJobs.Clear(); - - if (mCDM) { - mCDM->Close(); - mCDM = nullptr; - } -} - -void -GMPCDMProxy::RejectPromise(PromiseId aId, nsresult aCode, - const nsCString& aReason) -{ - if (NS_IsMainThread()) { - if (!mKeys.IsNull()) { - mKeys->RejectPromise(aId, aCode, aReason); - } - } else { - nsCOMPtr<nsIRunnable> task(new RejectPromiseTask(this, aId, aCode, - aReason)); - NS_DispatchToMainThread(task); - } -} - -void -GMPCDMProxy::ResolvePromise(PromiseId aId) -{ - if (NS_IsMainThread()) { - if (!mKeys.IsNull()) { - mKeys->ResolvePromise(aId); - } else { - NS_WARNING("GMPCDMProxy unable to resolve promise!"); - } - } else { - nsCOMPtr<nsIRunnable> task; - task = NewRunnableMethod<PromiseId>(this, - &GMPCDMProxy::ResolvePromise, - aId); - NS_DispatchToMainThread(task); - } -} - -const nsCString& -GMPCDMProxy::GetNodeId() const -{ - return mNodeId; -} - -void -GMPCDMProxy::OnSetSessionId(uint32_t aCreateSessionToken, - const nsAString& aSessionId) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - - RefPtr<dom::MediaKeySession> session(mKeys->GetPendingSession(aCreateSessionToken)); - if (session) { - session->SetSessionId(aSessionId); - } -} - -void -GMPCDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - mKeys->OnSessionLoaded(aPromiseId, aSuccess); -} - -void -GMPCDMProxy::OnSessionMessage(const nsAString& aSessionId, - dom::MediaKeyMessageType aMessageType, - nsTArray<uint8_t>& aMessage) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId)); - if (session) { - session->DispatchKeyMessage(aMessageType, aMessage); - } -} - -void -GMPCDMProxy::OnKeyStatusesChange(const nsAString& aSessionId) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId)); - if (session) { - session->DispatchKeyStatusesChange(); - } -} - -void -GMPCDMProxy::OnExpirationChange(const nsAString& aSessionId, - GMPTimestamp aExpiryTime) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId)); - if (session) { - session->SetExpiration(static_cast<double>(aExpiryTime)); - } -} - -void -GMPCDMProxy::OnSessionClosed(const nsAString& aSessionId) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId)); - if (session) { - session->OnClosed(); - } -} - -void -GMPCDMProxy::OnDecrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray<uint8_t>& aDecryptedData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - gmp_Decrypted(aId, aResult, aDecryptedData); -} - -static void -LogToConsole(const nsAString& aMsg) -{ - nsCOMPtr<nsIConsoleService> 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 -GMPCDMProxy::OnSessionError(const nsAString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsAString& aMsg) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - RefPtr<dom::MediaKeySession> session(mKeys->GetSession(aSessionId)); - if (session) { - session->DispatchKeyError(aSystemCode); - } - LogToConsole(aMsg); -} - -void -GMPCDMProxy::OnRejectPromise(uint32_t aPromiseId, - nsresult aDOMException, - const nsCString& aMsg) -{ - MOZ_ASSERT(NS_IsMainThread()); - RejectPromise(aPromiseId, aDOMException, aMsg); -} - -const nsString& -GMPCDMProxy::KeySystem() const -{ - return mKeySystem; -} - -CDMCaps& -GMPCDMProxy::Capabilites() { - return mCapabilites; -} - -RefPtr<GMPCDMProxy::DecryptPromise> -GMPCDMProxy::Decrypt(MediaRawData* aSample) -{ - RefPtr<DecryptJob> job(new DecryptJob(aSample)); - RefPtr<DecryptPromise> promise(job->Ensure()); - - nsCOMPtr<nsIRunnable> task( - NewRunnableMethod<RefPtr<DecryptJob>>(this, &GMPCDMProxy::gmp_Decrypt, job)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); - return promise; -} - -void -GMPCDMProxy::gmp_Decrypt(RefPtr<DecryptJob> aJob) -{ - MOZ_ASSERT(IsOnOwnerThread()); - - if (!mCDM) { - aJob->PostResult(AbortedErr); - return; - } - - aJob->mId = ++mDecryptionJobCount; - nsTArray<uint8_t> data; - data.AppendElements(aJob->mSample->Data(), aJob->mSample->Size()); - mCDM->Decrypt(aJob->mId, aJob->mSample->mCrypto, data); - mDecryptionJobs.AppendElement(aJob.forget()); -} - -void -GMPCDMProxy::gmp_Decrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray<uint8_t>& aDecryptedData) -{ - MOZ_ASSERT(IsOnOwnerThread()); -#ifdef DEBUG - bool jobIdFound = false; -#endif - for (size_t i = 0; i < mDecryptionJobs.Length(); i++) { - DecryptJob* job = mDecryptionJobs[i]; - if (job->mId == aId) { -#ifdef DEBUG - jobIdFound = true; -#endif - job->PostResult(aResult, aDecryptedData); - mDecryptionJobs.RemoveElementAt(i); - } - } -#ifdef DEBUG - if (!jobIdFound) { - NS_WARNING("GMPDecryptorChild returned incorrect job ID"); - } -#endif -} - -void -GMPCDMProxy::DecryptJob::PostResult(DecryptStatus aResult) -{ - nsTArray<uint8_t> empty; - PostResult(aResult, empty); -} - -void -GMPCDMProxy::DecryptJob::PostResult(DecryptStatus aResult, - const nsTArray<uint8_t>& aDecryptedData) -{ - if (aDecryptedData.Length() != mSample->Size()) { - NS_WARNING("CDM returned incorrect number of decrypted bytes"); - } - if (aResult == Ok) { - nsAutoPtr<MediaRawDataWriter> writer(mSample->CreateWriter()); - PodCopy(writer->Data(), - aDecryptedData.Elements(), - std::min<size_t>(aDecryptedData.Length(), mSample->Size())); - } else if (aResult == NoKeyErr) { - NS_WARNING("CDM returned NoKeyErr"); - // We still have the encrypted sample, so we can re-enqueue it to be - // decrypted again once the key is usable again. - } else { - nsAutoCString str("CDM returned decode failure DecryptStatus="); - str.AppendInt(aResult); - NS_WARNING(str.get()); - } - mPromise.Resolve(DecryptResult(aResult, mSample), __func__); -} - -void -GMPCDMProxy::GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId, - nsTArray<nsCString>& aSessionIds) -{ - CDMCaps::AutoLock caps(Capabilites()); - caps.GetSessionIdsForKeyId(aKeyId, aSessionIds); -} - -void -GMPCDMProxy::Terminated() -{ - MOZ_ASSERT(NS_IsMainThread()); - NS_WARNING("CDM terminated"); - if (mCreatePromiseId) { - RejectPromise(mCreatePromiseId, - NS_ERROR_DOM_MEDIA_FATAL_ERR, - NS_LITERAL_CSTRING("Crashed waiting for CDM to initialize")); - mCreatePromiseId = 0; - } - if (!mKeys.IsNull()) { - mKeys->Terminated(); - } -} - -uint32_t -GMPCDMProxy::GetDecryptorId() -{ - return mDecryptorId; -} - -} // namespace mozilla diff --git a/dom/media/gmp/GMPCDMProxy.h b/dom/media/gmp/GMPCDMProxy.h deleted file mode 100644 index a7fae235b6..0000000000 --- a/dom/media/gmp/GMPCDMProxy.h +++ /dev/null @@ -1,265 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#ifndef GMPCDMProxy_h_ -#define GMPCDMProxy_h_ - -#include "mozilla/CDMProxy.h" -#include "GMPCDMCallbackProxy.h" -#include "GMPDecryptorProxy.h" - -namespace mozilla { -class MediaRawData; - -// Implementation of CDMProxy which is based on GMP architecture. -class GMPCDMProxy : public CDMProxy { -public: - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPCDMProxy, override) - - typedef MozPromise<DecryptResult, DecryptResult, /* IsExclusive = */ true> DecryptPromise; - - GMPCDMProxy(dom::MediaKeys* aKeys, - const nsAString& aKeySystem, - GMPCrashHelper* aCrashHelper, - bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired); - - void Init(PromiseId aPromiseId, - const nsAString& aOrigin, - const nsAString& aTopLevelOrigin, - const nsAString& aGMPName, - bool aInPrivateBrowsing) override; - - void OnSetDecryptorId(uint32_t aId) override; - - void CreateSession(uint32_t aCreateSessionToken, - dom::MediaKeySessionType aSessionType, - PromiseId aPromiseId, - const nsAString& aInitDataType, - nsTArray<uint8_t>& aInitData) override; - - void LoadSession(PromiseId aPromiseId, - const nsAString& aSessionId) override; - - void SetServerCertificate(PromiseId aPromiseId, - nsTArray<uint8_t>& aCert) override; - - void UpdateSession(const nsAString& aSessionId, - PromiseId aPromiseId, - nsTArray<uint8_t>& aResponse) override; - - void CloseSession(const nsAString& aSessionId, - PromiseId aPromiseId) override; - - void RemoveSession(const nsAString& aSessionId, - PromiseId aPromiseId) override; - - void Shutdown() override; - - void Terminated() override; - - const nsCString& GetNodeId() const override; - - void OnSetSessionId(uint32_t aCreateSessionToken, - const nsAString& aSessionId) override; - - void OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess) override; - - void OnSessionMessage(const nsAString& aSessionId, - dom::MediaKeyMessageType aMessageType, - nsTArray<uint8_t>& aMessage) override; - - void OnExpirationChange(const nsAString& aSessionId, - GMPTimestamp aExpiryTime) override; - - void OnSessionClosed(const nsAString& aSessionId) override; - - void OnSessionError(const nsAString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsAString& aMsg) override; - - void OnRejectPromise(uint32_t aPromiseId, - nsresult aDOMException, - const nsCString& aMsg) override; - - RefPtr<DecryptPromise> Decrypt(MediaRawData* aSample) override; - - void OnDecrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray<uint8_t>& aDecryptedData) override; - - void RejectPromise(PromiseId aId, nsresult aExceptionCode, - const nsCString& aReason) override; - - void ResolvePromise(PromiseId aId) override; - - const nsString& KeySystem() const override; - - CDMCaps& Capabilites() override; - - void OnKeyStatusesChange(const nsAString& aSessionId) override; - - void GetSessionIdsForKeyId(const nsTArray<uint8_t>& aKeyId, - nsTArray<nsCString>& aSessionIds) override; - -#ifdef DEBUG - bool IsOnOwnerThread() override; -#endif - - uint32_t GetDecryptorId() override; - -private: - friend class gmp_InitDoneCallback; - friend class gmp_InitGetGMPDecryptorCallback; - - struct InitData { - uint32_t mPromiseId; - nsString mOrigin; - nsString mTopLevelOrigin; - nsString mGMPName; - RefPtr<GMPCrashHelper> mCrashHelper; - bool mInPrivateBrowsing; - }; - - // GMP thread only. - void gmp_Init(nsAutoPtr<InitData>&& aData); - void gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr<InitData>&& aData); - void gmp_InitGetGMPDecryptor(nsresult aResult, - const nsACString& aNodeId, - nsAutoPtr<InitData>&& aData); - - // GMP thread only. - void gmp_Shutdown(); - - // Main thread only. - void OnCDMCreated(uint32_t aPromiseId); - - struct CreateSessionData { - dom::MediaKeySessionType mSessionType; - uint32_t mCreateSessionToken; - PromiseId mPromiseId; - nsCString mInitDataType; - nsTArray<uint8_t> mInitData; - }; - // GMP thread only. - void gmp_CreateSession(nsAutoPtr<CreateSessionData> aData); - - struct SessionOpData { - PromiseId mPromiseId; - nsCString mSessionId; - }; - // GMP thread only. - void gmp_LoadSession(nsAutoPtr<SessionOpData> aData); - - struct SetServerCertificateData { - PromiseId mPromiseId; - nsTArray<uint8_t> mCert; - }; - // GMP thread only. - void gmp_SetServerCertificate(nsAutoPtr<SetServerCertificateData> aData); - - struct UpdateSessionData { - PromiseId mPromiseId; - nsCString mSessionId; - nsTArray<uint8_t> mResponse; - }; - // GMP thread only. - void gmp_UpdateSession(nsAutoPtr<UpdateSessionData> aData); - - // GMP thread only. - void gmp_CloseSession(nsAutoPtr<SessionOpData> aData); - - // GMP thread only. - void gmp_RemoveSession(nsAutoPtr<SessionOpData> aData); - - class DecryptJob { - public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DecryptJob) - - explicit DecryptJob(MediaRawData* aSample) - : mId(0) - , mSample(aSample) - { - } - - void PostResult(DecryptStatus aResult, - const nsTArray<uint8_t>& aDecryptedData); - void PostResult(DecryptStatus aResult); - - RefPtr<DecryptPromise> Ensure() { - return mPromise.Ensure(__func__); - } - - uint32_t mId; - RefPtr<MediaRawData> mSample; - private: - ~DecryptJob() {} - MozPromiseHolder<DecryptPromise> mPromise; - }; - // GMP thread only. - void gmp_Decrypt(RefPtr<DecryptJob> aJob); - - // GMP thread only. - void gmp_Decrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray<uint8_t>& aDecryptedData); - - class RejectPromiseTask : public Runnable { - public: - RejectPromiseTask(GMPCDMProxy* aProxy, - PromiseId aId, - nsresult aCode, - const nsCString& aReason) - : mProxy(aProxy) - , mId(aId) - , mCode(aCode) - , mReason(aReason) - { - } - NS_IMETHOD Run() override { - mProxy->RejectPromise(mId, mCode, mReason); - return NS_OK; - } - private: - RefPtr<GMPCDMProxy> mProxy; - PromiseId mId; - nsresult mCode; - nsCString mReason; - }; - - ~GMPCDMProxy(); - - GMPCrashHelper* mCrashHelper; - - GMPDecryptorProxy* mCDM; - - nsAutoPtr<GMPCDMCallbackProxy> mCallback; - - // Decryption jobs sent to CDM, awaiting result. - // GMP thread only. - nsTArray<RefPtr<DecryptJob>> 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; - - // True if GMPCDMProxy::gmp_Shutdown was called. - // GMP thread only. - bool mShutdownCalled; - - uint32_t mDecryptorId; - - PromiseId mCreatePromiseId; -}; - - -} // namespace mozilla - -#endif // GMPCDMProxy_h_ diff --git a/dom/media/gmp/GMPChild.cpp b/dom/media/gmp/GMPChild.cpp index fa6f2f4c83..0bf9d44036 100644 --- a/dom/media/gmp/GMPChild.cpp +++ b/dom/media/gmp/GMPChild.cpp @@ -22,9 +22,6 @@ #include "GMPUtils.h" #include "prio.h" #include "base/task.h" -#ifdef MOZ_EME -#include "widevine-adapter/WidevineAdapter.h" -#endif using namespace mozilla::ipc; @@ -256,13 +253,7 @@ GMPChild::AnswerStartPlugin(const nsString& aAdapter) return false; } -#ifdef MOZ_EME - bool isWidevine = aAdapter.EqualsLiteral("widevine"); - - GMPAdapter* adapter = (isWidevine) ? new WidevineAdapter() : nullptr; -#else GMPAdapter* adapter = nullptr; -#endif if (!mGMPLoader->Load(libPath.get(), libPath.Length(), mNodeId.BeginWriting(), diff --git a/dom/media/gmp/GMPDecryptorChild.cpp b/dom/media/gmp/GMPDecryptorChild.cpp index 6da3c6c43e..a1b561ab59 100644 --- a/dom/media/gmp/GMPDecryptorChild.cpp +++ b/dom/media/gmp/GMPDecryptorChild.cpp @@ -73,11 +73,6 @@ GMPDecryptorChild::Init(GMPDecryptor* aSession) { MOZ_ASSERT(aSession); mSession = aSession; - // The ID of this decryptor is the IPDL actor ID. Note it's unique inside - // the child process, but not necessarily across all gecko processes. However, - // since GMPDecryptors are segregated by node ID/origin, we shouldn't end up - // with clashes in the content process. - SendSetDecryptorId(Id()); } void diff --git a/dom/media/gmp/GMPDecryptorParent.cpp b/dom/media/gmp/GMPDecryptorParent.cpp index 56474e9736..c41d5d18f5 100644 --- a/dom/media/gmp/GMPDecryptorParent.cpp +++ b/dom/media/gmp/GMPDecryptorParent.cpp @@ -42,19 +42,6 @@ GMPDecryptorParent::~GMPDecryptorParent() { } -bool -GMPDecryptorParent::RecvSetDecryptorId(const uint32_t& aId) -{ -#ifdef MOZ_EME - if (!mIsOpen) { - NS_WARNING("Trying to use a dead GMP decrypter!"); - return false; - } - mCallback->SetDecryptorId(aId); -#endif - return true; -} - nsresult GMPDecryptorParent::Init(GMPDecryptorProxyCallback* aCallback, bool aDistinctiveIdentifierRequired, diff --git a/dom/media/gmp/GMPDecryptorParent.h b/dom/media/gmp/GMPDecryptorParent.h index 30ff246901..3acf7dbd96 100644 --- a/dom/media/gmp/GMPDecryptorParent.h +++ b/dom/media/gmp/GMPDecryptorParent.h @@ -72,8 +72,6 @@ private: // PGMPDecryptorParent - bool RecvSetDecryptorId(const uint32_t& aId) override; - bool RecvSetSessionId(const uint32_t& aCreateSessionToken, const nsCString& aSessionId) override; diff --git a/dom/media/gmp/GMPDecryptorProxy.h b/dom/media/gmp/GMPDecryptorProxy.h index ed16755f89..f9e34a45fd 100644 --- a/dom/media/gmp/GMPDecryptorProxy.h +++ b/dom/media/gmp/GMPDecryptorProxy.h @@ -6,9 +6,6 @@ #ifndef GMPDecryptorProxy_h_ #define GMPDecryptorProxy_h_ -#ifdef MOZ_EME -#include "mozilla/DecryptorProxyCallback.h" -#endif #include "GMPCallbackBase.h" #include "gmp-decryption.h" #include "nsString.h" @@ -17,12 +14,7 @@ namespace mozilla { class CryptoSample; } // namespace mozilla -#ifdef MOZ_EME -class GMPDecryptorProxyCallback : public DecryptorProxyCallback, - public GMPCallbackBase { -#else class GMPDecryptorProxyCallback : public GMPCallbackBase { -#endif public: virtual ~GMPDecryptorProxyCallback() {} diff --git a/dom/media/gmp/GMPParent.cpp b/dom/media/gmp/GMPParent.cpp index e6f7972649..c4a7a84a09 100644 --- a/dom/media/gmp/GMPParent.cpp +++ b/dom/media/gmp/GMPParent.cpp @@ -28,11 +28,6 @@ using mozilla::ipc::GeckoChildProcessHost; #include "WMFDecoderModule.h" #endif -#ifdef MOZ_EME -#include "mozilla/dom/WidevineCDMManifestBinding.h" -#include "widevine-adapter/WidevineAdapter.h" -#endif - namespace mozilla { #undef LOG @@ -654,18 +649,7 @@ GMPParent::ReadGMPMetaData() return ReadGMPInfoFile(infoFile); } -#ifdef MOZ_EME - // Maybe this is the Widevine adapted plugin? - nsCOMPtr<nsIFile> manifestFile; - rv = mDirectory->Clone(getter_AddRefs(manifestFile)); - if (NS_FAILED(rv)) { - return GenericPromise::CreateAndReject(rv, __func__); - } - manifestFile->AppendRelativePath(NS_LITERAL_STRING("manifest.json")); - return ReadChromiumManifestFile(manifestFile); -#else return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); -#endif } RefPtr<GenericPromise> @@ -758,48 +742,8 @@ GMPParent::ReadChromiumManifestFile(nsIFile* aFile) RefPtr<GenericPromise> GMPParent::ParseChromiumManifest(nsString aJSON) { -#ifdef MOZ_EME - LOGD("%s: for '%s'", __FUNCTION__, NS_LossyConvertUTF16toASCII(aJSON).get()); - - MOZ_ASSERT(NS_IsMainThread()); - mozilla::dom::WidevineCDMManifest m; - if (!m.Init(aJSON)) { - return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - nsresult ignored; // Note: ToInteger returns 0 on failure. - if (!WidevineAdapter::Supports(m.mX_cdm_module_versions.ToInteger(&ignored), - m.mX_cdm_interface_versions.ToInteger(&ignored), - m.mX_cdm_host_versions.ToInteger(&ignored))) { - return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); - } - - mDisplayName = NS_ConvertUTF16toUTF8(m.mName); - mDescription = NS_ConvertUTF16toUTF8(m.mDescription); - mVersion = NS_ConvertUTF16toUTF8(m.mVersion); - - GMPCapability video(NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER)); - video.mAPITags.AppendElement(NS_LITERAL_CSTRING("h264")); - video.mAPITags.AppendElement(NS_LITERAL_CSTRING("vp8")); - video.mAPITags.AppendElement(NS_LITERAL_CSTRING("vp9")); - video.mAPITags.AppendElement(kEMEKeySystemWidevine); - mCapabilities.AppendElement(Move(video)); - - GMPCapability decrypt(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR)); - decrypt.mAPITags.AppendElement(kEMEKeySystemWidevine); - mCapabilities.AppendElement(Move(decrypt)); - - MOZ_ASSERT(mName.EqualsLiteral("widevinecdm")); - mAdapter = NS_LITERAL_STRING("widevine"); -#ifdef XP_WIN - mLibs = NS_LITERAL_CSTRING("dxva2.dll"); -#endif - - return GenericPromise::CreateAndResolve(true, __func__); -#else // !MOZ_EME MOZ_ASSERT_UNREACHABLE("don't call me if EME isn't enabled"); return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); -#endif // !MOZ_EME } bool diff --git a/dom/media/gmp/PGMPDecryptor.ipdl b/dom/media/gmp/PGMPDecryptor.ipdl index 06b9b9cb60..207933e8a6 100644 --- a/dom/media/gmp/PGMPDecryptor.ipdl +++ b/dom/media/gmp/PGMPDecryptor.ipdl @@ -53,8 +53,6 @@ child: parent: async __delete__(); - async SetDecryptorId(uint32_t aId); - async SetSessionId(uint32_t aCreateSessionToken, nsCString aSessionId); diff --git a/dom/media/gmp/moz.build b/dom/media/gmp/moz.build index c4da2573fb..82d091168d 100644 --- a/dom/media/gmp/moz.build +++ b/dom/media/gmp/moz.build @@ -70,12 +70,6 @@ EXPORTS += [ 'GMPVideoPlaneImpl.h', ] -if CONFIG['MOZ_EME']: - EXPORTS += [ - 'GMPCDMCallbackProxy.h', - 'GMPCDMProxy.h', - ] - UNIFIED_SOURCES += [ 'GMPAudioDecoderChild.cpp', 'GMPAudioDecoderParent.cpp', @@ -111,17 +105,8 @@ UNIFIED_SOURCES += [ 'GMPVideoPlaneImpl.cpp', ] -if CONFIG['MOZ_EME']: - UNIFIED_SOURCES += [ - 'GMPCDMCallbackProxy.cpp', - 'GMPCDMProxy.cpp', - ] - DIRS += ['rlz'] -if CONFIG['MOZ_EME']: - DIRS += ['widevine-adapter'] - IPDL_SOURCES += [ 'GMPTypes.ipdlh', 'PGMP.ipdl', diff --git a/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp b/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp deleted file mode 100644 index 57d4ecec27..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#include "WidevineAdapter.h" -#include "content_decryption_module.h" -#include "VideoUtils.h" -#include "WidevineDecryptor.h" -#include "WidevineUtils.h" -#include "WidevineVideoDecoder.h" -#include "gmp-api/gmp-entrypoints.h" -#include "gmp-api/gmp-decryption.h" -#include "gmp-api/gmp-video-codec.h" -#include "gmp-api/gmp-platform.h" - -static const GMPPlatformAPI* sPlatform = nullptr; - -namespace mozilla { - -GMPErr GMPGetCurrentTime(GMPTimestamp* aOutTime) { - return sPlatform->getcurrenttime(aOutTime); -} - -// Call on main thread only. -GMPErr GMPSetTimerOnMainThread(GMPTask* aTask, int64_t aTimeoutMS) { - return sPlatform->settimer(aTask, aTimeoutMS); -} - -GMPErr GMPCreateRecord(const char* aRecordName, - uint32_t aRecordNameSize, - GMPRecord** aOutRecord, - GMPRecordClient* aClient) -{ - return sPlatform->createrecord(aRecordName, aRecordNameSize, aOutRecord, aClient); -} - -void -WidevineAdapter::SetAdaptee(PRLibrary* aLib) -{ - mLib = aLib; -} - -void* GetCdmHost(int aHostInterfaceVersion, void* aUserData) -{ - Log("GetCdmHostFunc(%d, %p)", aHostInterfaceVersion, aUserData); - WidevineDecryptor* decryptor = reinterpret_cast<WidevineDecryptor*>(aUserData); - MOZ_ASSERT(decryptor); - return static_cast<cdm::Host_9*>(decryptor); -} - -#define STRINGIFY(s) _STRINGIFY(s) -#define _STRINGIFY(s) #s - -GMPErr -WidevineAdapter::GMPInit(const GMPPlatformAPI* aPlatformAPI) -{ -#ifdef ENABLE_WIDEVINE_LOG - if (getenv("GMP_LOG_FILE")) { - // Clear log file. - FILE* f = fopen(getenv("GMP_LOG_FILE"), "w"); - if (f) { - fclose(f); - } - } -#endif - - sPlatform = aPlatformAPI; - if (!mLib) { - return GMPGenericErr; - } - - auto init = reinterpret_cast<decltype(::INITIALIZE_CDM_MODULE)*>( - PR_FindFunctionSymbol(mLib, STRINGIFY(INITIALIZE_CDM_MODULE))); - if (!init) { - return GMPGenericErr; - } - - Log(STRINGIFY(INITIALIZE_CDM_MODULE)"()"); - init(); - - return GMPNoErr; -} - -GMPErr -WidevineAdapter::GMPGetAPI(const char* aAPIName, - void* aHostAPI, - void** aPluginAPI, - uint32_t aDecryptorId) -{ - Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p", - aAPIName, aHostAPI, aPluginAPI, this, aDecryptorId); - if (!strcmp(aAPIName, GMP_API_DECRYPTOR)) { - if (WidevineDecryptor::GetInstance(aDecryptorId)) { - // We only support one CDM instance per PGMPDecryptor. Fail! - Log("WidevineAdapter::GMPGetAPI() Tried to create more than once CDM per IPDL actor! FAIL!"); - return GMPQuotaExceededErr; - } - auto create = reinterpret_cast<decltype(::CreateCdmInstance)*>( - PR_FindFunctionSymbol(mLib, "CreateCdmInstance")); - if (!create) { - Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p FAILED to find CreateCdmInstance", - aAPIName, aHostAPI, aPluginAPI, this, aDecryptorId); - return GMPGenericErr; - } - - WidevineDecryptor* decryptor = new WidevineDecryptor(); - - auto cdm = reinterpret_cast<cdm::ContentDecryptionModule_9*>( - create(cdm::ContentDecryptionModule_9::kVersion, - kEMEKeySystemWidevine.get(), - kEMEKeySystemWidevine.Length(), - &GetCdmHost, - decryptor)); - if (!cdm) { - Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p FAILED to create cdm", - aAPIName, aHostAPI, aPluginAPI, this, aDecryptorId); - return GMPGenericErr; - } - Log("cdm: 0x%x", cdm); - RefPtr<CDMWrapper> wrapper(new CDMWrapper(cdm, decryptor)); - decryptor->SetCDM(wrapper, aDecryptorId); - *aPluginAPI = decryptor; - - } else if (!strcmp(aAPIName, GMP_API_VIDEO_DECODER)) { - RefPtr<CDMWrapper> wrapper = WidevineDecryptor::GetInstance(aDecryptorId); - if (!wrapper) { - Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p No cdm for video decoder", - aAPIName, aHostAPI, aPluginAPI, thiss, aDecryptorId); - return GMPGenericErr; - } - *aPluginAPI = new WidevineVideoDecoder(static_cast<GMPVideoHost*>(aHostAPI), - wrapper); - } - return *aPluginAPI ? GMPNoErr : GMPNotImplementedErr; -} - -void -WidevineAdapter::GMPShutdown() -{ - Log("WidevineAdapter::GMPShutdown()"); - - decltype(::DeinitializeCdmModule)* deinit; - deinit = (decltype(deinit))(PR_FindFunctionSymbol(mLib, "DeinitializeCdmModule")); - if (deinit) { - Log("DeinitializeCdmModule()"); - deinit(); - } -} - -void -WidevineAdapter::GMPSetNodeId(const char* aNodeId, uint32_t aLength) -{ - -} - -/* static */ -bool -WidevineAdapter::Supports(int32_t aModuleVersion, - int32_t aInterfaceVersion, - int32_t aHostVersion) -{ - return aModuleVersion == CDM_MODULE_VERSION && - aInterfaceVersion == cdm::ContentDecryptionModule_9::kVersion && - aHostVersion == cdm::Host_9::kVersion; -} - -} // namespace mozilla diff --git a/dom/media/gmp/widevine-adapter/WidevineAdapter.h b/dom/media/gmp/widevine-adapter/WidevineAdapter.h deleted file mode 100644 index 714e041bef..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineAdapter.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#ifndef WidevineAdapter_h_ -#define WidevineAdapter_h_ - -#include "GMPLoader.h" -#include "prlink.h" -#include "GMPUtils.h" - -struct GMPPlatformAPI; - -namespace mozilla { - -class WidevineAdapter : public gmp::GMPAdapter { -public: - - void SetAdaptee(PRLibrary* aLib) override; - - // These are called in place of the corresponding GMP API functions. - GMPErr GMPInit(const GMPPlatformAPI* aPlatformAPI) override; - GMPErr GMPGetAPI(const char* aAPIName, - void* aHostAPI, - void** aPluginAPI, - uint32_t aDecryptorId) override; - void GMPShutdown() override; - void GMPSetNodeId(const char* aNodeId, uint32_t aLength) override; - - static bool Supports(int32_t aModuleVersion, - int32_t aInterfaceVersion, - int32_t aHostVersion); - -private: - PRLibrary* mLib = nullptr; -}; - -GMPErr GMPCreateThread(GMPThread** aThread); -GMPErr GMPRunOnMainThread(GMPTask* aTask); -GMPErr GMPCreateMutex(GMPMutex** aMutex); - -// Call on main thread only. -GMPErr GMPCreateRecord(const char* aRecordName, - uint32_t aRecordNameSize, - GMPRecord** aOutRecord, - GMPRecordClient* aClient); - -// Call on main thread only. -GMPErr GMPSetTimerOnMainThread(GMPTask* aTask, int64_t aTimeoutMS); - -GMPErr GMPGetCurrentTime(GMPTimestamp* aOutTime); - -GMPErr GMPCreateRecordIterator(RecvGMPRecordIteratorPtr aRecvIteratorFunc, - void* aUserArg); - -} // namespace mozilla - -#endif // WidevineAdapter_h_ diff --git a/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp b/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp deleted file mode 100644 index 4d3408804f..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp +++ /dev/null @@ -1,554 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#include "WidevineDecryptor.h" - -#include "WidevineAdapter.h" -#include "WidevineUtils.h" -#include "WidevineFileIO.h" -#include <mozilla/SizePrintfMacros.h> -#include <stdarg.h> -#include "base/time.h" - -using namespace cdm; -using namespace std; - -namespace mozilla { - -static map<uint32_t, RefPtr<CDMWrapper>> sDecryptors; - -/* static */ -RefPtr<CDMWrapper> -WidevineDecryptor::GetInstance(uint32_t aInstanceId) -{ - auto itr = sDecryptors.find(aInstanceId); - if (itr != sDecryptors.end()) { - return itr->second; - } - return nullptr; -} - - -WidevineDecryptor::WidevineDecryptor() - : mCallback(nullptr) -{ - Log("WidevineDecryptor created this=%p", this); - AddRef(); // Released in DecryptingComplete(). -} - -WidevineDecryptor::~WidevineDecryptor() -{ - Log("WidevineDecryptor destroyed this=%p", this); -} - -void -WidevineDecryptor::SetCDM(RefPtr<CDMWrapper> aCDM, uint32_t aInstanceId) -{ - mCDM = aCDM; - mInstanceId = aInstanceId; - sDecryptors[mInstanceId] = aCDM; -} - -void -WidevineDecryptor::Init(GMPDecryptorCallback* aCallback, - bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired) -{ - Log("WidevineDecryptor::Init() this=%p distinctiveId=%d persistentState=%d", - this, aDistinctiveIdentifierRequired, aPersistentStateRequired); - MOZ_ASSERT(aCallback); - mCallback = aCallback; - MOZ_ASSERT(mCDM); - mDistinctiveIdentifierRequired = aDistinctiveIdentifierRequired; - mPersistentStateRequired = aPersistentStateRequired; - if (CDM()) { - CDM()->Initialize(aDistinctiveIdentifierRequired, - aPersistentStateRequired); - } -} - -static SessionType -ToCDMSessionType(GMPSessionType aSessionType) -{ - switch (aSessionType) { - case kGMPTemporySession: return kTemporary; - case kGMPPersistentSession: return kPersistentLicense; - case kGMPSessionInvalid: return kTemporary; - // TODO: kPersistentKeyRelease - } - MOZ_ASSERT(false); // Not supposed to get here. - return kTemporary; -} - -void -WidevineDecryptor::CreateSession(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const char* aInitDataType, - uint32_t aInitDataTypeSize, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType) -{ - Log("Decryptor::CreateSession(token=%d, pid=%d)", aCreateSessionToken, aPromiseId); - InitDataType initDataType; - if (!strcmp(aInitDataType, "cenc")) { - initDataType = kCenc; - } else if (!strcmp(aInitDataType, "webm")) { - initDataType = kWebM; - } else if (!strcmp(aInitDataType, "keyids")) { - initDataType = kKeyIds; - } else { - // Invalid init data type - const char* errorMsg = "Invalid init data type when creating session."; - OnRejectPromise(aPromiseId, kExceptionNotSupportedError, 0, errorMsg, sizeof(errorMsg)); - return; - } - mPromiseIdToNewSessionTokens[aPromiseId] = aCreateSessionToken; - CDM()->CreateSessionAndGenerateRequest(aPromiseId, - ToCDMSessionType(aSessionType), - initDataType, - aInitData, aInitDataSize); -} - -void -WidevineDecryptor::LoadSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) -{ - Log("Decryptor::LoadSession(pid=%d, %s)", aPromiseId, aSessionId); - // TODO: session type?? - CDM()->LoadSession(aPromiseId, kPersistentLicense, aSessionId, aSessionIdLength); -} - -void -WidevineDecryptor::UpdateSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength, - const uint8_t* aResponse, - uint32_t aResponseSize) -{ - Log("Decryptor::UpdateSession(pid=%d, session=%s)", aPromiseId, aSessionId); - CDM()->UpdateSession(aPromiseId, aSessionId, aSessionIdLength, aResponse, aResponseSize); -} - -void -WidevineDecryptor::CloseSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) -{ - Log("Decryptor::CloseSession(pid=%d, session=%s)", aPromiseId, aSessionId); - CDM()->CloseSession(aPromiseId, aSessionId, aSessionIdLength); -} - -void -WidevineDecryptor::RemoveSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) -{ - Log("Decryptor::RemoveSession(%s)", aSessionId); - CDM()->RemoveSession(aPromiseId, aSessionId, aSessionIdLength); -} - -void -WidevineDecryptor::SetServerCertificate(uint32_t aPromiseId, - const uint8_t* aServerCert, - uint32_t aServerCertSize) -{ - Log("Decryptor::SetServerCertificate()"); - CDM()->SetServerCertificate(aPromiseId, aServerCert, aServerCertSize); -} - -class WidevineDecryptedBlock : public cdm::DecryptedBlock { -public: - - WidevineDecryptedBlock() - : mBuffer(nullptr) - , mTimestamp(0) - { - } - - ~WidevineDecryptedBlock() { - if (mBuffer) { - mBuffer->Destroy(); - mBuffer = nullptr; - } - } - - void SetDecryptedBuffer(cdm::Buffer* aBuffer) override { - mBuffer = aBuffer; - } - - cdm::Buffer* DecryptedBuffer() override { - return mBuffer; - } - - void SetTimestamp(int64_t aTimestamp) override { - mTimestamp = aTimestamp; - } - - int64_t Timestamp() const override { - return mTimestamp; - } - -private: - cdm::Buffer* mBuffer; - int64_t mTimestamp; -}; - -void -WidevineDecryptor::Decrypt(GMPBuffer* aBuffer, - GMPEncryptedBufferMetadata* aMetadata) -{ - if (!mCallback) { - Log("WidevineDecryptor::Decrypt() this=%p FAIL; !mCallback", this); - return; - } - const GMPEncryptedBufferMetadata* crypto = aMetadata; - InputBuffer sample; - nsTArray<SubsampleEntry> subsamples; - InitInputBuffer(crypto, aBuffer->Id(), aBuffer->Data(), aBuffer->Size(), sample, subsamples); - WidevineDecryptedBlock decrypted; - Status rv = CDM()->Decrypt(sample, &decrypted); - Log("Decryptor::Decrypt(timestamp=%lld) rv=%d sz=%d", - sample.timestamp, rv, decrypted.DecryptedBuffer()->Size()); - if (rv == kSuccess) { - aBuffer->Resize(decrypted.DecryptedBuffer()->Size()); - memcpy(aBuffer->Data(), - decrypted.DecryptedBuffer()->Data(), - decrypted.DecryptedBuffer()->Size()); - } - mCallback->Decrypted(aBuffer, ToGMPErr(rv)); -} - -void -WidevineDecryptor::DecryptingComplete() -{ - Log("WidevineDecryptor::DecryptingComplete() this=%p", this); - // Drop our references to the CDMWrapper. When any other references - // held elsewhere are dropped (for example references held by a - // WidevineVideoDecoder, or a runnable), the CDMWrapper destroys - // the CDM. - mCDM = nullptr; - sDecryptors.erase(mInstanceId); - mCallback = nullptr; - Release(); -} - -class WidevineBuffer : public cdm::Buffer { -public: - explicit WidevineBuffer(size_t aSize) { - Log("WidevineBuffer(size=" PRIuSIZE ") created", aSize); - mBuffer.SetLength(aSize); - } - ~WidevineBuffer() { - Log("WidevineBuffer(size=" PRIuSIZE ") destroyed", Size()); - } - void Destroy() override { delete this; } - uint32_t Capacity() const override { return mBuffer.Length(); }; - uint8_t* Data() override { return mBuffer.Elements(); } - void SetSize(uint32_t aSize) override { mBuffer.SetLength(aSize); } - uint32_t Size() const override { return mBuffer.Length(); } - -private: - WidevineBuffer(const WidevineBuffer&); - void operator=(const WidevineBuffer&); - - nsTArray<uint8_t> mBuffer; -}; - -Buffer* -WidevineDecryptor::Allocate(uint32_t aCapacity) -{ - Log("Decryptor::Allocate(capacity=%u)", aCapacity); - return new WidevineBuffer(aCapacity); -} - -class TimerTask : public GMPTask { -public: - TimerTask(WidevineDecryptor* aDecryptor, - RefPtr<CDMWrapper> aCDM, - void* aContext) - : mDecryptor(aDecryptor) - , mCDM(aCDM) - , mContext(aContext) - { - } - ~TimerTask() override {} - void Run() override { - mCDM->GetCDM()->TimerExpired(mContext); - } - void Destroy() override { delete this; } -private: - RefPtr<WidevineDecryptor> mDecryptor; - RefPtr<CDMWrapper> mCDM; - void* mContext; -}; - -void -WidevineDecryptor::SetTimer(int64_t aDelayMs, void* aContext) -{ - Log("Decryptor::SetTimer(delay_ms=%lld, context=0x%x)", aDelayMs, aContext); - if (mCDM) { - GMPSetTimerOnMainThread(new TimerTask(this, mCDM, aContext), aDelayMs); - } -} - -Time -WidevineDecryptor::GetCurrentWallTime() -{ - return base::Time::Now().ToDoubleT(); -} - -void -WidevineDecryptor::OnResolveKeyStatusPromise(uint32_t aPromiseId, - cdm::KeyStatus aKeyStatus) { - //TODO: The callback of GetStatusForPolicy. See Mozilla bug 1404230. -} - -void -WidevineDecryptor::OnResolveNewSessionPromise(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdSize) -{ - if (!mCallback) { - Log("Decryptor::OnResolveNewSessionPromise(aPromiseId=0x%d) FAIL; !mCallback", aPromiseId); - return; - } - Log("Decryptor::OnResolveNewSessionPromise(aPromiseId=0x%d)", aPromiseId); - auto iter = mPromiseIdToNewSessionTokens.find(aPromiseId); - if (iter == mPromiseIdToNewSessionTokens.end()) { - Log("FAIL: Decryptor::OnResolveNewSessionPromise(aPromiseId=%d) unknown aPromiseId", aPromiseId); - return; - } - mCallback->SetSessionId(iter->second, aSessionId, aSessionIdSize); - mCallback->ResolvePromise(aPromiseId); - mPromiseIdToNewSessionTokens.erase(iter); -} - -void -WidevineDecryptor::OnResolvePromise(uint32_t aPromiseId) -{ - if (!mCallback) { - Log("Decryptor::OnResolvePromise(aPromiseId=0x%d) FAIL; !mCallback", aPromiseId); - return; - } - Log("Decryptor::OnResolvePromise(aPromiseId=%d)", aPromiseId); - mCallback->ResolvePromise(aPromiseId); -} - -static GMPDOMException -ConvertCDMExceptionToGMPDOMException(cdm::Exception aException) -{ - switch (aException) { - case kExceptionNotSupportedError: return kGMPNotSupportedError; - case kExceptionInvalidStateError: return kGMPInvalidStateError; - case kExceptionTypeError: return kGMPTypeError; - case kExceptionQuotaExceededError: return kGMPQuotaExceededError; - case kUnknownError: return kGMPInvalidModificationError; // Note: Unique placeholder. - case kClientError: return kGMPAbortError; // Note: Unique placeholder. - case kOutputError: return kGMPSecurityError; // Note: Unique placeholder. - }; - return kGMPInvalidStateError; // Note: Unique placeholder. -} - -// Align with spec, the Exceptions used by CDM to reject promises . -// https://w3c.github.io/encrypted-media/#exceptions -cdm::Exception -ConvertCDMErrorToCDMException(cdm::Error error) { - switch (error) { - case cdm::kNotSupportedError: - return cdm::Exception::kExceptionNotSupportedError; - case cdm::kInvalidStateError: - return cdm::Exception::kExceptionInvalidStateError; - case cdm::kInvalidAccessError: - return cdm::Exception::kExceptionTypeError; - case cdm::kQuotaExceededError: - return cdm::Exception::kExceptionQuotaExceededError; - - case cdm::kUnknownError: - case cdm::kClientError: - case cdm::kOutputError: - break; - } - - return cdm::Exception::kExceptionInvalidStateError; -} - -void -WidevineDecryptor::OnRejectPromise(uint32_t aPromiseId, - cdm::Exception aException, - uint32_t aSystemCode, - const char* aErrorMessage, - uint32_t aErrorMessageSize) -{ - if (!mCallback) { - Log("Decryptor::OnRejectPromise(aPromiseId=%d, err=%d, sysCode=%u, msg=%s) FAIL; !mCallback", - aPromiseId, (int)aException, aSystemCode, aErrorMessage); - return; - } - Log("Decryptor::OnRejectPromise(aPromiseId=%d, err=%d, sysCode=%u, msg=%s)", - aPromiseId, (int)aException, aSystemCode, aErrorMessage); - mCallback->RejectPromise(aPromiseId, - ConvertCDMExceptionToGMPDOMException(aException), - !aErrorMessageSize ? "" : aErrorMessage, - aErrorMessageSize); -} - -static GMPSessionMessageType -ToGMPMessageType(MessageType message_type) -{ - switch (message_type) { - case kLicenseRequest: return kGMPLicenseRequest; - case kLicenseRenewal: return kGMPLicenseRenewal; - case kLicenseRelease: return kGMPLicenseRelease; - } - return kGMPMessageInvalid; -} - -void -WidevineDecryptor::OnSessionMessage(const char* aSessionId, - uint32_t aSessionIdSize, - cdm::MessageType aMessageType, - const char* aMessage, - uint32_t aMessageSize) -{ - if (!mCallback) { - Log("Decryptor::OnSessionMessage() FAIL; !mCallback"); - return; - } - Log("Decryptor::OnSessionMessage()"); - mCallback->SessionMessage(aSessionId, - aSessionIdSize, - ToGMPMessageType(aMessageType), - reinterpret_cast<const uint8_t*>(aMessage), - aMessageSize); -} - -static GMPMediaKeyStatus -ToGMPKeyStatus(KeyStatus aStatus) -{ - switch (aStatus) { - case kUsable: return kGMPUsable; - case kInternalError: return kGMPInternalError; - case kExpired: return kGMPExpired; - case kOutputRestricted: return kGMPOutputRestricted; - case kOutputDownscaled: return kGMPOutputDownscaled; - case kStatusPending: return kGMPStatusPending; - case kReleased: return kGMPReleased; - } - return kGMPUnknown; -} - -void -WidevineDecryptor::OnSessionKeysChange(const char* aSessionId, - uint32_t aSessionIdSize, - bool aHasAdditionalUsableKey, - const KeyInformation* aKeysInfo, - uint32_t aKeysInfoCount) -{ - if (!mCallback) { - Log("Decryptor::OnSessionKeysChange() FAIL; !mCallback"); - return; - } - Log("Decryptor::OnSessionKeysChange()"); - - nsTArray<GMPMediaKeyInfo> key_infos; - for (uint32_t i = 0; i < aKeysInfoCount; i++) { - key_infos.AppendElement(GMPMediaKeyInfo(aKeysInfo[i].key_id, - aKeysInfo[i].key_id_size, - ToGMPKeyStatus(aKeysInfo[i].status))); - } - mCallback->BatchedKeyStatusChanged(aSessionId, aSessionIdSize, - key_infos.Elements(), key_infos.Length()); -} - -static GMPTimestamp -ToGMPTime(Time aCDMTime) -{ - return static_cast<GMPTimestamp>(aCDMTime * 1000); -} - -void -WidevineDecryptor::OnExpirationChange(const char* aSessionId, - uint32_t aSessionIdSize, - Time aNewExpiryTime) -{ - if (!mCallback) { - Log("Decryptor::OnExpirationChange(sid=%s) t=%lf FAIL; !mCallback", - aSessionId, aNewExpiryTime); - return; - } - Log("Decryptor::OnExpirationChange(sid=%s) t=%lf", aSessionId, aNewExpiryTime); - GMPTimestamp expiry = ToGMPTime(aNewExpiryTime); - if (aNewExpiryTime == 0) { - return; - } - mCallback->ExpirationChange(aSessionId, aSessionIdSize, expiry); -} - -void -WidevineDecryptor::OnSessionClosed(const char* aSessionId, - uint32_t aSessionIdSize) -{ - if (!mCallback) { - Log("Decryptor::OnSessionClosed(sid=%s) FAIL; !mCallback", aSessionId); - return; - } - Log("Decryptor::OnSessionClosed(sid=%s)", aSessionId); - mCallback->SessionClosed(aSessionId, aSessionIdSize); -} - -void -WidevineDecryptor::SendPlatformChallenge(const char* aServiceId, - uint32_t aServiceIdSize, - const char* aChallenge, - uint32_t aChallengeSize) -{ - Log("Decryptor::SendPlatformChallenge(service_id=%s)", aServiceId); -} - -void -WidevineDecryptor::EnableOutputProtection(uint32_t aDesiredProtectionMask) -{ - Log("Decryptor::EnableOutputProtection(mask=0x%x)", aDesiredProtectionMask); -} - -void -WidevineDecryptor::QueryOutputProtectionStatus() -{ - Log("Decryptor::QueryOutputProtectionStatus()"); -} - -void -WidevineDecryptor::OnDeferredInitializationDone(StreamType aStreamType, - Status aDecoderStatus) -{ - Log("Decryptor::OnDeferredInitializationDone()"); -} - -FileIO* -WidevineDecryptor::CreateFileIO(FileIOClient* aClient) -{ - Log("Decryptor::CreateFileIO()"); - if (!mPersistentStateRequired) { - return nullptr; - } - return new WidevineFileIO(aClient); -} - -void -WidevineDecryptor::RequestStorageId(uint32_t aVersion) -{ - Log("Decryptor::RequestStorageId() aVersion = %u", aVersion); - if (aVersion >= 0x80000000) { - mCDM->OnStorageId(aVersion, nullptr, 0); - return; - } - - //TODO: Need to provide a menaingful buffer instead of a dummy one. - mCDM->OnStorageId(aVersion, new uint8_t[1024*1024], 1024 * 1024); -} - -} // namespace mozilla diff --git a/dom/media/gmp/widevine-adapter/WidevineDecryptor.h b/dom/media/gmp/widevine-adapter/WidevineDecryptor.h deleted file mode 100644 index f291c321d3..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineDecryptor.h +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#ifndef WidevineDecryptor_h_ -#define WidevineDecryptor_h_ - -#include "stddef.h" -#include "content_decryption_module.h" -#include "gmp-api/gmp-decryption.h" -#include "mozilla/RefPtr.h" -#include "WidevineUtils.h" -#include <map> - -namespace mozilla { - -class WidevineDecryptor : public GMPDecryptor - , public cdm::Host_9 -{ -public: - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WidevineDecryptor) - - WidevineDecryptor(); - - void SetCDM(RefPtr<CDMWrapper> aCDM, uint32_t aDecryptorId); - - static RefPtr<CDMWrapper> GetInstance(uint32_t aDecryptorId); - - // GMPDecryptor - void Init(GMPDecryptorCallback* aCallback, - bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired) override; - - void CreateSession(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const char* aInitDataType, - uint32_t aInitDataTypeSize, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType) override; - - void LoadSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) override; - - void UpdateSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength, - const uint8_t* aResponse, - uint32_t aResponseSize) override; - - void CloseSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) override; - - void RemoveSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) override; - - void SetServerCertificate(uint32_t aPromiseId, - const uint8_t* aServerCert, - uint32_t aServerCertSize) override; - - void Decrypt(GMPBuffer* aBuffer, - GMPEncryptedBufferMetadata* aMetadata) override; - - void DecryptingComplete() override; - - - // cdm::Host_9 implementation - cdm::Buffer* Allocate(uint32_t aCapacity) override; - void SetTimer(int64_t aDelayMs, void* aContext) override; - cdm::Time GetCurrentWallTime() override; - // cdm::Host_9 interface - void OnResolveKeyStatusPromise(uint32_t aPromiseId, - cdm::KeyStatus aKeyStatus) override; - void OnResolveNewSessionPromise(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdSize) override; - void OnResolvePromise(uint32_t aPromiseId) override; - void OnRejectPromise(uint32_t aPromiseId, - cdm::Exception aException, - uint32_t aSystemCode, - const char* aErrorMessage, - uint32_t aErrorMessageSize) override; - void OnSessionMessage(const char* aSessionId, - uint32_t aSessionIdSize, - cdm::MessageType aMessageType, - const char* aMessage, - uint32_t aMessageSize) override; - void OnSessionKeysChange(const char* aSessionId, - uint32_t aSessionIdSize, - bool aHasAdditionalUsableKey, - const cdm::KeyInformation* aKeysInfo, - uint32_t aKeysInfoCount) override; - void OnExpirationChange(const char* aSessionId, - uint32_t aSessionIdSize, - cdm::Time aNewExpiryTime) override; - void OnSessionClosed(const char* aSessionId, - uint32_t aSessionIdSize) override; - void SendPlatformChallenge(const char* aServiceId, - uint32_t aServiceIdSize, - const char* aChallenge, - uint32_t aChallengeSize) override; - void EnableOutputProtection(uint32_t aDesiredProtectionMask) override; - void QueryOutputProtectionStatus() override; - void OnDeferredInitializationDone(cdm::StreamType aStreamType, - cdm::Status aDecoderStatus) override; - // cdm::Host_9 interface - // NOTE: the interface has changed upstream. - void RequestStorageId(uint32_t aVersion) override; - cdm::FileIO* CreateFileIO(cdm::FileIOClient* aClient) override; - - GMPDecryptorCallback* Callback() const { return mCallback; } - RefPtr<CDMWrapper> GetCDMWrapper() const { return mCDM; } -private: - ~WidevineDecryptor(); - RefPtr<CDMWrapper> mCDM; - cdm::ContentDecryptionModule_9* CDM() { return mCDM->GetCDM(); } - - GMPDecryptorCallback* mCallback; - std::map<uint32_t, uint32_t> mPromiseIdToNewSessionTokens; - bool mDistinctiveIdentifierRequired = false; - bool mPersistentStateRequired = false; - uint32_t mInstanceId = 0; -}; - -} // namespace mozilla - -#endif // WidevineDecryptor_h_ diff --git a/dom/media/gmp/widevine-adapter/WidevineFileIO.cpp b/dom/media/gmp/widevine-adapter/WidevineFileIO.cpp deleted file mode 100644 index b5fb1d705c..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineFileIO.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "WidevineFileIO.h" -#include "WidevineUtils.h" -#include "WidevineAdapter.h" - -using namespace cdm; - -namespace mozilla { - -void -WidevineFileIO::Open(const char* aFilename, uint32_t aFilenameLength) -{ - mName = std::string(aFilename, aFilename + aFilenameLength); - GMPRecord* record = nullptr; - GMPErr err = GMPCreateRecord(aFilename, aFilenameLength, &record, static_cast<GMPRecordClient*>(this)); - if (GMP_FAILED(err)) { - Log("WidevineFileIO::Open() '%s' GMPCreateRecord failed", mName.c_str()); - mClient->OnOpenComplete(FileIOClient::kError); - return; - } - if (GMP_FAILED(record->Open())) { - Log("WidevineFileIO::Open() '%s' record open failed", mName.c_str()); - mClient->OnOpenComplete(FileIOClient::kError); - return; - } - - Log("WidevineFileIO::Open() '%s'", mName.c_str()); - mRecord = record; -} - -void -WidevineFileIO::Read() -{ - if (!mRecord) { - Log("WidevineFileIO::Read() '%s' used uninitialized!", mName.c_str()); - mClient->OnReadComplete(FileIOClient::kError, nullptr, 0); - return; - } - Log("WidevineFileIO::Read() '%s'", mName.c_str()); - mRecord->Read(); -} - -void -WidevineFileIO::Write(const uint8_t* aData, uint32_t aDataSize) -{ - if (!mRecord) { - Log("WidevineFileIO::Write() '%s' used uninitialized!", mName.c_str()); - mClient->OnWriteComplete(FileIOClient::kError); - return; - } - mRecord->Write(aData, aDataSize); -} - -void -WidevineFileIO::Close() -{ - Log("WidevineFileIO::Close() '%s'", mName.c_str()); - if (mRecord) { - mRecord->Close(); - mRecord = nullptr; - } - delete this; -} - -static FileIOClient::Status -GMPToWidevineFileStatus(GMPErr aStatus) -{ - switch (aStatus) { - case GMPRecordInUse: return FileIOClient::kInUse; - case GMPNoErr: return FileIOClient::kSuccess; - default: return FileIOClient::kError; - } -} - -void -WidevineFileIO::OpenComplete(GMPErr aStatus) -{ - Log("WidevineFileIO::OpenComplete() '%s' status=%d", mName.c_str(), aStatus); - mClient->OnOpenComplete(GMPToWidevineFileStatus(aStatus)); -} - -void -WidevineFileIO::ReadComplete(GMPErr aStatus, - const uint8_t* aData, - uint32_t aDataSize) -{ - Log("WidevineFileIO::OnReadComplete() '%s' status=%d", mName.c_str(), aStatus); - mClient->OnReadComplete(GMPToWidevineFileStatus(aStatus), aData, aDataSize); -} - -void -WidevineFileIO::WriteComplete(GMPErr aStatus) -{ - Log("WidevineFileIO::WriteComplete() '%s' status=%d", mName.c_str(), aStatus); - mClient->OnWriteComplete(GMPToWidevineFileStatus(aStatus)); -} - -} // namespace mozilla diff --git a/dom/media/gmp/widevine-adapter/WidevineFileIO.h b/dom/media/gmp/widevine-adapter/WidevineFileIO.h deleted file mode 100644 index 63003d9b60..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineFileIO.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#ifndef WidevineFileIO_h_ -#define WidevineFileIO_h_ - -#include <stddef.h> -#include "content_decryption_module.h" -#include "gmp-api/gmp-storage.h" -#include <string> - -namespace mozilla { - -class WidevineFileIO : public cdm::FileIO - , public GMPRecordClient -{ -public: - explicit WidevineFileIO(cdm::FileIOClient* aClient) - : mClient(aClient) - , mRecord(nullptr) - {} - - // cdm::FileIO - void Open(const char* aFilename, uint32_t aFilenameLength) override; - void Read() override; - void Write(const uint8_t* aData, uint32_t aDataSize) override; - void Close() override; - - // GMPRecordClient - void OpenComplete(GMPErr aStatus) override; - void ReadComplete(GMPErr aStatus, - const uint8_t* aData, - uint32_t aDataSize) override; - void WriteComplete(GMPErr aStatus) override; - -private: - cdm::FileIOClient* mClient; - GMPRecord* mRecord; - std::string mName; -}; - -} // namespace mozilla - -#endif // WidevineFileIO_h_
\ No newline at end of file diff --git a/dom/media/gmp/widevine-adapter/WidevineUtils.cpp b/dom/media/gmp/widevine-adapter/WidevineUtils.cpp deleted file mode 100644 index 10c6c2e18c..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineUtils.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#include "WidevineUtils.h" -#include "WidevineDecryptor.h" - -#include "gmp-api/gmp-errors.h" -#include <stdarg.h> -#include <stdio.h> - -namespace mozilla { - -#ifdef ENABLE_WIDEVINE_LOG -void -Log(const char* aFormat, ...) -{ - va_list ap; - va_start(ap, aFormat); - const size_t len = 1024; - char buf[len]; - vsnprintf(buf, len, aFormat, ap); - va_end(ap); - if (getenv("GMP_LOG_FILE")) { - FILE* f = fopen(getenv("GMP_LOG_FILE"), "a"); - if (f) { - fprintf(f, "%s\n", buf); - fflush(f); - fclose(f); - f = nullptr; - } - } else { - printf("LOG: %s\n", buf); - } -} -#endif // ENABLE_WIDEVINE_LOG - -GMPErr -ToGMPErr(cdm::Status aStatus) -{ - switch (aStatus) { - case cdm::kSuccess: return GMPNoErr; - case cdm::kNeedMoreData: return GMPGenericErr; - case cdm::kNoKey: return GMPNoKeyErr; - case cdm::kInitializationError: return GMPGenericErr; - case cdm::kDecryptError: return GMPCryptoErr; - case cdm::kDecodeError: return GMPDecodeErr; - case cdm::kDeferredInitialization: return GMPGenericErr; - default: return GMPGenericErr; - } -} - -void InitInputBuffer(const GMPEncryptedBufferMetadata* aCrypto, - int64_t aTimestamp, - const uint8_t* aData, - size_t aDataSize, - cdm::InputBuffer &aInputBuffer, - nsTArray<cdm::SubsampleEntry> &aSubsamples) -{ - if (aCrypto) { - aInputBuffer.key_id = aCrypto->KeyId(); - aInputBuffer.key_id_size = aCrypto->KeyIdSize(); - aInputBuffer.iv = aCrypto->IV(); - aInputBuffer.iv_size = aCrypto->IVSize(); - aInputBuffer.num_subsamples = aCrypto->NumSubsamples(); - aSubsamples.SetCapacity(aInputBuffer.num_subsamples); - const uint16_t* clear = aCrypto->ClearBytes(); - const uint32_t* cipher = aCrypto->CipherBytes(); - for (size_t i = 0; i < aCrypto->NumSubsamples(); i++) { - aSubsamples.AppendElement(cdm::SubsampleEntry(clear[i], cipher[i])); - } - } - aInputBuffer.data = aData; - aInputBuffer.data_size = aDataSize; - aInputBuffer.subsamples = aSubsamples.Elements(); - aInputBuffer.timestamp = aTimestamp; -} - -CDMWrapper::CDMWrapper(cdm::ContentDecryptionModule_9* aCDM, - WidevineDecryptor* aDecryptor) - : mCDM(aCDM) - , mDecryptor(aDecryptor) -{ - MOZ_ASSERT(mCDM); -} - -CDMWrapper::~CDMWrapper() -{ - Log("CDMWrapper destroying CDM=%p", mCDM); - mCDM->Destroy(); - mCDM = nullptr; -} - -} // namespace mozilla diff --git a/dom/media/gmp/widevine-adapter/WidevineUtils.h b/dom/media/gmp/widevine-adapter/WidevineUtils.h deleted file mode 100644 index 2f6137fe3b..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineUtils.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#ifndef WidevineUtils_h_ -#define WidevineUtils_h_ - -#include "stddef.h" -#include "content_decryption_module.h" -#include "gmp-api/gmp-decryption.h" -#include "gmp-api/gmp-platform.h" -#include "nsISupportsImpl.h" -#include "nsTArray.h" - -namespace mozilla { - -// Uncomment for logging... -//#define ENABLE_WIDEVINE_LOG 1 -#ifdef ENABLE_WIDEVINE_LOG -void -Log(const char* aFormat, ...); -#else -#define Log(...) -#endif // ENABLE_WIDEVINE_LOG - - -#define ENSURE_TRUE(condition, rv) { \ - if (!(condition)) {\ - Log("ENSURE_TRUE FAILED %s:%d", __FILE__, __LINE__); \ - return rv; \ - } \ -} \ - -#define ENSURE_GMP_SUCCESS(err, rv) { \ - if (GMP_FAILED(err)) {\ - Log("ENSURE_GMP_SUCCESS FAILED %s:%d", __FILE__, __LINE__); \ - return rv; \ - } \ -} \ - -GMPErr -ToGMPErr(cdm::Status aStatus); - -class WidevineDecryptor; - -class CDMWrapper { -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMWrapper) - - explicit CDMWrapper(cdm::ContentDecryptionModule_9* aCDM, - WidevineDecryptor* aDecryptor); - cdm::ContentDecryptionModule_9* GetCDM() const { return mCDM; } - void OnStorageId(uint32_t aVersion, const uint8_t* aStorageId, - uint32_t aStorageIdSize) { - mCDM->OnStorageId(aVersion, aStorageId, aStorageIdSize); - } -private: - ~CDMWrapper(); - cdm::ContentDecryptionModule_9* mCDM; - RefPtr<WidevineDecryptor> mDecryptor; -}; - -void InitInputBuffer(const GMPEncryptedBufferMetadata* aCrypto, - int64_t aTimestamp, - const uint8_t* aData, - size_t aDataSize, - cdm::InputBuffer &aInputBuffer, - nsTArray<cdm::SubsampleEntry> &aSubsamples); - -} // namespace mozilla - -#endif // WidevineUtils_h_ diff --git a/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.cpp b/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.cpp deleted file mode 100644 index 70d2fd8e08..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#include "WidevineVideoDecoder.h" - -#include "mp4_demuxer/AnnexB.h" -#include "WidevineUtils.h" -#include "WidevineVideoFrame.h" -#include "mozilla/Move.h" - -using namespace cdm; - -namespace mozilla { - -WidevineVideoDecoder::WidevineVideoDecoder(GMPVideoHost* aVideoHost, - RefPtr<CDMWrapper> aCDMWrapper) - : mVideoHost(aVideoHost) - , mCDMWrapper(Move(aCDMWrapper)) - , mExtraData(new MediaByteBuffer()) - , mSentInput(false) - , mCodecType(kGMPVideoCodecInvalid) - , mReturnOutputCallDepth(0) - , mDrainPending(false) - , mResetInProgress(false) -{ - // Expect to start with a CDM wrapper, will release it in DecodingComplete(). - MOZ_ASSERT(mCDMWrapper); - Log("WidevineVideoDecoder created this=%p", this); - - // Corresponding Release is in DecodingComplete(). - AddRef(); -} - -WidevineVideoDecoder::~WidevineVideoDecoder() -{ - Log("WidevineVideoDecoder destroyed this=%p", this); -} - -static -VideoDecoderConfig::VideoCodecProfile -ToCDMH264Profile(uint8_t aProfile) -{ - switch (aProfile) { - case 66: return VideoDecoderConfig::kH264ProfileBaseline; - case 77: return VideoDecoderConfig::kH264ProfileMain; - case 88: return VideoDecoderConfig::kH264ProfileExtended; - case 100: return VideoDecoderConfig::kH264ProfileHigh; - case 110: return VideoDecoderConfig::kH264ProfileHigh10; - case 122: return VideoDecoderConfig::kH264ProfileHigh422; - case 144: return VideoDecoderConfig::kH264ProfileHigh444Predictive; - } - return VideoDecoderConfig::kUnknownVideoCodecProfile; -} - -void -WidevineVideoDecoder::InitDecode(const GMPVideoCodec& aCodecSettings, - const uint8_t* aCodecSpecific, - uint32_t aCodecSpecificLength, - GMPVideoDecoderCallback* aCallback, - int32_t aCoreCount) -{ - mCallback = aCallback; - VideoDecoderConfig config; - mCodecType = aCodecSettings.mCodecType; - if (mCodecType == kGMPVideoCodecH264) { - config.codec = VideoDecoderConfig::kCodecH264; - const GMPVideoCodecH264* h264 = (const GMPVideoCodecH264*)(aCodecSpecific); - config.profile = ToCDMH264Profile(h264->mAVCC.mProfile); - } else if (mCodecType == kGMPVideoCodecVP8) { - config.codec = VideoDecoderConfig::kCodecVp8; - config.profile = VideoDecoderConfig::kProfileNotNeeded; - } else if (mCodecType == kGMPVideoCodecVP9) { - config.codec = VideoDecoderConfig::kCodecVp9; - config.profile = VideoDecoderConfig::kProfileNotNeeded; - } else { - mCallback->Error(GMPInvalidArgErr); - return; - } - config.format = kYv12; - config.coded_size = Size(aCodecSettings.mWidth, aCodecSettings.mHeight); - mExtraData->AppendElements(aCodecSpecific + 1, aCodecSpecificLength); - config.extra_data = mExtraData->Elements(); - config.extra_data_size = mExtraData->Length(); - Status rv = CDM()->InitializeVideoDecoder(config); - if (rv != kSuccess) { - mCallback->Error(ToGMPErr(rv)); - return; - } - Log("WidevineVideoDecoder::InitDecode() rv=%d", rv); - mAnnexB = mp4_demuxer::AnnexB::ConvertExtraDataToAnnexB(mExtraData); -} - -void -WidevineVideoDecoder::Decode(GMPVideoEncodedFrame* aInputFrame, - bool aMissingFrames, - const uint8_t* aCodecSpecificInfo, - uint32_t aCodecSpecificInfoLength, - int64_t aRenderTimeMs) -{ - // We should not be given new input if a drain has been initiated - MOZ_ASSERT(!mDrainPending); - // We may not get the same out of the CDM decoder as we put in, and there - // may be some latency, i.e. we may need to input (say) 30 frames before - // we receive output. So we need to store the durations of the frames input, - // and retrieve them on output. - mFrameDurations[aInputFrame->TimeStamp()] = aInputFrame->Duration(); - - mSentInput = true; - InputBuffer sample; - - RefPtr<MediaRawData> raw( - new MediaRawData(aInputFrame->Buffer(), aInputFrame->Size())); - if (aInputFrame->Size() && !raw->Data()) { - // OOM. - mCallback->Error(GMPAllocErr); - return; - } - raw->mExtraData = mExtraData; - raw->mKeyframe = (aInputFrame->FrameType() == kGMPKeyFrame); - if (mCodecType == kGMPVideoCodecH264) { - // Convert input from AVCC, which GMPAPI passes in, to AnnexB, which - // Chromium uses internally. - mp4_demuxer::AnnexB::ConvertSampleToAnnexB(raw); - } - - const GMPEncryptedBufferMetadata* crypto = aInputFrame->GetDecryptionData(); - nsTArray<SubsampleEntry> subsamples; - InitInputBuffer(crypto, aInputFrame->TimeStamp(), raw->Data(), raw->Size(), sample, subsamples); - - // For keyframes, ConvertSampleToAnnexB will stick the AnnexB extra data - // at the start of the input. So we need to account for that as clear data - // in the subsamples. - if (raw->mKeyframe && !subsamples.IsEmpty() && mCodecType == kGMPVideoCodecH264) { - subsamples[0].clear_bytes += mAnnexB->Length(); - } - - WidevineVideoFrame frame; - Status rv = CDM()->DecryptAndDecodeFrame(sample, &frame); - Log("WidevineVideoDecoder::Decode(timestamp=%lld) rv=%d", sample.timestamp, rv); - - // Destroy frame, so that the shmem is now free to be used to return - // output to the Gecko process. - aInputFrame->Destroy(); - aInputFrame = nullptr; - - if (rv == kSuccess) { - if (!ReturnOutput(frame)) { - Log("WidevineVideoDecoder::Decode() Failed in ReturnOutput()"); - mCallback->Error(GMPDecodeErr); - return; - } - // A reset should only be started at most at level mReturnOutputCallDepth 1, - // and if it's started it should be finished by that call by the time - // the it returns, so it should always be false by this point. - MOZ_ASSERT(!mResetInProgress); - // Only request more data if we don't have pending samples. - if (mFrameAllocationQueue.empty()) { - MOZ_ASSERT(mCDMWrapper); - mCallback->InputDataExhausted(); - } - } else if (rv == kNeedMoreData) { - MOZ_ASSERT(mCDMWrapper); - mCallback->InputDataExhausted(); - } else { - mCallback->Error(ToGMPErr(rv)); - } - // Finish a drain if pending and we have no pending ReturnOutput calls on the stack. - if (mDrainPending && mReturnOutputCallDepth == 0) { - Drain(); - } -} - -// Util class to assist with counting mReturnOutputCallDepth. -class CounterHelper { -public: - // RAII, increment counter - explicit CounterHelper(int32_t& counter) - : mCounter(counter) - { - mCounter++; - } - - // RAII, decrement counter - ~CounterHelper() - { - mCounter--; - } - -private: - int32_t& mCounter; -}; - -// Util class to make sure GMP frames are freed. Holds a GMPVideoi420Frame* -// and will destroy it when the helper is destroyed unless the held frame -// if forgotten with ForgetFrame. -class FrameDestroyerHelper { -public: - explicit FrameDestroyerHelper(GMPVideoi420Frame*& frame) - : frame(frame) - { - } - - // RAII, destroy frame if held. - ~FrameDestroyerHelper() - { - if (frame) { - frame->Destroy(); - } - frame = nullptr; - } - - // Forget the frame without destroying it. - void ForgetFrame() - { - frame = nullptr; - } - -private: - GMPVideoi420Frame* frame; -}; - - -// Special handing is needed around ReturnOutput as it spins the IPC message -// queue when creating an empty frame and can end up with reentrant calls into -// the class methods. -bool -WidevineVideoDecoder::ReturnOutput(WidevineVideoFrame& aCDMFrame) -{ - MOZ_ASSERT(mReturnOutputCallDepth >= 0); - CounterHelper counterHelper(mReturnOutputCallDepth); - mFrameAllocationQueue.push_back(Move(aCDMFrame)); - if (mReturnOutputCallDepth > 1) { - // In a reentrant call. - return true; - } - while (!mFrameAllocationQueue.empty()) { - MOZ_ASSERT(mReturnOutputCallDepth == 1); - // If we're at call level 1 a reset should not have been started. A - // reset may be received during CreateEmptyFrame below, but we should not - // be in a reset at this stage -- this would indicate receiving decode - // messages before completing our reset, which we should not. - MOZ_ASSERT(!mResetInProgress); - WidevineVideoFrame currentCDMFrame = Move(mFrameAllocationQueue.front()); - mFrameAllocationQueue.pop_front(); - GMPVideoFrame* f = nullptr; - auto err = mVideoHost->CreateFrame(kGMPI420VideoFrame, &f); - if (GMP_FAILED(err) || !f) { - Log("Failed to create i420 frame!\n"); - return false; - } - auto gmpFrame = static_cast<GMPVideoi420Frame*>(f); - FrameDestroyerHelper frameDestroyerHelper(gmpFrame); - Size size = currentCDMFrame.Size(); - const int32_t yStride = currentCDMFrame.Stride(VideoFrame::kYPlane); - const int32_t uStride = currentCDMFrame.Stride(VideoFrame::kUPlane); - const int32_t vStride = currentCDMFrame.Stride(VideoFrame::kVPlane); - const int32_t halfHeight = size.height / 2; - // This call can cause a shmem alloc, during this alloc other calls - // may be made to this class and placed on the stack. ***WARNING***: - // other IPC calls can happen during this call, resulting in calls - // being made to the CDM. After this call state can have changed, - // and should be reevaluated. - err = gmpFrame->CreateEmptyFrame(size.width, - size.height, - yStride, - uStride, - vStride); - // Assert possible reentrant calls or resets haven't altered level unexpectedly. - MOZ_ASSERT(mReturnOutputCallDepth == 1); - ENSURE_GMP_SUCCESS(err, false); - - // If a reset started we need to dump the current frame and complete the reset. - if (mResetInProgress) { - MOZ_ASSERT(mCDMWrapper); - MOZ_ASSERT(mFrameAllocationQueue.empty()); - CompleteReset(); - return true; - } - - err = gmpFrame->SetWidth(size.width); - ENSURE_GMP_SUCCESS(err, false); - - err = gmpFrame->SetHeight(size.height); - ENSURE_GMP_SUCCESS(err, false); - - Buffer* buffer = currentCDMFrame.FrameBuffer(); - uint8_t* outBuffer = gmpFrame->Buffer(kGMPYPlane); - ENSURE_TRUE(outBuffer != nullptr, false); - MOZ_ASSERT(gmpFrame->AllocatedSize(kGMPYPlane) >= yStride*size.height); - memcpy(outBuffer, - buffer->Data() + currentCDMFrame.PlaneOffset(VideoFrame::kYPlane), - yStride * size.height); - - outBuffer = gmpFrame->Buffer(kGMPUPlane); - ENSURE_TRUE(outBuffer != nullptr, false); - MOZ_ASSERT(gmpFrame->AllocatedSize(kGMPUPlane) >= uStride * halfHeight); - memcpy(outBuffer, - buffer->Data() + currentCDMFrame.PlaneOffset(VideoFrame::kUPlane), - uStride * halfHeight); - - outBuffer = gmpFrame->Buffer(kGMPVPlane); - ENSURE_TRUE(outBuffer != nullptr, false); - MOZ_ASSERT(gmpFrame->AllocatedSize(kGMPVPlane) >= vStride * halfHeight); - memcpy(outBuffer, - buffer->Data() + currentCDMFrame.PlaneOffset(VideoFrame::kVPlane), - vStride * halfHeight); - - gmpFrame->SetTimestamp(currentCDMFrame.Timestamp()); - - auto d = mFrameDurations.find(currentCDMFrame.Timestamp()); - if (d != mFrameDurations.end()) { - gmpFrame->SetDuration(d->second); - mFrameDurations.erase(d); - } - - // Forget frame so it's not deleted, call back taking ownership. - frameDestroyerHelper.ForgetFrame(); - mCallback->Decoded(gmpFrame); - } - - return true; -} - -void -WidevineVideoDecoder::Reset() -{ - Log("WidevineVideoDecoder::Reset() mSentInput=%d", mSentInput); - // We shouldn't reset if a drain is pending. - MOZ_ASSERT(!mDrainPending); - mResetInProgress = true; - if (mSentInput) { - CDM()->ResetDecoder(kStreamTypeVideo); - } - // Remove queued frames, but do not reset mReturnOutputCallDepth, let the - // ReturnOutput calls unwind and decrement the counter as needed. - mFrameAllocationQueue.clear(); - mFrameDurations.clear(); - // Only if no ReturnOutput calls are in progress can we complete, otherwise - // ReturnOutput needs to finalize the reset. - if (mReturnOutputCallDepth == 0) { - CompleteReset(); - } -} - -void -WidevineVideoDecoder::CompleteReset() -{ - mCallback->ResetComplete(); - mSentInput = false; - mResetInProgress = false; -} - -void -WidevineVideoDecoder::Drain() -{ - Log("WidevineVideoDecoder::Drain()"); - if (mReturnOutputCallDepth > 0) { - Log("Drain call is reentrant, postponing drain"); - mDrainPending = true; - return; - } - - Status rv = kSuccess; - while (rv == kSuccess) { - WidevineVideoFrame frame; - InputBuffer sample; - Status rv = CDM()->DecryptAndDecodeFrame(sample, &frame); - Log("WidevineVideoDecoder::Drain(); DecryptAndDecodeFrame() rv=%d", rv); - if (frame.Format() == kUnknownVideoFormat) { - break; - } - if (rv == kSuccess) { - if (!ReturnOutput(frame)) { - Log("WidevineVideoDecoder::Decode() Failed in ReturnOutput()"); - } - } - } - // Shouldn't be reset while draining. - MOZ_ASSERT(!mResetInProgress); - - CDM()->ResetDecoder(kStreamTypeVideo); - mDrainPending = false; - mCallback->DrainComplete(); -} - -void -WidevineVideoDecoder::DecodingComplete() -{ - Log("WidevineVideoDecoder::DecodingComplete()"); - if (mCDMWrapper) { - CDM()->DeinitializeDecoder(kStreamTypeVideo); - mCDMWrapper = nullptr; - } - // Release that corresponds to AddRef() in constructor. - Release(); -} - -} // namespace mozilla diff --git a/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.h b/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.h deleted file mode 100644 index f5e63519be..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#ifndef WidevineVideoDecoder_h_ -#define WidevineVideoDecoder_h_ - -#include "stddef.h" -#include "content_decryption_module.h" -#include "gmp-api/gmp-video-decode.h" -#include "gmp-api/gmp-video-host.h" -#include "MediaData.h" -#include "nsISupportsImpl.h" -#include "nsTArray.h" -#include "WidevineDecryptor.h" -#include "WidevineVideoFrame.h" -#include <map> -#include <deque> - -namespace mozilla { - -class WidevineVideoDecoder : public GMPVideoDecoder { -public: - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WidevineVideoDecoder) - - WidevineVideoDecoder(GMPVideoHost* aVideoHost, - RefPtr<CDMWrapper> aCDMWrapper); - void InitDecode(const GMPVideoCodec& aCodecSettings, - const uint8_t* aCodecSpecific, - uint32_t aCodecSpecificLength, - GMPVideoDecoderCallback* aCallback, - int32_t aCoreCount) override; - void Decode(GMPVideoEncodedFrame* aInputFrame, - bool aMissingFrames, - const uint8_t* aCodecSpecificInfo, - uint32_t aCodecSpecificInfoLength, - int64_t aRenderTimeMs = -1) override; - void Reset() override; - void Drain() override; - void DecodingComplete() override; - -private: - - ~WidevineVideoDecoder(); - - cdm::ContentDecryptionModule_9* CDM() const { - // CDM should only be accessed before 'DecodingComplete'. - MOZ_ASSERT(mCDMWrapper); - // CDMWrapper ensure the CDM is non-null, no need to check again. - return mCDMWrapper->GetCDM(); - } - - bool ReturnOutput(WidevineVideoFrame& aFrame); - void CompleteReset(); - - GMPVideoHost* mVideoHost; - RefPtr<CDMWrapper> mCDMWrapper; - RefPtr<MediaByteBuffer> mExtraData; - RefPtr<MediaByteBuffer> mAnnexB; - GMPVideoDecoderCallback* mCallback; - std::map<uint64_t, uint64_t> mFrameDurations; - bool mSentInput; - GMPVideoCodecType mCodecType; - // Frames waiting on allocation - std::deque<WidevineVideoFrame> mFrameAllocationQueue; - // Number of calls of ReturnOutput currently in progress. - int32_t mReturnOutputCallDepth; - // If we're waiting to drain. Used to prevent drain completing while - // ReturnOutput calls are still on the stack. - bool mDrainPending; - // If a reset is being performed. Used to track if ReturnOutput should - // dump current frame. - bool mResetInProgress; -}; - -} // namespace mozilla - -#endif // WidevineVideoDecoder_h_ diff --git a/dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp b/dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp deleted file mode 100644 index 4221bf15b8..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#include "WidevineVideoFrame.h" - -#include "WidevineUtils.h" - -using namespace cdm; - -namespace mozilla { - -WidevineVideoFrame::WidevineVideoFrame() - : mFormat(kUnknownVideoFormat) - , mSize(0,0) - , mBuffer(nullptr) - , mTimestamp(0) -{ - Log("WidevineVideoFrame::WidevineVideoFrame() this=%p", this); - memset(mPlaneOffsets, 0, sizeof(mPlaneOffsets)); - memset(mPlaneStrides, 0, sizeof(mPlaneStrides)); -} - -WidevineVideoFrame::WidevineVideoFrame(WidevineVideoFrame&& aOther) - : mFormat(aOther.mFormat) - , mSize(aOther.mSize) - , mBuffer(aOther.mBuffer) - , mTimestamp(aOther.mTimestamp) -{ - Log("WidevineVideoFrame::WidevineVideoFrame(WidevineVideoFrame&&) this=%p, other=%p", - this, &aOther); - memcpy(mPlaneOffsets, aOther.mPlaneOffsets, sizeof(mPlaneOffsets)); - memcpy(mPlaneStrides, aOther.mPlaneStrides, sizeof(mPlaneStrides)); - aOther.mBuffer = nullptr; -} - -WidevineVideoFrame::~WidevineVideoFrame() -{ - if (mBuffer) { - mBuffer->Destroy(); - mBuffer = nullptr; - } -} - -void -WidevineVideoFrame::SetFormat(cdm::VideoFormat aFormat) -{ - Log("WidevineVideoFrame::SetFormat(%d) this=%p", aFormat, this); - mFormat = aFormat; -} - -cdm::VideoFormat -WidevineVideoFrame::Format() const -{ - return mFormat; -} - -void -WidevineVideoFrame::SetSize(cdm::Size aSize) -{ - Log("WidevineVideoFrame::SetSize(%d,%d) this=%p", aSize.width, aSize.height, this); - mSize.width = aSize.width; - mSize.height = aSize.height; -} - -cdm::Size -WidevineVideoFrame::Size() const -{ - return mSize; -} - -void -WidevineVideoFrame::SetFrameBuffer(cdm::Buffer* aFrameBuffer) -{ - Log("WidevineVideoFrame::SetFrameBuffer(%p) this=%p", aFrameBuffer, this); - MOZ_ASSERT(!mBuffer); - mBuffer = aFrameBuffer; -} - -cdm::Buffer* -WidevineVideoFrame::FrameBuffer() -{ - return mBuffer; -} - -void -WidevineVideoFrame::SetPlaneOffset(cdm::VideoFrame::VideoPlane aPlane, uint32_t aOffset) -{ - Log("WidevineVideoFrame::SetPlaneOffset(%d, %d) this=%p", aPlane, aOffset, this); - mPlaneOffsets[aPlane] = aOffset; -} - -uint32_t -WidevineVideoFrame::PlaneOffset(cdm::VideoFrame::VideoPlane aPlane) -{ - return mPlaneOffsets[aPlane]; -} - -void -WidevineVideoFrame::SetStride(cdm::VideoFrame::VideoPlane aPlane, uint32_t aStride) -{ - Log("WidevineVideoFrame::SetStride(%d, %d) this=%p", aPlane, aStride, this); - mPlaneStrides[aPlane] = aStride; -} - -uint32_t -WidevineVideoFrame::Stride(cdm::VideoFrame::VideoPlane aPlane) -{ - return mPlaneStrides[aPlane]; -} - -void -WidevineVideoFrame::SetTimestamp(int64_t timestamp) -{ - Log("WidevineVideoFrame::SetTimestamp(%lld) this=%p", timestamp, this); - mTimestamp = timestamp; -} - -int64_t -WidevineVideoFrame::Timestamp() const -{ - return mTimestamp; -} - -} // namespace mozilla diff --git a/dom/media/gmp/widevine-adapter/WidevineVideoFrame.h b/dom/media/gmp/widevine-adapter/WidevineVideoFrame.h deleted file mode 100644 index 96d4f20f8e..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineVideoFrame.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#ifndef WidevineVideoFrame_h_ -#define WidevineVideoFrame_h_ - -#include "stddef.h" -#include "content_decryption_module.h" -#include <vector> - -namespace mozilla { - -class WidevineVideoFrame : public cdm::VideoFrame { -public: - WidevineVideoFrame(); - WidevineVideoFrame(WidevineVideoFrame&& other); - ~WidevineVideoFrame(); - - void SetFormat(cdm::VideoFormat aFormat) override; - cdm::VideoFormat Format() const override; - - void SetSize(cdm::Size aSize) override; - cdm::Size Size() const override; - - void SetFrameBuffer(cdm::Buffer* aFrameBuffer) override; - cdm::Buffer* FrameBuffer() override; - - void SetPlaneOffset(cdm::VideoFrame::VideoPlane aPlane, uint32_t aOffset) override; - uint32_t PlaneOffset(cdm::VideoFrame::VideoPlane aPlane) override; - - void SetStride(cdm::VideoFrame::VideoPlane aPlane, uint32_t aStride) override; - uint32_t Stride(cdm::VideoFrame::VideoPlane aPlane) override; - - void SetTimestamp(int64_t aTimestamp) override; - int64_t Timestamp() const override; - -protected: - cdm::VideoFormat mFormat; - cdm::Size mSize; - cdm::Buffer* mBuffer; - uint32_t mPlaneOffsets[kMaxPlanes]; - uint32_t mPlaneStrides[kMaxPlanes]; - int64_t mTimestamp; -}; - -} // namespace mozilla - -#endif diff --git a/dom/media/gmp/widevine-adapter/content_decryption_module.h b/dom/media/gmp/widevine-adapter/content_decryption_module.h deleted file mode 100644 index 0539135fbe..0000000000 --- a/dom/media/gmp/widevine-adapter/content_decryption_module.h +++ /dev/null @@ -1,1278 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CDM_CONTENT_DECRYPTION_MODULE_H_ -#define CDM_CONTENT_DECRYPTION_MODULE_H_ - -#include "content_decryption_module_export.h" - -#if defined(_MSC_VER) -typedef unsigned char uint8_t; -typedef unsigned int uint32_t; -typedef int int32_t; -typedef __int64 int64_t; -#else -#include <stdint.h> -#endif - -// Define CDM_CLASS_API to export class types. We have to add visibility -// attributes to make sure virtual tables in CDM consumer and CDM implementation -// are the same. Generally, it was always a good idea, as there're no guarantees -// about that for the internal symbols, but it has only become a practical issue -// after introduction of LTO devirtualization. See more details on -// https://crbug.com/609564#c35 -#if defined(_WIN32) -#if defined(__clang__) -#define CDM_CLASS_API [[clang::lto_visibility_public]] -#else -#define CDM_CLASS_API -#endif -#else // defined(_WIN32) -#define CDM_CLASS_API __attribute__((visibility("default"))) -#endif // defined(_WIN32) - -// The version number must be rolled when the exported functions are updated! -// If the CDM and the adapter use different versions of these functions, the -// adapter will fail to load or crash! -#define CDM_MODULE_VERSION 4 - -// Build the versioned entrypoint name. -// The extra macros are necessary to expand version to an actual value. -#define INITIALIZE_CDM_MODULE \ - BUILD_ENTRYPOINT(InitializeCdmModule, CDM_MODULE_VERSION) -#define BUILD_ENTRYPOINT(name, version) \ - BUILD_ENTRYPOINT_NO_EXPANSION(name, version) -#define BUILD_ENTRYPOINT_NO_EXPANSION(name, version) name##_##version - -extern "C" { -CDM_API void INITIALIZE_CDM_MODULE(); - -CDM_API void DeinitializeCdmModule(); - -// Returns a pointer to the requested CDM Host interface upon success. -// Returns NULL if the requested CDM Host interface is not supported. -// The caller should cast the returned pointer to the type matching -// |host_interface_version|. -typedef void* (*GetCdmHostFunc)(int host_interface_version, void* user_data); - -// Returns a pointer to the requested CDM upon success. -// Returns NULL if an error occurs or the requested |cdm_interface_version| or -// |key_system| is not supported or another error occurs. -// The caller should cast the returned pointer to the type matching -// |cdm_interface_version|. -// Caller retains ownership of arguments and must call Destroy() on the returned -// object. -CDM_API void* CreateCdmInstance( - int cdm_interface_version, - const char* key_system, uint32_t key_system_size, - GetCdmHostFunc get_cdm_host_func, void* user_data); - -CDM_API const char* GetCdmVersion(); -} - -namespace cdm { - -class CDM_CLASS_API AudioFrames; -class CDM_CLASS_API DecryptedBlock; -class CDM_CLASS_API VideoFrame; - -class CDM_CLASS_API Host_8; -class CDM_CLASS_API Host_9; - -enum Status { - kSuccess = 0, - kNeedMoreData, // Decoder needs more data to produce a decoded frame/sample. - kNoKey, // The required decryption key is not available. - kInitializationError, // Initialization error. - kDecryptError, // Decryption failed. - kDecodeError, // Error decoding audio or video. - kDeferredInitialization // Decoder is not ready for initialization. -}; - -// This must at least contain the exceptions defined in the spec: -// https://w3c.github.io/encrypted-media/#exceptions -// The following starts with the list of DOM4 exceptions from: -// http://www.w3.org/TR/dom/#domexception -// Some DOM4 exceptions are not included as they are not expected to be used. -// Should only be used on Host_8 and before. -enum Error { - kNotSupportedError = 9, - kInvalidStateError = 11, - kInvalidAccessError = 15, - kQuotaExceededError = 22, - - // Additional exceptions that do not have assigned codes. - // There are other non-EME-specific values, not included in this list. - kUnknownError = 30, - - // Additional values from previous EME versions. They currently have no - // matching DOMException. - kClientError = 100, - kOutputError = 101 -}; - -// Exceptions used by the CDM to reject promises. -// https://w3c.github.io/encrypted-media/#exceptions -enum Exception { - kExceptionTypeError, - kExceptionNotSupportedError, - kExceptionInvalidStateError, - kExceptionQuotaExceededError -}; - -// Time is defined as the number of seconds since the Epoch -// (00:00:00 UTC, January 1, 1970), not including any added leap second. -// Also see Time definition in spec: https://w3c.github.io/encrypted-media/#time -// Note that Time is defined in millisecond accuracy in the spec but in second -// accuracy here. -typedef double Time; - -// An input buffer can be split into several continuous subsamples. -// A SubsampleEntry specifies the number of clear and cipher bytes in each -// subsample. For example, the following buffer has three subsamples: -// -// |<----- subsample1 ----->|<----- subsample2 ----->|<----- subsample3 ----->| -// | clear1 | cipher1 | clear2 | cipher2 | clear3 | cipher3 | -// -// For decryption, all of the cipher bytes in a buffer should be concatenated -// (in the subsample order) into a single logical stream. The clear bytes should -// not be considered as part of decryption. -// -// Stream to decrypt: | cipher1 | cipher2 | cipher3 | -// Decrypted stream: | decrypted1| decrypted2 | decrypted3 | -// -// After decryption, the decrypted bytes should be copied over the position -// of the corresponding cipher bytes in the original buffer to form the output -// buffer. Following the above example, the decrypted buffer should be: -// -// |<----- subsample1 ----->|<----- subsample2 ----->|<----- subsample3 ----->| -// | clear1 | decrypted1| clear2 | decrypted2 | clear3 | decrypted3 | -// -struct SubsampleEntry { - SubsampleEntry(uint32_t clear_bytes, uint32_t cipher_bytes) - : clear_bytes(clear_bytes), cipher_bytes(cipher_bytes) {} - - uint32_t clear_bytes; - uint32_t cipher_bytes; -}; - -// Represents an input buffer to be decrypted (and possibly decoded). It does -// not own any pointers in this struct. If |iv_size| = 0, the data is -// unencrypted. -struct InputBuffer { - InputBuffer() - : data(nullptr), - data_size(0), - key_id(nullptr), - key_id_size(0), - iv(nullptr), - iv_size(0), - subsamples(nullptr), - num_subsamples(0), - timestamp(0) {} - - const uint8_t* data; // Pointer to the beginning of the input data. - uint32_t data_size; // Size (in bytes) of |data|. - - const uint8_t* key_id; // Key ID to identify the decryption key. - uint32_t key_id_size; // Size (in bytes) of |key_id|. - - const uint8_t* iv; // Initialization vector. - uint32_t iv_size; // Size (in bytes) of |iv|. - - const struct SubsampleEntry* subsamples; - uint32_t num_subsamples; // Number of subsamples in |subsamples|. - - int64_t timestamp; // Presentation timestamp in microseconds. -}; - -struct AudioDecoderConfig { - enum AudioCodec { - kUnknownAudioCodec = 0, - kCodecVorbis, - kCodecAac - }; - - AudioDecoderConfig() - : codec(kUnknownAudioCodec), - channel_count(0), - bits_per_channel(0), - samples_per_second(0), - extra_data(nullptr), - extra_data_size(0) {} - - AudioCodec codec; - int32_t channel_count; - int32_t bits_per_channel; - int32_t samples_per_second; - - // Optional byte data required to initialize audio decoders, such as the - // vorbis setup header. - uint8_t* extra_data; - uint32_t extra_data_size; -}; - -// Supported sample formats for AudioFrames. -enum AudioFormat { - kUnknownAudioFormat = 0, // Unknown format value. Used for error reporting. - kAudioFormatU8, // Interleaved unsigned 8-bit w/ bias of 128. - kAudioFormatS16, // Interleaved signed 16-bit. - kAudioFormatS32, // Interleaved signed 32-bit. - kAudioFormatF32, // Interleaved float 32-bit. - kAudioFormatPlanarS16, // Signed 16-bit planar. - kAudioFormatPlanarF32, // Float 32-bit planar. -}; - -// Surface formats based on FOURCC labels, see: http://www.fourcc.org/yuv.php -// Values are chosen to be consistent with Chromium's VideoPixelFormat values. -enum VideoFormat { - kUnknownVideoFormat = 0, // Unknown format value. Used for error reporting. - kYv12 = 1, // 12bpp YVU planar 1x1 Y, 2x2 VU samples. - kI420 = 2, // 12bpp YUV planar 1x1 Y, 2x2 UV samples. - - // In the following formats, each sample uses 16-bit in storage, while the - // sample value is stored in the least significant N bits where N is - // specified by the number after "P". For example, for YUV420P9, each Y, U, - // and V sample is stored in the least significant 9 bits in a 2-byte block. - kYUV420P9 = 16, - kYUV420P10 = 17, - kYUV422P9 = 18, - kYUV422P10 = 19, - kYUV444P9 = 20, - kYUV444P10 = 21, - kYUV420P12 = 22, - kYUV422P12 = 23, - kYUV444P12 = 24, -}; - -struct Size { - Size() : width(0), height(0) {} - Size(int32_t width, int32_t height) : width(width), height(height) {} - - int32_t width; - int32_t height; -}; - -struct VideoDecoderConfig { - enum VideoCodec { - kUnknownVideoCodec = 0, - kCodecVp8, - kCodecH264, - kCodecVp9 - }; - - enum VideoCodecProfile { - kUnknownVideoCodecProfile = 0, - kProfileNotNeeded, - kH264ProfileBaseline, - kH264ProfileMain, - kH264ProfileExtended, - kH264ProfileHigh, - kH264ProfileHigh10, - kH264ProfileHigh422, - kH264ProfileHigh444Predictive, - // VP9 Profiles are only passed in starting from CDM_9. - kVP9Profile0, - kVP9Profile1, - kVP9Profile2, - kVP9Profile3 - }; - - VideoDecoderConfig() - : codec(kUnknownVideoCodec), - profile(kUnknownVideoCodecProfile), - format(kUnknownVideoFormat), - extra_data(nullptr), - extra_data_size(0) {} - - VideoCodec codec; - VideoCodecProfile profile; - VideoFormat format; - - // Width and height of video frame immediately post-decode. Not all pixels - // in this region are valid. - Size coded_size; - - // Optional byte data required to initialize video decoders, such as H.264 - // AAVC data. - uint8_t* extra_data; - uint32_t extra_data_size; -}; - -enum StreamType { - kStreamTypeAudio = 0, - kStreamTypeVideo = 1 -}; - -// Structure provided to ContentDecryptionModule::OnPlatformChallengeResponse() -// after a platform challenge was initiated via Host::SendPlatformChallenge(). -// All values will be NULL / zero in the event of a challenge failure. -struct PlatformChallengeResponse { - // |challenge| provided during Host::SendPlatformChallenge() combined with - // nonce data and signed with the platform's private key. - const uint8_t* signed_data; - uint32_t signed_data_length; - - // RSASSA-PKCS1-v1_5-SHA256 signature of the |signed_data| block. - const uint8_t* signed_data_signature; - uint32_t signed_data_signature_length; - - // X.509 device specific certificate for the |service_id| requested. - const uint8_t* platform_key_certificate; - uint32_t platform_key_certificate_length; -}; - -// Used when passing arrays of binary data. Does not own the referenced data. -struct BinaryData { - BinaryData() : data(nullptr), length(0) {} - const uint8_t* data; - uint32_t length; -}; - -// The current status of the associated key. The valid types are defined in the -// spec: https://w3c.github.io/encrypted-media/#idl-def-MediaKeyStatus -enum KeyStatus { - kUsable = 0, - kInternalError = 1, - kExpired = 2, - kOutputRestricted = 3, - kOutputDownscaled = 4, - kStatusPending = 5, - kReleased = 6 -}; - -// Used when passing arrays of key information. Does not own the referenced -// data. |system_code| is an additional error code for unusable keys and -// should be 0 when |status| == kUsable. -struct KeyInformation { - KeyInformation() - : key_id(nullptr), - key_id_size(0), - status(kInternalError), - system_code(0) {} - const uint8_t* key_id; - uint32_t key_id_size; - KeyStatus status; - uint32_t system_code; -}; - -// Supported output protection methods for use with EnableOutputProtection() and -// returned by OnQueryOutputProtectionStatus(). -enum OutputProtectionMethods { - kProtectionNone = 0, - kProtectionHDCP = 1 << 0 -}; - -// Connected output link types returned by OnQueryOutputProtectionStatus(). -enum OutputLinkTypes { - kLinkTypeNone = 0, - kLinkTypeUnknown = 1 << 0, - kLinkTypeInternal = 1 << 1, - kLinkTypeVGA = 1 << 2, - kLinkTypeHDMI = 1 << 3, - kLinkTypeDVI = 1 << 4, - kLinkTypeDisplayPort = 1 << 5, - kLinkTypeNetwork = 1 << 6 -}; - -// Result of the QueryOutputProtectionStatus() call. -enum QueryResult { - kQuerySucceeded = 0, - kQueryFailed -}; - -// The Initialization Data Type. The valid types are defined in the spec: -// http://w3c.github.io/encrypted-media/initdata-format-registry.html#registry -enum InitDataType { - kCenc = 0, - kKeyIds = 1, - kWebM = 2 -}; - -// The type of session to create. The valid types are defined in the spec: -// https://w3c.github.io/encrypted-media/#idl-def-SessionType -enum SessionType { - kTemporary = 0, - kPersistentLicense = 1, - kPersistentKeyRelease = 2 -}; - -// The type of the message event. The valid types are defined in the spec: -// https://w3c.github.io/encrypted-media/#idl-def-MediaKeyMessageType -enum MessageType { - kLicenseRequest = 0, - kLicenseRenewal = 1, - kLicenseRelease = 2 -}; - -enum HdcpVersion { - kHdcpVersionNone, - kHdcpVersion1_0, - kHdcpVersion1_1, - kHdcpVersion1_2, - kHdcpVersion1_3, - kHdcpVersion1_4, - kHdcpVersion2_0, - kHdcpVersion2_1, - kHdcpVersion2_2 -}; - -struct Policy { - Policy() : min_hdcp_version(kHdcpVersionNone) {} - - HdcpVersion min_hdcp_version; -}; - -// FileIO interface provides a way for the CDM to store data in a file in -// persistent storage. This interface aims only at providing basic read/write -// capabilities and should not be used as a full fledged file IO API. -// Each CDM and origin (e.g. HTTPS, "foo.example.com", 443) combination has -// its own persistent storage. All instances of a given CDM associated with a -// given origin share the same persistent storage. -// Note to implementors of this interface: -// Per-origin storage and the ability for users to clear it are important. -// See http://www.w3.org/TR/encrypted-media/#privacy-storedinfo. -class CDM_CLASS_API FileIO { - public: - // Opens the file with |file_name| for read and write. - // FileIOClient::OnOpenComplete() will be called after the opening - // operation finishes. - // - When the file is opened by a CDM instance, it will be classified as "in - // use". In this case other CDM instances in the same domain may receive - // kInUse status when trying to open it. - // - |file_name| must only contain letters (A-Za-z), digits(0-9), or "._-". - // It must not start with an underscore ('_'), and must be at least 1 - // character and no more than 256 characters long. - virtual void Open(const char* file_name, uint32_t file_name_size) = 0; - - // Reads the contents of the file. FileIOClient::OnReadComplete() will be - // called with the read status. Read() should not be called if a previous - // Read() or Write() call is still pending; otherwise OnReadComplete() will - // be called with kInUse. - virtual void Read() = 0; - - // Writes |data_size| bytes of |data| into the file. - // FileIOClient::OnWriteComplete() will be called with the write status. - // All existing contents in the file will be overwritten. Calling Write() with - // NULL |data| will clear all contents in the file. Write() should not be - // called if a previous Write() or Read() call is still pending; otherwise - // OnWriteComplete() will be called with kInUse. - virtual void Write(const uint8_t* data, uint32_t data_size) = 0; - - // Closes the file if opened, destroys this FileIO object and releases any - // resources allocated. The CDM must call this method when it finished using - // this object. A FileIO object must not be used after Close() is called. - virtual void Close() = 0; - - protected: - FileIO() {} - virtual ~FileIO() {} -}; - -// Responses to FileIO calls. All responses will be called asynchronously. -// When kError is returned, the FileIO object could be in an error state. All -// following calls (other than Close()) could return kError. The CDM should -// still call Close() to destroy the FileIO object. -class CDM_CLASS_API FileIOClient { - public: - enum Status { - kSuccess = 0, - kInUse, - kError - }; - - // Response to a FileIO::Open() call with the open |status|. - virtual void OnOpenComplete(Status status) = 0; - - // Response to a FileIO::Read() call to provide |data_size| bytes of |data| - // read from the file. - // - kSuccess indicates that all contents of the file has been successfully - // read. In this case, 0 |data_size| means that the file is empty. - // - kInUse indicates that there are other read/write operations pending. - // - kError indicates read failure, e.g. the storage is not open or cannot be - // fully read. - virtual void OnReadComplete(Status status, - const uint8_t* data, uint32_t data_size) = 0; - - // Response to a FileIO::Write() call. - // - kSuccess indicates that all the data has been written into the file - // successfully. - // - kInUse indicates that there are other read/write operations pending. - // - kError indicates write failure, e.g. the storage is not open or cannot be - // fully written. Upon write failure, the contents of the file should be - // regarded as corrupt and should not used. - virtual void OnWriteComplete(Status status) = 0; - - protected: - FileIOClient() {} - virtual ~FileIOClient() {} -}; - -// ContentDecryptionModule interface that all CDMs need to implement. -// The interface is versioned for backward compatibility. -// Note: ContentDecryptionModule implementations must use the allocator -// provided in CreateCdmInstance() to allocate any Buffer that needs to -// be passed back to the caller. Implementations must call Buffer::Destroy() -// when a Buffer is created that will never be returned to the caller. -class CDM_CLASS_API ContentDecryptionModule_8 { - public: - static const int kVersion = 8; - typedef Host_8 Host; - - // Initializes the CDM instance, providing information about permitted - // functionalities. - // If |allow_distinctive_identifier| is false, messages from the CDM, - // such as message events, must not contain a Distinctive Identifier, - // even in an encrypted form. - // If |allow_persistent_state| is false, the CDM must not attempt to - // persist state. Calls to CreateFileIO() will fail. - virtual void Initialize(bool allow_distinctive_identifier, - bool allow_persistent_state) = 0; - - // SetServerCertificate(), CreateSessionAndGenerateRequest(), LoadSession(), - // UpdateSession(), CloseSession(), and RemoveSession() all accept a - // |promise_id|, which must be passed to the completion Host method - // (e.g. Host::OnResolveNewSessionPromise()). - - // Provides a server certificate to be used to encrypt messages to the - // license server. The CDM must respond by calling either - // Host::OnResolvePromise() or Host::OnRejectPromise(). - virtual void SetServerCertificate(uint32_t promise_id, - const uint8_t* server_certificate_data, - uint32_t server_certificate_data_size) = 0; - - // Creates a session given |session_type|, |init_data_type|, and |init_data|. - // The CDM must respond by calling either Host::OnResolveNewSessionPromise() - // or Host::OnRejectPromise(). - virtual void CreateSessionAndGenerateRequest(uint32_t promise_id, - SessionType session_type, - InitDataType init_data_type, - const uint8_t* init_data, - uint32_t init_data_size) = 0; - - // Loads the session of type |session_type| specified by |session_id|. - // The CDM must respond by calling either Host::OnResolveNewSessionPromise() - // or Host::OnRejectPromise(). If the session is not found, call - // Host::OnResolveNewSessionPromise() with session_id = NULL. - virtual void LoadSession(uint32_t promise_id, - SessionType session_type, - const char* session_id, - uint32_t session_id_size) = 0; - - // Updates the session with |response|. The CDM must respond by calling - // either Host::OnResolvePromise() or Host::OnRejectPromise(). - virtual void UpdateSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size, - const uint8_t* response, - uint32_t response_size) = 0; - - // Requests that the CDM close the session. The CDM must respond by calling - // either Host::OnResolvePromise() or Host::OnRejectPromise() when the request - // has been processed. This may be before the session is closed. Once the - // session is closed, Host::OnSessionClosed() must also be called. - virtual void CloseSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size) = 0; - - // Removes any stored session data associated with this session. Will only be - // called for persistent sessions. The CDM must respond by calling either - // Host::OnResolvePromise() or Host::OnRejectPromise() when the request has - // been processed. - virtual void RemoveSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size) = 0; - - // Performs scheduled operation with |context| when the timer fires. - virtual void TimerExpired(void* context) = 0; - - // Decrypts the |encrypted_buffer|. - // - // Returns kSuccess if decryption succeeded, in which case the callee - // should have filled the |decrypted_buffer| and passed the ownership of - // |data| in |decrypted_buffer| to the caller. - // Returns kNoKey if the CDM did not have the necessary decryption key - // to decrypt. - // Returns kDecryptError if any other error happened. - // If the return value is not kSuccess, |decrypted_buffer| should be ignored - // by the caller. - virtual Status Decrypt(const InputBuffer& encrypted_buffer, - DecryptedBlock* decrypted_buffer) = 0; - - // Initializes the CDM audio decoder with |audio_decoder_config|. This - // function must be called before DecryptAndDecodeSamples() is called. - // - // Returns kSuccess if the |audio_decoder_config| is supported and the CDM - // audio decoder is successfully initialized. - // Returns kSessionError if |audio_decoder_config| is not supported. The CDM - // may still be able to do Decrypt(). - // Returns kDeferredInitialization if the CDM is not ready to initialize the - // decoder at this time. Must call Host::OnDeferredInitializationDone() once - // initialization is complete. - virtual Status InitializeAudioDecoder( - const AudioDecoderConfig& audio_decoder_config) = 0; - - // Initializes the CDM video decoder with |video_decoder_config|. This - // function must be called before DecryptAndDecodeFrame() is called. - // - // Returns kSuccess if the |video_decoder_config| is supported and the CDM - // video decoder is successfully initialized. - // Returns kSessionError if |video_decoder_config| is not supported. The CDM - // may still be able to do Decrypt(). - // Returns kDeferredInitialization if the CDM is not ready to initialize the - // decoder at this time. Must call Host::OnDeferredInitializationDone() once - // initialization is complete. - virtual Status InitializeVideoDecoder( - const VideoDecoderConfig& video_decoder_config) = 0; - - // De-initializes the CDM decoder and sets it to an uninitialized state. The - // caller can initialize the decoder again after this call to re-initialize - // it. This can be used to reconfigure the decoder if the configuration - // changes. - virtual void DeinitializeDecoder(StreamType decoder_type) = 0; - - // Resets the CDM decoder to an initialized clean state. All internal buffers - // MUST be flushed. - virtual void ResetDecoder(StreamType decoder_type) = 0; - - // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into a - // |video_frame|. Upon end-of-stream, the caller should call this function - // repeatedly with empty |encrypted_buffer| (|data| == NULL) until only empty - // |video_frame| (|format| == kEmptyVideoFrame) is produced. - // - // Returns kSuccess if decryption and decoding both succeeded, in which case - // the callee will have filled the |video_frame| and passed the ownership of - // |frame_buffer| in |video_frame| to the caller. - // Returns kNoKey if the CDM did not have the necessary decryption key - // to decrypt. - // Returns kNeedMoreData if more data was needed by the decoder to generate - // a decoded frame (e.g. during initialization and end-of-stream). - // Returns kDecryptError if any decryption error happened. - // Returns kDecodeError if any decoding error happened. - // If the return value is not kSuccess, |video_frame| should be ignored by - // the caller. - virtual Status DecryptAndDecodeFrame(const InputBuffer& encrypted_buffer, - VideoFrame* video_frame) = 0; - - // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into - // |audio_frames|. Upon end-of-stream, the caller should call this function - // repeatedly with empty |encrypted_buffer| (|data| == NULL) until only empty - // |audio_frames| is produced. - // - // Returns kSuccess if decryption and decoding both succeeded, in which case - // the callee will have filled |audio_frames| and passed the ownership of - // |data| in |audio_frames| to the caller. - // Returns kNoKey if the CDM did not have the necessary decryption key - // to decrypt. - // Returns kNeedMoreData if more data was needed by the decoder to generate - // audio samples (e.g. during initialization and end-of-stream). - // Returns kDecryptError if any decryption error happened. - // Returns kDecodeError if any decoding error happened. - // If the return value is not kSuccess, |audio_frames| should be ignored by - // the caller. - virtual Status DecryptAndDecodeSamples(const InputBuffer& encrypted_buffer, - AudioFrames* audio_frames) = 0; - - // Called by the host after a platform challenge was initiated via - // Host::SendPlatformChallenge(). - virtual void OnPlatformChallengeResponse( - const PlatformChallengeResponse& response) = 0; - - // Called by the host after a call to Host::QueryOutputProtectionStatus(). The - // |link_mask| is a bit mask of OutputLinkTypes and |output_protection_mask| - // is a bit mask of OutputProtectionMethods. If |result| is kQueryFailed, - // then |link_mask| and |output_protection_mask| are undefined and should - // be ignored. - virtual void OnQueryOutputProtectionStatus( - QueryResult result, - uint32_t link_mask, - uint32_t output_protection_mask) = 0; - - // Destroys the object in the same context as it was created. - virtual void Destroy() = 0; - - protected: - ContentDecryptionModule_8() {} - virtual ~ContentDecryptionModule_8() {} -}; - -// ContentDecryptionModule interface that all CDMs need to implement. -// The interface is versioned for backward compatibility. -// Note: ContentDecryptionModule implementations must use the allocator -// provided in CreateCdmInstance() to allocate any Buffer that needs to -// be passed back to the caller. Implementations must call Buffer::Destroy() -// when a Buffer is created that will never be returned to the caller. -class CDM_CLASS_API ContentDecryptionModule_9 { - public: - static const int kVersion = 9; - typedef Host_9 Host; - - // Initializes the CDM instance, providing information about permitted - // functionalities. - // If |allow_distinctive_identifier| is false, messages from the CDM, - // such as message events, must not contain a Distinctive Identifier, - // even in an encrypted form. - // If |allow_persistent_state| is false, the CDM must not attempt to - // persist state. Calls to CreateFileIO() will fail. - virtual void Initialize(bool allow_distinctive_identifier, - bool allow_persistent_state) = 0; - - // Gets the key status if the CDM has a hypothetical key with the |policy|. - // The CDM must respond by calling either Host::OnResolveKeyStatusPromise() - // with the result key status or Host::OnRejectPromise() if an unexpected - // error happened or this method is not supported. - virtual void GetStatusForPolicy(uint32_t promise_id, - const Policy& policy) = 0; - - // SetServerCertificate(), CreateSessionAndGenerateRequest(), LoadSession(), - // UpdateSession(), CloseSession(), and RemoveSession() all accept a - // |promise_id|, which must be passed to the completion Host method - // (e.g. Host::OnResolveNewSessionPromise()). - - // Provides a server certificate to be used to encrypt messages to the - // license server. The CDM must respond by calling either - // Host::OnResolvePromise() or Host::OnRejectPromise(). - virtual void SetServerCertificate(uint32_t promise_id, - const uint8_t* server_certificate_data, - uint32_t server_certificate_data_size) = 0; - - // Creates a session given |session_type|, |init_data_type|, and |init_data|. - // The CDM must respond by calling either Host::OnResolveNewSessionPromise() - // or Host::OnRejectPromise(). - virtual void CreateSessionAndGenerateRequest(uint32_t promise_id, - SessionType session_type, - InitDataType init_data_type, - const uint8_t* init_data, - uint32_t init_data_size) = 0; - - // Loads the session of type |session_type| specified by |session_id|. - // The CDM must respond by calling either Host::OnResolveNewSessionPromise() - // or Host::OnRejectPromise(). If the session is not found, call - // Host::OnResolveNewSessionPromise() with session_id = NULL. - virtual void LoadSession(uint32_t promise_id, - SessionType session_type, - const char* session_id, - uint32_t session_id_size) = 0; - - // Updates the session with |response|. The CDM must respond by calling - // either Host::OnResolvePromise() or Host::OnRejectPromise(). - virtual void UpdateSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size, - const uint8_t* response, - uint32_t response_size) = 0; - - // Requests that the CDM close the session. The CDM must respond by calling - // either Host::OnResolvePromise() or Host::OnRejectPromise() when the request - // has been processed. This may be before the session is closed. Once the - // session is closed, Host::OnSessionClosed() must also be called. - virtual void CloseSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size) = 0; - - // Removes any stored session data associated with this session. Will only be - // called for persistent sessions. The CDM must respond by calling either - // Host::OnResolvePromise() or Host::OnRejectPromise() when the request has - // been processed. - virtual void RemoveSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size) = 0; - - // Performs scheduled operation with |context| when the timer fires. - virtual void TimerExpired(void* context) = 0; - - // Decrypts the |encrypted_buffer|. - // - // Returns kSuccess if decryption succeeded, in which case the callee - // should have filled the |decrypted_buffer| and passed the ownership of - // |data| in |decrypted_buffer| to the caller. - // Returns kNoKey if the CDM did not have the necessary decryption key - // to decrypt. - // Returns kDecryptError if any other error happened. - // If the return value is not kSuccess, |decrypted_buffer| should be ignored - // by the caller. - virtual Status Decrypt(const InputBuffer& encrypted_buffer, - DecryptedBlock* decrypted_buffer) = 0; - - // Initializes the CDM audio decoder with |audio_decoder_config|. This - // function must be called before DecryptAndDecodeSamples() is called. - // - // Returns kSuccess if the |audio_decoder_config| is supported and the CDM - // audio decoder is successfully initialized. - // Returns kInitializationError if |audio_decoder_config| is not supported. - // The CDM may still be able to do Decrypt(). - // Returns kDeferredInitialization if the CDM is not ready to initialize the - // decoder at this time. Must call Host::OnDeferredInitializationDone() once - // initialization is complete. - virtual Status InitializeAudioDecoder( - const AudioDecoderConfig& audio_decoder_config) = 0; - - // Initializes the CDM video decoder with |video_decoder_config|. This - // function must be called before DecryptAndDecodeFrame() is called. - // - // Returns kSuccess if the |video_decoder_config| is supported and the CDM - // video decoder is successfully initialized. - // Returns kInitializationError if |video_decoder_config| is not supported. - // The CDM may still be able to do Decrypt(). - // Returns kDeferredInitialization if the CDM is not ready to initialize the - // decoder at this time. Must call Host::OnDeferredInitializationDone() once - // initialization is complete. - virtual Status InitializeVideoDecoder( - const VideoDecoderConfig& video_decoder_config) = 0; - - // De-initializes the CDM decoder and sets it to an uninitialized state. The - // caller can initialize the decoder again after this call to re-initialize - // it. This can be used to reconfigure the decoder if the configuration - // changes. - virtual void DeinitializeDecoder(StreamType decoder_type) = 0; - - // Resets the CDM decoder to an initialized clean state. All internal buffers - // MUST be flushed. - virtual void ResetDecoder(StreamType decoder_type) = 0; - - // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into a - // |video_frame|. Upon end-of-stream, the caller should call this function - // repeatedly with empty |encrypted_buffer| (|data| == NULL) until only empty - // |video_frame| (|format| == kEmptyVideoFrame) is produced. - // - // Returns kSuccess if decryption and decoding both succeeded, in which case - // the callee will have filled the |video_frame| and passed the ownership of - // |frame_buffer| in |video_frame| to the caller. - // Returns kNoKey if the CDM did not have the necessary decryption key - // to decrypt. - // Returns kNeedMoreData if more data was needed by the decoder to generate - // a decoded frame (e.g. during initialization and end-of-stream). - // Returns kDecryptError if any decryption error happened. - // Returns kDecodeError if any decoding error happened. - // If the return value is not kSuccess, |video_frame| should be ignored by - // the caller. - virtual Status DecryptAndDecodeFrame(const InputBuffer& encrypted_buffer, - VideoFrame* video_frame) = 0; - - // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into - // |audio_frames|. Upon end-of-stream, the caller should call this function - // repeatedly with empty |encrypted_buffer| (|data| == NULL) until only empty - // |audio_frames| is produced. - // - // Returns kSuccess if decryption and decoding both succeeded, in which case - // the callee will have filled |audio_frames| and passed the ownership of - // |data| in |audio_frames| to the caller. - // Returns kNoKey if the CDM did not have the necessary decryption key - // to decrypt. - // Returns kNeedMoreData if more data was needed by the decoder to generate - // audio samples (e.g. during initialization and end-of-stream). - // Returns kDecryptError if any decryption error happened. - // Returns kDecodeError if any decoding error happened. - // If the return value is not kSuccess, |audio_frames| should be ignored by - // the caller. - virtual Status DecryptAndDecodeSamples(const InputBuffer& encrypted_buffer, - AudioFrames* audio_frames) = 0; - - // Called by the host after a platform challenge was initiated via - // Host::SendPlatformChallenge(). - virtual void OnPlatformChallengeResponse( - const PlatformChallengeResponse& response) = 0; - - // Called by the host after a call to Host::QueryOutputProtectionStatus(). The - // |link_mask| is a bit mask of OutputLinkTypes and |output_protection_mask| - // is a bit mask of OutputProtectionMethods. If |result| is kQueryFailed, - // then |link_mask| and |output_protection_mask| are undefined and should - // be ignored. - virtual void OnQueryOutputProtectionStatus( - QueryResult result, - uint32_t link_mask, - uint32_t output_protection_mask) = 0; - - // Called by the host after a call to Host::RequestStorageId(). If the - // version of the storage ID requested is available, |storage_id| and - // |storage_id_size| are set appropriately. |version| will be the same as - // what was requested, unless 0 (latest) was requested, in which case - // |version| will be the actual version number for the |storage_id| returned. - // If the requested version is not available, null/zero will be provided as - // |storage_id| and |storage_id_size|, respectively, and |version| should be - // ignored. - virtual void OnStorageId(uint32_t version, - const uint8_t* storage_id, - uint32_t storage_id_size) = 0; - - // Destroys the object in the same context as it was created. - virtual void Destroy() = 0; - - protected: - ContentDecryptionModule_9() {} - virtual ~ContentDecryptionModule_9() {} -}; - -typedef ContentDecryptionModule_9 ContentDecryptionModule; - -// Represents a buffer created by Allocator implementations. -class CDM_CLASS_API Buffer { - public: - // Destroys the buffer in the same context as it was created. - virtual void Destroy() = 0; - - virtual uint32_t Capacity() const = 0; - virtual uint8_t* Data() = 0; - virtual void SetSize(uint32_t size) = 0; - virtual uint32_t Size() const = 0; - - protected: - Buffer() {} - virtual ~Buffer() {} - - private: - Buffer(const Buffer&); - void operator=(const Buffer&); -}; - -class CDM_CLASS_API Host_8 { - public: - static const int kVersion = 8; - - // Returns a Buffer* containing non-zero members upon success, or NULL on - // failure. The caller owns the Buffer* after this call. The buffer is not - // guaranteed to be zero initialized. The capacity of the allocated Buffer - // is guaranteed to be not less than |capacity|. - virtual Buffer* Allocate(uint32_t capacity) = 0; - - // Requests the host to call ContentDecryptionModule::TimerFired() |delay_ms| - // from now with |context|. - virtual void SetTimer(int64_t delay_ms, void* context) = 0; - - // Returns the current wall time. - virtual Time GetCurrentWallTime() = 0; - - // Called by the CDM when a session is created or loaded and the value for the - // MediaKeySession's sessionId attribute is available (|session_id|). - // This must be called before OnSessionMessage() or - // OnSessionKeysChange() is called for the same session. |session_id_size| - // should not include null termination. - // When called in response to LoadSession(), the |session_id| must be the - // same as the |session_id| passed in LoadSession(), or NULL if the - // session could not be loaded. - virtual void OnResolveNewSessionPromise(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size) = 0; - - // Called by the CDM when a session is updated or released. - virtual void OnResolvePromise(uint32_t promise_id) = 0; - - // Called by the CDM when an error occurs as a result of one of the - // ContentDecryptionModule calls that accept a |promise_id|. - // |error| must be specified, |error_message| and |system_code| - // are optional. |error_message_size| should not include null termination. - virtual void OnRejectPromise(uint32_t promise_id, - Error error, - uint32_t system_code, - const char* error_message, - uint32_t error_message_size) = 0; - - // Called by the CDM when it has a message for session |session_id|. - // Size parameters should not include null termination. - // |legacy_destination_url| is only for supporting the prefixed EME API and - // is ignored by unprefixed EME. It should only be non-null if |message_type| - // is kLicenseRenewal. - virtual void OnSessionMessage(const char* session_id, - uint32_t session_id_size, - MessageType message_type, - const char* message, - uint32_t message_size, - const char* legacy_destination_url, - uint32_t legacy_destination_url_length) = 0; - - // Called by the CDM when there has been a change in keys or their status for - // session |session_id|. |has_additional_usable_key| should be set if a - // key is newly usable (e.g. new key available, previously expired key has - // been renewed, etc.) and the browser should attempt to resume playback. - // |key_ids| is the list of key ids for this session along with their - // current status. |key_ids_count| is the number of entries in |key_ids|. - // Size parameter for |session_id| should not include null termination. - virtual void OnSessionKeysChange(const char* session_id, - uint32_t session_id_size, - bool has_additional_usable_key, - const KeyInformation* keys_info, - uint32_t keys_info_count) = 0; - - // Called by the CDM when there has been a change in the expiration time for - // session |session_id|. This can happen as the result of an Update() call - // or some other event. If this happens as a result of a call to Update(), - // it must be called before resolving the Update() promise. |new_expiry_time| - // represents the time after which the key(s) in the session will no longer - // be usable for decryption. It can be 0 if no such time exists or if the - // license explicitly never expires. Size parameter should not include null - // termination. - virtual void OnExpirationChange(const char* session_id, - uint32_t session_id_size, - Time new_expiry_time) = 0; - - // Called by the CDM when session |session_id| is closed. Size - // parameter should not include null termination. - virtual void OnSessionClosed(const char* session_id, - uint32_t session_id_size) = 0; - - // Called by the CDM when an error occurs in session |session_id| - // unrelated to one of the ContentDecryptionModule calls that accept a - // |promise_id|. |error| must be specified, |error_message| and - // |system_code| are optional. Length parameters should not include null - // termination. - // Note: - // - This method is only for supporting prefixed EME API. - // - This method will be ignored by unprefixed EME. All errors reported - // in this method should probably also be reported by one of other methods. - virtual void OnLegacySessionError( - const char* session_id, uint32_t session_id_length, - Error error, - uint32_t system_code, - const char* error_message, uint32_t error_message_length) = 0; - - // The following are optional methods that may not be implemented on all - // platforms. - - // Sends a platform challenge for the given |service_id|. |challenge| is at - // most 256 bits of data to be signed. Once the challenge has been completed, - // the host will call ContentDecryptionModule::OnPlatformChallengeResponse() - // with the signed challenge response and platform certificate. Size - // parameters should not include null termination. - virtual void SendPlatformChallenge(const char* service_id, - uint32_t service_id_size, - const char* challenge, - uint32_t challenge_size) = 0; - - // Attempts to enable output protection (e.g. HDCP) on the display link. The - // |desired_protection_mask| is a bit mask of OutputProtectionMethods. No - // status callback is issued, the CDM must call QueryOutputProtectionStatus() - // periodically to ensure the desired protections are applied. - virtual void EnableOutputProtection(uint32_t desired_protection_mask) = 0; - - // Requests the current output protection status. Once the host has the status - // it will call ContentDecryptionModule::OnQueryOutputProtectionStatus(). - virtual void QueryOutputProtectionStatus() = 0; - - // Must be called by the CDM if it returned kDeferredInitialization during - // InitializeAudioDecoder() or InitializeVideoDecoder(). - virtual void OnDeferredInitializationDone(StreamType stream_type, - Status decoder_status) = 0; - - // Creates a FileIO object from the host to do file IO operation. Returns NULL - // if a FileIO object cannot be obtained. Once a valid FileIO object is - // returned, |client| must be valid until FileIO::Close() is called. The - // CDM can call this method multiple times to operate on different files. - virtual FileIO* CreateFileIO(FileIOClient* client) = 0; - - protected: - Host_8() {} - virtual ~Host_8() {} -}; - -class CDM_CLASS_API Host_9 { - public: - static const int kVersion = 9; - - // Returns a Buffer* containing non-zero members upon success, or NULL on - // failure. The caller owns the Buffer* after this call. The buffer is not - // guaranteed to be zero initialized. The capacity of the allocated Buffer - // is guaranteed to be not less than |capacity|. - virtual Buffer* Allocate(uint32_t capacity) = 0; - - // Requests the host to call ContentDecryptionModule::TimerFired() |delay_ms| - // from now with |context|. - virtual void SetTimer(int64_t delay_ms, void* context) = 0; - - // Returns the current wall time. - virtual Time GetCurrentWallTime() = 0; - - // Called by the CDM when a key status is available in response to - // GetStatusForPolicy(). - virtual void OnResolveKeyStatusPromise(uint32_t promise_id, - KeyStatus key_status) = 0; - - // Called by the CDM when a session is created or loaded and the value for the - // MediaKeySession's sessionId attribute is available (|session_id|). - // This must be called before OnSessionMessage() or - // OnSessionKeysChange() is called for the same session. |session_id_size| - // should not include null termination. - // When called in response to LoadSession(), the |session_id| must be the - // same as the |session_id| passed in LoadSession(), or NULL if the - // session could not be loaded. - virtual void OnResolveNewSessionPromise(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size) = 0; - - // Called by the CDM when a session is updated or released. - virtual void OnResolvePromise(uint32_t promise_id) = 0; - - // Called by the CDM when an error occurs as a result of one of the - // ContentDecryptionModule calls that accept a |promise_id|. - // |exception| must be specified. |error_message| and |system_code| - // are optional. |error_message_size| should not include null termination. - virtual void OnRejectPromise(uint32_t promise_id, - Exception exception, - uint32_t system_code, - const char* error_message, - uint32_t error_message_size) = 0; - - // Called by the CDM when it has a message for session |session_id|. - // Size parameters should not include null termination. - virtual void OnSessionMessage(const char* session_id, - uint32_t session_id_size, - MessageType message_type, - const char* message, - uint32_t message_size) = 0; - - // Called by the CDM when there has been a change in keys or their status for - // session |session_id|. |has_additional_usable_key| should be set if a - // key is newly usable (e.g. new key available, previously expired key has - // been renewed, etc.) and the browser should attempt to resume playback. - // |key_ids| is the list of key ids for this session along with their - // current status. |key_ids_count| is the number of entries in |key_ids|. - // Size parameter for |session_id| should not include null termination. - virtual void OnSessionKeysChange(const char* session_id, - uint32_t session_id_size, - bool has_additional_usable_key, - const KeyInformation* keys_info, - uint32_t keys_info_count) = 0; - - // Called by the CDM when there has been a change in the expiration time for - // session |session_id|. This can happen as the result of an Update() call - // or some other event. If this happens as a result of a call to Update(), - // it must be called before resolving the Update() promise. |new_expiry_time| - // represents the time after which the key(s) in the session will no longer - // be usable for decryption. It can be 0 if no such time exists or if the - // license explicitly never expires. Size parameter should not include null - // termination. - virtual void OnExpirationChange(const char* session_id, - uint32_t session_id_size, - Time new_expiry_time) = 0; - - // Called by the CDM when session |session_id| is closed. Size - // parameter should not include null termination. - virtual void OnSessionClosed(const char* session_id, - uint32_t session_id_size) = 0; - - // The following are optional methods that may not be implemented on all - // platforms. - - // Sends a platform challenge for the given |service_id|. |challenge| is at - // most 256 bits of data to be signed. Once the challenge has been completed, - // the host will call ContentDecryptionModule::OnPlatformChallengeResponse() - // with the signed challenge response and platform certificate. Size - // parameters should not include null termination. - virtual void SendPlatformChallenge(const char* service_id, - uint32_t service_id_size, - const char* challenge, - uint32_t challenge_size) = 0; - - // Attempts to enable output protection (e.g. HDCP) on the display link. The - // |desired_protection_mask| is a bit mask of OutputProtectionMethods. No - // status callback is issued, the CDM must call QueryOutputProtectionStatus() - // periodically to ensure the desired protections are applied. - virtual void EnableOutputProtection(uint32_t desired_protection_mask) = 0; - - // Requests the current output protection status. Once the host has the status - // it will call ContentDecryptionModule::OnQueryOutputProtectionStatus(). - virtual void QueryOutputProtectionStatus() = 0; - - // Must be called by the CDM if it returned kDeferredInitialization during - // InitializeAudioDecoder() or InitializeVideoDecoder(). - virtual void OnDeferredInitializationDone(StreamType stream_type, - Status decoder_status) = 0; - - // Creates a FileIO object from the host to do file IO operation. Returns NULL - // if a FileIO object cannot be obtained. Once a valid FileIO object is - // returned, |client| must be valid until FileIO::Close() is called. The - // CDM can call this method multiple times to operate on different files. - virtual FileIO* CreateFileIO(FileIOClient* client) = 0; - - // Requests a specific version of the storage ID. A storage ID is a stable, - // device specific ID used by the CDM to securely store persistent data. The - // ID will be returned by the host via ContentDecryptionModule::OnStorageId(). - // If |version| is 0, the latest version will be returned. All |version|s - // that are greater than or equal to 0x80000000 are reserved for the CDM and - // should not be supported or returned by the host. The CDM must not expose - // the ID outside the client device, even in encrypted form. - virtual void RequestStorageId(uint32_t version) = 0; - - protected: - Host_9() {} - virtual ~Host_9() {} -}; - -// Represents a decrypted block that has not been decoded. -class CDM_CLASS_API DecryptedBlock { - public: - virtual void SetDecryptedBuffer(Buffer* buffer) = 0; - virtual Buffer* DecryptedBuffer() = 0; - - // TODO(tomfinegan): Figure out if timestamp is really needed. If it is not, - // we can just pass Buffer pointers around. - virtual void SetTimestamp(int64_t timestamp) = 0; - virtual int64_t Timestamp() const = 0; - - protected: - DecryptedBlock() {} - virtual ~DecryptedBlock() {} -}; - -class CDM_CLASS_API VideoFrame { - public: - enum VideoPlane { - kYPlane = 0, - kUPlane = 1, - kVPlane = 2, - kMaxPlanes = 3, - }; - - virtual void SetFormat(VideoFormat format) = 0; - virtual VideoFormat Format() const = 0; - - virtual void SetSize(cdm::Size size) = 0; - virtual cdm::Size Size() const = 0; - - virtual void SetFrameBuffer(Buffer* frame_buffer) = 0; - virtual Buffer* FrameBuffer() = 0; - - virtual void SetPlaneOffset(VideoPlane plane, uint32_t offset) = 0; - virtual uint32_t PlaneOffset(VideoPlane plane) = 0; - - virtual void SetStride(VideoPlane plane, uint32_t stride) = 0; - virtual uint32_t Stride(VideoPlane plane) = 0; - - virtual void SetTimestamp(int64_t timestamp) = 0; - virtual int64_t Timestamp() const = 0; - - protected: - VideoFrame() {} - virtual ~VideoFrame() {} -}; - -// Represents decrypted and decoded audio frames. AudioFrames can contain -// multiple audio output buffers, which are serialized into this format: -// -// |<------------------- serialized audio buffer ------------------->| -// | int64_t timestamp | int64_t length | length bytes of audio data | -// -// For example, with three audio output buffers, the AudioFrames will look -// like this: -// -// |<----------------- AudioFrames ------------------>| -// | audio buffer 0 | audio buffer 1 | audio buffer 2 | -class CDM_CLASS_API AudioFrames { - public: - virtual void SetFrameBuffer(Buffer* buffer) = 0; - virtual Buffer* FrameBuffer() = 0; - - // The CDM must call this method, providing a valid format, when providing - // frame buffers. Planar data should be stored end to end; e.g., - // |ch1 sample1||ch1 sample2|....|ch1 sample_last||ch2 sample1|... - virtual void SetFormat(AudioFormat format) = 0; - virtual AudioFormat Format() const = 0; - - protected: - AudioFrames() {} - virtual ~AudioFrames() {} -}; - -} // namespace cdm - -#endif // CDM_CONTENT_DECRYPTION_MODULE_H_ diff --git a/dom/media/gmp/widevine-adapter/content_decryption_module_export.h b/dom/media/gmp/widevine-adapter/content_decryption_module_export.h deleted file mode 100644 index 51d485892b..0000000000 --- a/dom/media/gmp/widevine-adapter/content_decryption_module_export.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CDM_CONTENT_DECRYPTION_MODULE_EXPORT_H_ -#define CDM_CONTENT_DECRYPTION_MODULE_EXPORT_H_ - -// Define CDM_API so that functionality implemented by the CDM module -// can be exported to consumers. -#if defined(_WIN32) - -#if defined(CDM_IMPLEMENTATION) -#define CDM_API __declspec(dllexport) -#else -#define CDM_API __declspec(dllimport) -#endif // defined(CDM_IMPLEMENTATION) - -#else // defined(_WIN32) -#define CDM_API __attribute__((visibility("default"))) -#endif // defined(_WIN32) - -#endif // CDM_CONTENT_DECRYPTION_MODULE_EXPORT_H_ diff --git a/dom/media/gmp/widevine-adapter/content_decryption_module_ext.h b/dom/media/gmp/widevine-adapter/content_decryption_module_ext.h deleted file mode 100644 index 5df8344e60..0000000000 --- a/dom/media/gmp/widevine-adapter/content_decryption_module_ext.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CDM_CONTENT_DECRYPTION_MODULE_EXT_H_ -#define CDM_CONTENT_DECRYPTION_MODULE_EXT_H_ - -#if defined(_WIN32) -#include <windows.h> -#endif - -#include "content_decryption_module_export.h" - -#if defined(_MSC_VER) -typedef unsigned int uint32_t; -#else -#include <stdint.h> -#endif - -namespace cdm { - -#if defined(_WIN32) -typedef wchar_t FilePathCharType; -typedef HANDLE PlatformFile; -const PlatformFile kInvalidPlatformFile = INVALID_HANDLE_VALUE; -#else -typedef char FilePathCharType; -typedef int PlatformFile; -const PlatformFile kInvalidPlatformFile = -1; -#endif // defined(_WIN32) - -struct HostFile { - HostFile(const FilePathCharType* file_path, - PlatformFile file, - PlatformFile sig_file) - : file_path(file_path), file(file), sig_file(sig_file) {} - - // File that is part of the host of the CDM. - const FilePathCharType* file_path = nullptr; - PlatformFile file = kInvalidPlatformFile; - - // Signature file for |file|. - PlatformFile sig_file = kInvalidPlatformFile; -}; - -} // namespace cdm - -extern "C" { - -// Functions in this file are dynamically retrieved by their versioned function -// names. Increment the version number for any backward incompatible API -// changes. - -// Verifies CDM host. All files in |host_files| are opened in read-only mode. -// -// Returns false and closes all files if there is an immediate failure. -// Otherwise returns true as soon as possible and processes the files -// asynchronously. All files MUST be closed by the CDM after this one-time -// processing is finished. -CDM_API bool VerifyCdmHost_0(const cdm::HostFile* host_files, - uint32_t num_files); -} - -#endif // CDM_CONTENT_DECRYPTION_MODULE_EXT_H_ diff --git a/dom/media/gmp/widevine-adapter/moz.build b/dom/media/gmp/widevine-adapter/moz.build deleted file mode 100644 index 4a3a079cec..0000000000 --- a/dom/media/gmp/widevine-adapter/moz.build +++ /dev/null @@ -1,24 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# 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/. - -SOURCES += [ - 'WidevineAdapter.cpp', - 'WidevineDecryptor.cpp', - 'WidevineFileIO.cpp', - 'WidevineUtils.cpp', - 'WidevineVideoDecoder.cpp', - 'WidevineVideoFrame.cpp', -] - -FINAL_LIBRARY = 'xul' - -LOCAL_INCLUDES += [ - '/dom/media/gmp', -] - -if CONFIG['CLANG_CXX']: - CXXFLAGS += ['-Wno-error=shadow'] - -include('/ipc/chromium/chromium-config.mozbuild') diff --git a/dom/media/gtest/MockMediaDecoderOwner.h b/dom/media/gtest/MockMediaDecoderOwner.h index 1009ca30a1..64d7290187 100644 --- a/dom/media/gtest/MockMediaDecoderOwner.h +++ b/dom/media/gtest/MockMediaDecoderOwner.h @@ -34,10 +34,6 @@ public: void DownloadProgressed() override {} void UpdateReadyState() override {} void FirstFrameLoaded() override {} -#ifdef MOZ_EME - void DispatchEncrypted(const nsTArray<uint8_t>& aInitData, - const nsAString& aInitDataType) override {} -#endif bool IsActive() const override { return true; } bool IsHidden() const override { return false; } void DownloadSuspended() override {} diff --git a/dom/media/mediasource/TrackBuffersManager.cpp b/dom/media/mediasource/TrackBuffersManager.cpp index 022bb5bd10..907ee40e8f 100644 --- a/dom/media/mediasource/TrackBuffersManager.cpp +++ b/dom/media/mediasource/TrackBuffersManager.cpp @@ -58,34 +58,6 @@ AppendStateToStr(SourceBufferAttributes::AppendState aState) static Atomic<uint32_t> sStreamSourceID(0u); -#ifdef MOZ_EME -class DispatchKeyNeededEvent : public Runnable { -public: - DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder, - nsTArray<uint8_t>& aInitData, - const nsString& aInitDataType) - : mDecoder(aDecoder) - , mInitData(aInitData) - , mInitDataType(aInitDataType) - { - } - NS_IMETHOD Run() override { - // 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: - RefPtr<AbstractMediaDecoder> mDecoder; - nsTArray<uint8_t> mInitData; - nsString mInitDataType; -}; -#endif // MOZ_EME - TrackBuffersManager::TrackBuffersManager(MediaSourceDecoder* aParentDecoder, const nsACString& aType) : mInputBuffer(new MediaByteBuffer) @@ -1101,14 +1073,6 @@ TrackBuffersManager::OnDemuxerInitDone(nsresult) UniquePtr<EncryptionInfo> crypto = mInputDemuxer->GetCrypto(); if (crypto && crypto->IsEncrypted()) { -#ifdef MOZ_EME - // Try and dispatch 'encrypted'. Won't go if ready state still HAVE_NOTHING. - for (uint32_t i = 0; i < crypto->mInitDatas.Length(); i++) { - NS_DispatchToMainThread( - new DispatchKeyNeededEvent(mParentDecoder, crypto->mInitDatas[i].mInitData, - crypto->mInitDatas[i].mType)); - } -#endif info.mCrypto = *crypto; // We clear our crypto init data array, so the MediaFormatReader will // not emit an encrypted event for the same init data again. diff --git a/dom/media/moz.build b/dom/media/moz.build index ef018d4a75..ca3cdac1ca 100644 --- a/dom/media/moz.build +++ b/dom/media/moz.build @@ -44,9 +44,6 @@ if CONFIG['MOZ_FMP4']: if CONFIG['MOZ_WEBRTC']: DIRS += ['bridge'] -if CONFIG['MOZ_EME']: - DIRS += ['eme'] - if CONFIG['MOZ_GMP']: DIRS += [ 'gmp', diff --git a/dom/media/platforms/PDMFactory.cpp b/dom/media/platforms/PDMFactory.cpp index 029b88cecb..02cbd3d92b 100644 --- a/dom/media/platforms/PDMFactory.cpp +++ b/dom/media/platforms/PDMFactory.cpp @@ -35,11 +35,6 @@ #include "AgnosticDecoderModule.h" -#ifdef MOZ_EME -#include "mozilla/CDMProxy.h" -#include "EMEDecoderModule.h" -#endif - #include "DecoderDoctorDiagnostics.h" #include "MP4Decoder.h" @@ -206,11 +201,6 @@ PDMFactory::CreateDecoder(const CreateDecoderParams& aParams) } const TrackInfo& config = aParams.mConfig; - bool isEncrypted = mEMEPDM && config.mCrypto.mValid; - - if (isEncrypted) { - return CreateDecoderWithPDM(mEMEPDM, aParams); - } DecoderDoctorDiagnostics* diagnostics = aParams.mDiagnostics; if (diagnostics) { @@ -334,9 +324,6 @@ bool PDMFactory::Supports(const TrackInfo& aTrackInfo, DecoderDoctorDiagnostics* aDiagnostics) const { - if (mEMEPDM) { - return mEMEPDM->Supports(aTrackInfo, aDiagnostics); - } RefPtr<PlatformDecoderModule> current = GetDecoder(aTrackInfo, aDiagnostics); return !!current; } @@ -444,13 +431,4 @@ PDMFactory::GetDecoder(const TrackInfo& aTrackInfo, return pdm.forget(); } -#ifdef MOZ_EME -void -PDMFactory::SetCDMProxy(CDMProxy* aProxy) -{ - RefPtr<PDMFactory> m = new PDMFactory(); - mEMEPDM = new EMEDecoderModule(aProxy, m); -} -#endif - } // namespace mozilla diff --git a/dom/media/platforms/PDMFactory.h b/dom/media/platforms/PDMFactory.h index 186c05ca4e..313633ab57 100644 --- a/dom/media/platforms/PDMFactory.h +++ b/dom/media/platforms/PDMFactory.h @@ -10,10 +10,6 @@ #include "mozilla/Function.h" #include "mozilla/StaticMutex.h" -#ifdef MOZ_EME -class CDMProxy; -#endif - namespace mozilla { class DecoderDoctorDiagnostics; @@ -39,15 +35,6 @@ public: bool Supports(const TrackInfo& aTrackInfo, DecoderDoctorDiagnostics* aDiagnostics) const; -#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. - void SetCDMProxy(CDMProxy* aProxy); -#endif - static const int kYUV400 = 0; static const int kYUV420 = 1; static const int kYUV422 = 2; @@ -69,7 +56,6 @@ private: const CreateDecoderParams& aParams); nsTArray<RefPtr<PlatformDecoderModule>> mCurrentPDMs; - RefPtr<PlatformDecoderModule> mEMEPDM; RefPtr<PlatformDecoderModule> mBlankPDM; bool mWMFFailedToLoad = false; diff --git a/dom/media/platforms/PlatformDecoderModule.h b/dom/media/platforms/PlatformDecoderModule.h index f2abe4b7f7..63b4e00d5c 100644 --- a/dom/media/platforms/PlatformDecoderModule.h +++ b/dom/media/platforms/PlatformDecoderModule.h @@ -39,9 +39,6 @@ class RemoteDecoderModule; class MediaDataDecoder; class MediaDataDecoderCallback; class TaskQueue; -#ifdef MOZ_EME -class CDMProxy; -#endif static LazyLogModule sPDMLog("PlatformDecoderModule"); diff --git a/dom/media/platforms/agnostic/eme/EMEAudioDecoder.cpp b/dom/media/platforms/agnostic/eme/EMEAudioDecoder.cpp deleted file mode 100644 index fd0449d66f..0000000000 --- a/dom/media/platforms/agnostic/eme/EMEAudioDecoder.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#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); -} - -EMEAudioDecoder::EMEAudioDecoder(CDMProxy* aProxy, - const GMPAudioDecoderParams& aParams) - : GMPAudioDecoder(GMPAudioDecoderParams(aParams).WithAdapter( - new EMEAudioCallbackAdapter(aParams.mCallback))) - , mProxy(aProxy) -{} - -void -EMEAudioDecoder::InitTags(nsTArray<nsCString>& aTags) -{ - aTags.AppendElement(NS_LITERAL_CSTRING("aac")); - aTags.AppendElement(NS_ConvertUTF16toUTF8(mProxy->KeySystem())); -} - -nsCString -EMEAudioDecoder::GetNodeId() -{ - return mProxy->GetNodeId(); -} - -} // namespace mozilla diff --git a/dom/media/platforms/agnostic/eme/EMEAudioDecoder.h b/dom/media/platforms/agnostic/eme/EMEAudioDecoder.h deleted file mode 100644 index fd41125d87..0000000000 --- a/dom/media/platforms/agnostic/eme/EMEAudioDecoder.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#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) - {} - - void Error(GMPErr aErr) override; -}; - -class EMEAudioDecoder : public GMPAudioDecoder { -public: - EMEAudioDecoder(CDMProxy* aProxy, const GMPAudioDecoderParams& aParams); - -private: - void InitTags(nsTArray<nsCString>& aTags) override; - nsCString GetNodeId() override; - - RefPtr<CDMProxy> mProxy; -}; - -} // namespace mozilla - -#endif diff --git a/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp b/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp deleted file mode 100644 index a293824608..0000000000 --- a/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp +++ /dev/null @@ -1,306 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#include "EMEDecoderModule.h" -#include "EMEAudioDecoder.h" -#include "EMEVideoDecoder.h" -#include "MediaDataDecoderProxy.h" -#include "mozIGeckoMediaPluginService.h" -#include "mozilla/CDMProxy.h" -#include "mozilla/Unused.h" -#include "nsAutoPtr.h" -#include "nsServiceManagerUtils.h" -#include "MediaInfo.h" -#include "nsClassHashtable.h" -#include "GMPDecoderModule.h" -#include "MP4Decoder.h" - -namespace mozilla { - -typedef MozPromiseRequestHolder<CDMProxy::DecryptPromise> DecryptPromiseRequestHolder; - -class EMEDecryptor : public MediaDataDecoder { - -public: - - EMEDecryptor(MediaDataDecoder* aDecoder, - MediaDataDecoderCallback* aCallback, - CDMProxy* aProxy, - TaskQueue* aDecodeTaskQueue) - : mDecoder(aDecoder) - , mCallback(aCallback) - , mTaskQueue(aDecodeTaskQueue) - , mProxy(aProxy) - , mSamplesWaitingForKey(new SamplesWaitingForKey(this, this->mCallback, - mTaskQueue, mProxy)) - , mIsShutdown(false) - { - } - - RefPtr<InitPromise> Init() override { - MOZ_ASSERT(!mIsShutdown); - return mDecoder->Init(); - } - - void Input(MediaRawData* aSample) override { - MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); - if (mIsShutdown) { - NS_WARNING("EME encrypted sample arrived after shutdown"); - return; - } - if (mSamplesWaitingForKey->WaitIfKeyNotUsable(aSample)) { - return; - } - - nsAutoPtr<MediaRawDataWriter> writer(aSample->CreateWriter()); - mProxy->GetSessionIdsForKeyId(aSample->mCrypto.mKeyId, - writer->mCrypto.mSessionIds); - - mDecrypts.Put(aSample, new DecryptPromiseRequestHolder()); - mDecrypts.Get(aSample)->Begin(mProxy->Decrypt(aSample)->Then( - mTaskQueue, __func__, this, - &EMEDecryptor::Decrypted, - &EMEDecryptor::Decrypted)); - return; - } - - void Decrypted(const DecryptResult& aDecrypted) { - MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); - MOZ_ASSERT(aDecrypted.mSample); - - nsAutoPtr<DecryptPromiseRequestHolder> holder; - mDecrypts.RemoveAndForget(aDecrypted.mSample, holder); - if (holder) { - holder->Complete(); - } else { - // Decryption is not in the list of decrypt operations waiting - // for a result. It must have been flushed or drained. Ignore result. - return; - } - - if (mIsShutdown) { - NS_WARNING("EME decrypted sample arrived after shutdown"); - return; - } - - if (aDecrypted.mStatus == NoKeyErr) { - // Key became unusable after we sent the sample to CDM to decrypt. - // Call Input() again, so that the sample is enqueued for decryption - // if the key becomes usable again. - Input(aDecrypted.mSample); - } else if (aDecrypted.mStatus != Ok) { - if (mCallback) { - mCallback->Error(MediaResult( - NS_ERROR_DOM_MEDIA_FATAL_ERR, - RESULT_DETAIL("decrypted.mStatus=%u", uint32_t(aDecrypted.mStatus)))); - } - } else { - MOZ_ASSERT(!mIsShutdown); - // The Adobe GMP AAC decoder gets confused if we pass it non-encrypted - // samples with valid crypto data. So clear the crypto data, since the - // sample should be decrypted now anyway. If we don't do this and we're - // using the Adobe GMP for unencrypted decoding of data that is decrypted - // by gmp-clearkey, decoding will fail. - UniquePtr<MediaRawDataWriter> writer(aDecrypted.mSample->CreateWriter()); - writer->mCrypto = CryptoSample(); - mDecoder->Input(aDecrypted.mSample); - } - } - - void Flush() override { - MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); - MOZ_ASSERT(!mIsShutdown); - for (auto iter = mDecrypts.Iter(); !iter.Done(); iter.Next()) { - nsAutoPtr<DecryptPromiseRequestHolder>& holder = iter.Data(); - holder->DisconnectIfExists(); - iter.Remove(); - } - mDecoder->Flush(); - mSamplesWaitingForKey->Flush(); - } - - void Drain() override { - MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); - MOZ_ASSERT(!mIsShutdown); - for (auto iter = mDecrypts.Iter(); !iter.Done(); iter.Next()) { - nsAutoPtr<DecryptPromiseRequestHolder>& holder = iter.Data(); - holder->DisconnectIfExists(); - iter.Remove(); - } - mDecoder->Drain(); - } - - void Shutdown() override { - MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); - MOZ_ASSERT(!mIsShutdown); - mIsShutdown = true; - mDecoder->Shutdown(); - mSamplesWaitingForKey->BreakCycles(); - mSamplesWaitingForKey = nullptr; - mDecoder = nullptr; - mProxy = nullptr; - mCallback = nullptr; - } - - const char* GetDescriptionName() const override { - return mDecoder->GetDescriptionName(); - } - -private: - - RefPtr<MediaDataDecoder> mDecoder; - MediaDataDecoderCallback* mCallback; - RefPtr<TaskQueue> mTaskQueue; - RefPtr<CDMProxy> mProxy; - nsClassHashtable<nsRefPtrHashKey<MediaRawData>, DecryptPromiseRequestHolder> mDecrypts; - RefPtr<SamplesWaitingForKey> mSamplesWaitingForKey; - bool mIsShutdown; -}; - -class EMEMediaDataDecoderProxy : public MediaDataDecoderProxy { -public: - EMEMediaDataDecoderProxy(already_AddRefed<AbstractThread> aProxyThread, - MediaDataDecoderCallback* aCallback, - CDMProxy* aProxy, - TaskQueue* aTaskQueue) - : MediaDataDecoderProxy(Move(aProxyThread), aCallback) - , mSamplesWaitingForKey(new SamplesWaitingForKey(this, aCallback, - aTaskQueue, aProxy)) - , mProxy(aProxy) - { - } - - void Input(MediaRawData* aSample) override; - void Shutdown() override; - -private: - RefPtr<SamplesWaitingForKey> mSamplesWaitingForKey; - RefPtr<CDMProxy> mProxy; -}; - -void -EMEMediaDataDecoderProxy::Input(MediaRawData* aSample) -{ - if (mSamplesWaitingForKey->WaitIfKeyNotUsable(aSample)) { - return; - } - - nsAutoPtr<MediaRawDataWriter> writer(aSample->CreateWriter()); - mProxy->GetSessionIdsForKeyId(aSample->mCrypto.mKeyId, - writer->mCrypto.mSessionIds); - - MediaDataDecoderProxy::Input(aSample); -} - -void -EMEMediaDataDecoderProxy::Shutdown() -{ - MediaDataDecoderProxy::Shutdown(); - - mSamplesWaitingForKey->BreakCycles(); - mSamplesWaitingForKey = nullptr; - mProxy = nullptr; -} - -EMEDecoderModule::EMEDecoderModule(CDMProxy* aProxy, PDMFactory* aPDM) - : mProxy(aProxy) - , mPDM(aPDM) -{ -} - -EMEDecoderModule::~EMEDecoderModule() -{ -} - -static already_AddRefed<MediaDataDecoderProxy> -CreateDecoderWrapper(MediaDataDecoderCallback* aCallback, CDMProxy* aProxy, TaskQueue* aTaskQueue) -{ - RefPtr<gmp::GeckoMediaPluginService> s(gmp::GeckoMediaPluginService::GetGeckoMediaPluginService()); - if (!s) { - return nullptr; - } - RefPtr<AbstractThread> thread(s->GetAbstractGMPThread()); - if (!thread) { - return nullptr; - } - RefPtr<MediaDataDecoderProxy> decoder( - new EMEMediaDataDecoderProxy(thread.forget(), aCallback, aProxy, aTaskQueue)); - return decoder.forget(); -} - -already_AddRefed<MediaDataDecoder> -EMEDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams) -{ - MOZ_ASSERT(aParams.mConfig.mCrypto.mValid); - - if (SupportsMimeType(aParams.mConfig.mMimeType, nullptr)) { - // GMP decodes. Assume that means it can decrypt too. - RefPtr<MediaDataDecoderProxy> wrapper = - CreateDecoderWrapper(aParams.mCallback, mProxy, aParams.mTaskQueue); - auto params = GMPVideoDecoderParams(aParams).WithCallback(wrapper); - wrapper->SetProxyTarget(new EMEVideoDecoder(mProxy, params)); - return wrapper.forget(); - } - - MOZ_ASSERT(mPDM); - RefPtr<MediaDataDecoder> decoder(mPDM->CreateDecoder(aParams)); - if (!decoder) { - return nullptr; - } - - RefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(decoder, - aParams.mCallback, - mProxy, - AbstractThread::GetCurrent()->AsTaskQueue())); - return emeDecoder.forget(); -} - -already_AddRefed<MediaDataDecoder> -EMEDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams) -{ - MOZ_ASSERT(aParams.mConfig.mCrypto.mValid); - - if (SupportsMimeType(aParams.mConfig.mMimeType, nullptr)) { - // GMP decodes. Assume that means it can decrypt too. - RefPtr<MediaDataDecoderProxy> wrapper = - CreateDecoderWrapper(aParams.mCallback, mProxy, aParams.mTaskQueue); - auto gmpParams = GMPAudioDecoderParams(aParams).WithCallback(wrapper); - wrapper->SetProxyTarget(new EMEAudioDecoder(mProxy, gmpParams)); - return wrapper.forget(); - } - - MOZ_ASSERT(mPDM); - RefPtr<MediaDataDecoder> decoder(mPDM->CreateDecoder(aParams)); - if (!decoder) { - return nullptr; - } - - RefPtr<MediaDataDecoder> emeDecoder(new EMEDecryptor(decoder, - aParams.mCallback, - mProxy, - AbstractThread::GetCurrent()->AsTaskQueue())); - return emeDecoder.forget(); -} - -PlatformDecoderModule::ConversionRequired -EMEDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const -{ - if (aConfig.IsVideo() && MP4Decoder::IsH264(aConfig.mMimeType)) { - return ConversionRequired::kNeedAVCC; - } else { - return ConversionRequired::kNeedNone; - } -} - -bool -EMEDecoderModule::SupportsMimeType(const nsACString& aMimeType, - DecoderDoctorDiagnostics* aDiagnostics) const -{ - Maybe<nsCString> gmp; - gmp.emplace(NS_ConvertUTF16toUTF8(mProxy->KeySystem())); - return GMPDecoderModule::SupportsMimeType(aMimeType, gmp); -} - -} // namespace mozilla diff --git a/dom/media/platforms/agnostic/eme/EMEDecoderModule.h b/dom/media/platforms/agnostic/eme/EMEDecoderModule.h deleted file mode 100644 index 8480e54536..0000000000 --- a/dom/media/platforms/agnostic/eme/EMEDecoderModule.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#if !defined(EMEDecoderModule_h_) -#define EMEDecoderModule_h_ - -#include "PlatformDecoderModule.h" -#include "PDMFactory.h" -#include "gmp-decryption.h" - -namespace mozilla { - -class CDMProxy; - -class EMEDecoderModule : public PlatformDecoderModule { -private: - -public: - EMEDecoderModule(CDMProxy* aProxy, PDMFactory* aPDM); - - virtual ~EMEDecoderModule(); - -protected: - // Decode thread. - already_AddRefed<MediaDataDecoder> - CreateVideoDecoder(const CreateDecoderParams& aParams) override; - - // Decode thread. - already_AddRefed<MediaDataDecoder> - CreateAudioDecoder(const CreateDecoderParams& aParams) override; - - ConversionRequired - DecoderNeedsConversion(const TrackInfo& aConfig) const override; - - bool - SupportsMimeType(const nsACString& aMimeType, - DecoderDoctorDiagnostics* aDiagnostics) const override; - -private: - RefPtr<CDMProxy> mProxy; - // Will be null if CDM has decoding capability. - RefPtr<PDMFactory> mPDM; - // We run the PDM on its own task queue. - RefPtr<TaskQueue> mTaskQueue; -}; - -} // namespace mozilla - -#endif // EMEDecoderModule_h_ diff --git a/dom/media/platforms/agnostic/eme/EMEVideoDecoder.cpp b/dom/media/platforms/agnostic/eme/EMEVideoDecoder.cpp deleted file mode 100644 index d7b4b1c250..0000000000 --- a/dom/media/platforms/agnostic/eme/EMEVideoDecoder.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#include "EMEVideoDecoder.h" -#include "GMPVideoEncodedFrameImpl.h" -#include "mozilla/CDMProxy.h" -#include "MediaData.h" -#include "MP4Decoder.h" -#include "VPXDecoder.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); -} - -EMEVideoDecoder::EMEVideoDecoder(CDMProxy* aProxy, - const GMPVideoDecoderParams& aParams) - : GMPVideoDecoder(GMPVideoDecoderParams(aParams).WithAdapter( - new EMEVideoCallbackAdapter(aParams.mCallback, - VideoInfo(aParams.mConfig.mDisplay), - aParams.mImageContainer))) - , mProxy(aProxy) - , mDecryptorId(aProxy->GetDecryptorId()) -{} - -void -EMEVideoDecoder::InitTags(nsTArray<nsCString>& aTags) -{ - VideoInfo config = GetConfig(); - if (MP4Decoder::IsH264(config.mMimeType)) { - aTags.AppendElement(NS_LITERAL_CSTRING("h264")); - } else if (VPXDecoder::IsVP8(config.mMimeType)) { - aTags.AppendElement(NS_LITERAL_CSTRING("vp8")); - } else if (VPXDecoder::IsVP9(config.mMimeType)) { - aTags.AppendElement(NS_LITERAL_CSTRING("vp9")); - } - aTags.AppendElement(NS_ConvertUTF16toUTF8(mProxy->KeySystem())); -} - -nsCString -EMEVideoDecoder::GetNodeId() -{ - return mProxy->GetNodeId(); -} - -GMPUniquePtr<GMPVideoEncodedFrame> -EMEVideoDecoder::CreateFrame(MediaRawData* aSample) -{ - GMPUniquePtr<GMPVideoEncodedFrame> frame = GMPVideoDecoder::CreateFrame(aSample); - if (frame && aSample->mCrypto.mValid) { - static_cast<gmp::GMPVideoEncodedFrameImpl*>(frame.get())->InitCrypto(aSample->mCrypto); - } - return frame; -} - -} // namespace mozilla diff --git a/dom/media/platforms/agnostic/eme/EMEVideoDecoder.h b/dom/media/platforms/agnostic/eme/EMEVideoDecoder.h deleted file mode 100644 index e3b63b5066..0000000000 --- a/dom/media/platforms/agnostic/eme/EMEVideoDecoder.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#ifndef EMEVideoDecoder_h_ -#define EMEVideoDecoder_h_ - -#include "GMPVideoDecoder.h" -#include "PlatformDecoderModule.h" - -namespace mozilla { - -class CDMProxy; -class TaskQueue; - -class EMEVideoCallbackAdapter : public VideoCallbackAdapter { -public: - EMEVideoCallbackAdapter(MediaDataDecoderCallbackProxy* aCallback, - VideoInfo aVideoInfo, - layers::ImageContainer* aImageContainer) - : VideoCallbackAdapter(aCallback, aVideoInfo, aImageContainer) - {} - - void Error(GMPErr aErr) override; -}; - -class EMEVideoDecoder : public GMPVideoDecoder { -public: - EMEVideoDecoder(CDMProxy* aProxy, const GMPVideoDecoderParams& aParams); - -private: - void InitTags(nsTArray<nsCString>& aTags) override; - nsCString GetNodeId() override; - uint32_t DecryptorId() const override { return mDecryptorId; } - GMPUniquePtr<GMPVideoEncodedFrame> CreateFrame(MediaRawData* aSample) override; - - RefPtr<CDMProxy> mProxy; - uint32_t mDecryptorId; -}; - -} // namespace mozilla - -#endif // EMEVideoDecoder_h_ diff --git a/dom/media/platforms/agnostic/eme/SamplesWaitingForKey.cpp b/dom/media/platforms/agnostic/eme/SamplesWaitingForKey.cpp deleted file mode 100644 index 532fc63c01..0000000000 --- a/dom/media/platforms/agnostic/eme/SamplesWaitingForKey.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#include "SamplesWaitingForKey.h" -#include "mozilla/CDMProxy.h" -#include "mozilla/CDMCaps.h" -#include "MediaData.h" - -namespace mozilla { - -SamplesWaitingForKey::SamplesWaitingForKey(MediaDataDecoder* aDecoder, - MediaDataDecoderCallback* aCallback, - TaskQueue* aTaskQueue, - CDMProxy* aProxy) - : mMutex("SamplesWaitingForKey") - , mDecoder(aDecoder) - , mDecoderCallback(aCallback) - , mTaskQueue(aTaskQueue) - , mProxy(aProxy) -{ -} - -SamplesWaitingForKey::~SamplesWaitingForKey() -{ -} - -bool -SamplesWaitingForKey::WaitIfKeyNotUsable(MediaRawData* aSample) -{ - if (!aSample || !aSample->mCrypto.mValid || !mProxy) { - return false; - } - CDMCaps::AutoLock caps(mProxy->Capabilites()); - const auto& keyid = aSample->mCrypto.mKeyId; - if (!caps.IsKeyUsable(keyid)) { - { - MutexAutoLock lock(mMutex); - mSamples.AppendElement(aSample); - } - mDecoderCallback->WaitingForKey(); - caps.NotifyWhenKeyIdUsable(aSample->mCrypto.mKeyId, 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]->mCrypto.mKeyId) { - RefPtr<nsIRunnable> task; - task = NewRunnableMethod<RefPtr<MediaRawData>>(mDecoder, - &MediaDataDecoder::Input, - RefPtr<MediaRawData>(mSamples[i])); - 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/platforms/agnostic/eme/SamplesWaitingForKey.h b/dom/media/platforms/agnostic/eme/SamplesWaitingForKey.h deleted file mode 100644 index 8672bccdd1..0000000000 --- a/dom/media/platforms/agnostic/eme/SamplesWaitingForKey.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; 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/. */ - -#ifndef SamplesWaitingForKey_h_ -#define SamplesWaitingForKey_h_ - -#include "mozilla/TaskQueue.h" - -#include "PlatformDecoderModule.h" - -namespace mozilla { - -typedef nsTArray<uint8_t> CencKeyId; - -class CDMProxy; - -// Encapsulates the task of waiting for the CDMProxy to have the necessary -// keys to decrypt a given sample. -class SamplesWaitingForKey { -public: - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SamplesWaitingForKey) - - explicit SamplesWaitingForKey(MediaDataDecoder* aDecoder, - MediaDataDecoderCallback* aCallback, - TaskQueue* 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(MediaRawData* aSample); - - void NotifyUsable(const CencKeyId& aKeyId); - - void Flush(); - - void BreakCycles(); - -protected: - ~SamplesWaitingForKey(); - -private: - Mutex mMutex; - RefPtr<MediaDataDecoder> mDecoder; - MediaDataDecoderCallback* mDecoderCallback; - RefPtr<TaskQueue> mTaskQueue; - RefPtr<CDMProxy> mProxy; - nsTArray<RefPtr<MediaRawData>> mSamples; -}; - -} // namespace mozilla - -#endif // SamplesWaitingForKey_h_ diff --git a/dom/media/platforms/agnostic/eme/moz.build b/dom/media/platforms/agnostic/eme/moz.build deleted file mode 100644 index 74260b3ba2..0000000000 --- a/dom/media/platforms/agnostic/eme/moz.build +++ /dev/null @@ -1,22 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# 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' diff --git a/dom/media/platforms/moz.build b/dom/media/platforms/moz.build index 09d9afa4d2..d4dc579b19 100644 --- a/dom/media/platforms/moz.build +++ b/dom/media/platforms/moz.build @@ -32,9 +32,6 @@ DIRS += [ 'omx' ] -if CONFIG['MOZ_EME']: - DIRS += ['agnostic/eme'] - if CONFIG['MOZ_GMP']: DIRS += ['agnostic/gmp'] diff --git a/dom/media/test/mochitest.ini b/dom/media/test/mochitest.ini index 516c2beb03..2699c03ac2 100644 --- a/dom/media/test/mochitest.ini +++ b/dom/media/test/mochitest.ini @@ -425,9 +425,6 @@ support-files = dirac.ogg^headers^ dynamic_redirect.sjs dynamic_resource.sjs -#ifdef MOZ_EME - eme.js -#endif file_access_controls.html flac-s24.flac flac-s24.flac^headers^ @@ -684,38 +681,6 @@ tags=capturestream [test_decoder_disable.html] [test_defaultMuted.html] [test_delay_load.html] -#ifdef MOZ_EME -[test_eme_session_callable_value.html] -[test_eme_canvas_blocked.html] -skip-if = toolkit == 'android' # bug 1149374 -[test_eme_detach_media_keys.html] -skip-if = toolkit == 'android' # bug 1149374 -[test_eme_initDataTypes.html] -skip-if = toolkit == 'android' # bug 1149374 -[test_eme_missing_pssh.html] -skip-if = toolkit == 'android' # bug 1149374 -[test_eme_non_mse_fails.html] -skip-if = toolkit == 'android' # bug 1149374 -[test_eme_request_notifications.html] -skip-if = toolkit == 'android' # bug 1149374 -[test_eme_playback.html] -skip-if = toolkit == 'android' # bug 1149374 -[test_eme_requestKeySystemAccess.html] -skip-if = toolkit == 'android' # bug 1149374 -[test_eme_setMediaKeys_before_attach_MediaSource.html] -skip-if = toolkit == 'android' # bug 1149374 -[test_eme_stream_capture_blocked_case1.html] -tags=msg capturestream -skip-if = toolkit == 'android' # bug 1149374 -[test_eme_stream_capture_blocked_case2.html] -tags=msg capturestream -skip-if = toolkit == 'android' # bug 1149374 -[test_eme_stream_capture_blocked_case3.html] -tags=msg capturestream -skip-if = toolkit == 'android' # bug 1149374 -[test_eme_waitingforkey.html] -skip-if = toolkit == 'android' # bug 1149374 -#endif [test_empty_resource.html] [test_error_in_video_document.html] [test_error_on_404.html] diff --git a/dom/media/test/test_eme_canvas_blocked.html b/dom/media/test/test_eme_canvas_blocked.html deleted file mode 100644 index e84b6db402..0000000000 --- a/dom/media/test/test_eme_canvas_blocked.html +++ /dev/null @@ -1,58 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Test Encrypted Media Extensions</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> - <script type="text/javascript" src="manifest.js"></script> - <script type="text/javascript" src="eme.js"></script> -</head> -<body> -<pre id="test"> -<script class="testbody" type="text/javascript"> -var manager = new MediaTestManager; - -function startTest(test, token) -{ - manager.started(token); - - var sessions = []; - - var v = SetupEME(test, token); - v.preload = "auto"; // Required due to "canplay" not firing for MSE unless we do this. - - v.addEventListener("loadeddata", function(ev) { - var video = ev.target; - var canvas = document.createElement("canvas"); - canvas.width = video.videoWidth; - canvas.height = video.videoHeight; - document.body.appendChild(canvas); - var ctx = canvas.getContext("2d"); - var threwError = false; - try { - ctx.drawImage(video, 0, 0); - } catch (ex) { - threwError = true; - } - ok(threwError, TimeStamp(token) + " - Should throw an error when trying to draw EME video to canvas."); - manager.finished(token); - }); - - LoadTestWithManagedLoadToken(test, v, manager, token, - { onlyLoadFirstFragments:2, noEndOfStream:false }); -} - -function beginTest() { - manager.runTests(gEMETests, startTest); -} - -if (!IsMacOSSnowLeopardOrEarlier()) { - SimpleTest.waitForExplicitFinish(); - SetupEMEPref(beginTest); -} else { - todo(false, "Test disabled on this platform."); -} -</script> -</pre> -</body> -</html> diff --git a/dom/media/test/test_eme_detach_media_keys.html b/dom/media/test/test_eme_detach_media_keys.html deleted file mode 100644 index 6d3dc8467e..0000000000 --- a/dom/media/test/test_eme_detach_media_keys.html +++ /dev/null @@ -1,63 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Test Encrypted Media Extensions</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> - <script type="text/javascript" src="manifest.js"></script> - <script type="text/javascript" src="eme.js"></script> -</head> -<body> -<pre id="test"> -<video id="v" controls></video> -<script class="testbody" type="text/javascript"> - -SimpleTest.waitForExplicitFinish(); - -function createAndSet() { - return new Promise(function(resolve, reject) { - var m; - navigator.requestMediaKeySystemAccess(CLEARKEY_KEYSYSTEM, gCencMediaKeySystemConfig) - .then(function (access) { - return access.createMediaKeys(); - }) - .then(function (mediaKeys) { - m = mediaKeys; - return document.getElementById("v").setMediaKeys(mediaKeys); - }) - .then(function() { - resolve(m); - }); - } -)} - -var m1,m2; - -// Test that if we create and set two MediaKeys on one video element, -// that if the first MediaKeys we set on the media elemnt is still usable -// after the second MediaKeys has been set on the media element. -SetupEMEPref(() => { - createAndSet().then((m) => { - m1 = m; // Stash MediaKeys. - return createAndSet(); - }) - .then((m) => { - m2 = m; - is(document.getElementById("v").mediaKeys, m2, "Should have set MediaKeys on media element"); - ok(document.getElementById("v").mediaKeys != m1, "First MediaKeys should no longer be set on media element"); - var s = m1.createSession("temporary"); - return s.generateRequest("webm", StringToArrayBuffer(atob('YAYeAX5Hfod+V9ANHtANHg=='))); - }) - .then(() => { - ok(true, "Was able to generateRequest using second CDM"); - SimpleTest.finish(); - }, () => { - ok(false, "Was *NOT* able to generateRequest using second CDM"); - SimpleTest.finish(); - }); -}); - -</script> -</pre> -</body> -</html> diff --git a/dom/media/test/test_eme_initDataTypes.html b/dom/media/test/test_eme_initDataTypes.html deleted file mode 100644 index 4821c3cb82..0000000000 --- a/dom/media/test/test_eme_initDataTypes.html +++ /dev/null @@ -1,133 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Test Encrypted Media Extensions</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> - <script type="text/javascript" src="manifest.js"></script> - <script type="text/javascript" src="eme.js"></script> -</head> -<body> -<pre id="test"> -<script class="testbody" type="text/javascript"> - -var tests = [ - { - name: "One keyId", - initDataType: 'keyids', - initData: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A"]}', - expectedRequest: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A"],"type":"temporary"}', - sessionType: 'temporary', - expectPass: true, - }, - { - name: "Two keyIds", - initDataType: 'keyids', - initData: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A", "0DdtU9od-Bh5L3xbv0Xf_A"]}', - expectedRequest: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A","0DdtU9od-Bh5L3xbv0Xf_A"],"type":"temporary"}', - sessionType: 'temporary', - expectPass: true, - }, - { - name: "Two keyIds, temporary session", - initDataType: 'keyids', - initData: '{"type":"temporary", "kids":["LwVHf8JLtPrv2GUXFW2v_A", "0DdtU9od-Bh5L3xbv0Xf_A"]}', - expectedRequest: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A","0DdtU9od-Bh5L3xbv0Xf_A"],"type":"temporary"}', - sessionType: 'temporary', - expectPass: true, - }, - { - name: "Two keyIds, persistent session, type before kids", - initDataType: 'keyids', - initData: '{"type":"persistent-license", "kids":["LwVHf8JLtPrv2GUXFW2v_A", "0DdtU9od-Bh5L3xbv0Xf_A"]}', - expectedRequest: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A","0DdtU9od-Bh5L3xbv0Xf_A"],"type":"persistent-license"}', - sessionType: 'persistent-license', - expectPass: false, - }, - { - name: "Invalid keyId", - initDataType: 'keyids', - initData: '{"kids":["0"]}', - sessionType: 'temporary', - expectPass: false, - }, - { - name: "Empty keyId", - initDataType: 'keyids', - initData: '{"kids":[""]}', - sessionType: 'temporary', - expectPass: false, - }, - { - name: "Invalid initData", - initDataType: 'keyids', - initData: 'invalid initData', - sessionType: 'temporary', - expectPass: false, - }, - { - name: "'webm' initDataType", - initDataType: 'webm', - initData: 'YAYeAX5Hfod+V9ANHtANHg==', - expectedRequest: '{"kids":["YAYeAX5Hfod-V9ANHtANHg"],"type":"temporary"}', - sessionType: 'temporary', - expectPass: true, - }, - { - name: "'webm' initDataType with non 16 byte keyid", - initDataType: 'webm', - initData: 'YAYeAX5Hfod', - expectedRequest: '{\"kids\":[\"YAYeAX5Hfoc\"],\"type\":\"temporary\"}', - sessionType: 'temporary', - expectPass: true, - }, -]; - -function PrepareInitData(initDataType, initData) -{ - if (initDataType == "keyids") { - return new TextEncoder().encode(initData); - } else if (initDataType == "webm") { - return StringToArrayBuffer(atob(initData)); - } -} - -function Test(test) { - return new Promise(function(resolve, reject) { - var configs = [{ - initDataTypes: [test.initDataType], - videoCapabilities: [{contentType: 'video/mp4' }], - }]; - navigator.requestMediaKeySystemAccess('org.w3.clearkey', configs) - .then((access) => access.createMediaKeys()) - .then((mediaKeys) => { - var session = mediaKeys.createSession(test.sessionType); - session.addEventListener("message", function(event) { - is(event.messageType, "license-request", "'" + test.name + "' MediaKeyMessage type should be license-request."); - var text = new TextDecoder().decode(event.message); - is(text, test.expectedRequest, "'" + test.name + "' got expected response."); - is(text == test.expectedRequest, test.expectPass, - "'" + test.name + "' expected to " + (test.expectPass ? "pass" : "fail")); - resolve(); - }); - var initData = PrepareInitData(test.initDataType, test.initData); - return session.generateRequest(test.initDataType, initData); - } - ).catch((x) => { - ok(!test.expectPass, "'" + test.name + "' expected to fail."); - resolve(); - }); - }); -} - -function beginTest() { - Promise.all(tests.map(Test)).then(function() { SimpleTest.finish(); }); -} - -SimpleTest.waitForExplicitFinish(); -SetupEMEPref(beginTest); - -</script> -</pre> -</body> -</html> diff --git a/dom/media/test/test_eme_missing_pssh.html b/dom/media/test/test_eme_missing_pssh.html deleted file mode 100644 index 196ced4022..0000000000 --- a/dom/media/test/test_eme_missing_pssh.html +++ /dev/null @@ -1,92 +0,0 @@ -<!DOCTYPE HTML> -<html> - <head> - <title>Test Encrypted Media Extensions</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> - <script type="text/javascript" src="manifest.js"></script> - <script type="text/javascript" src="eme.js"></script> - </head> - <body> - <audio controls id="audio"></audio> - <pre id="test"> - <script class="testbody" type="text/javascript"> - - // Tests that a fragmented MP4 file without a PSSH, but with valid encrypted - // tracks with valid TENC boxes, is able to load with EME. - // We setup MSE before starting up EME, so that we exercise the "waiting for - // cdm" step in the MediaDecoderStateMachine. - - SimpleTest.waitForExplicitFinish(); - - var pssh = [ - 0x00, 0x00, 0x00, 0x00, - 0x70, 0x73, 0x73, 0x68, // BMFF box header (76 bytes, 'pssh') - 0x01, 0x00, 0x00, 0x00, // Full box header (version = 1, flags = 0) - 0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, // SystemID - 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b, - 0x00, 0x00, 0x00, 0x01, // KID_count (1) - 0x2f, 0xef, 0x8a, 0xd8, 0x12, 0xdf, 0x42, 0x97, - 0x83, 0xe9, 0xbf, 0x6e, 0x5e, 0x49, 0x3e, 0x53, - 0x00, 0x00, 0x00, 0x00 // Size of Data (0) - ]; - - var audio = document.getElementById("audio"); - - function LoadEME() { - var options = [{ - initDataType: 'cenc', - audioType: 'audio/mp4; codecs="mp4a.40.2"', - }]; - navigator.requestMediaKeySystemAccess("org.w3.clearkey", options) - .then((keySystemAccess) => { - return keySystemAccess.createMediaKeys(); - }, bail("Failed to request key system access.")) - - .then((mediaKeys) => { - audio.setMediaKeys(mediaKeys); - var session = mediaKeys.createSession(); - once(session, "message", (message) => { - is(message.messageType, 'license-request', "Expected a license-request"); - var license = new TextEncoder().encode(JSON.stringify({ - 'keys': [{ - 'kty':'oct', - 'kid':'L--K2BLfQpeD6b9uXkk-Uw', - 'k':HexToBase64('7f412f0575f44f718259beef56ec7771') - }], - 'type': 'temporary' - })); - session.update(license); - }); - session.generateRequest('cenc', new Uint8Array(pssh)); - }); - } - - function DownloadMedia(url, type, mediaSource) { - return new Promise(function(resolve, reject) { - var sourceBuffer = mediaSource.addSourceBuffer(type); - fetchWithXHR(url, (response) => { - once(sourceBuffer, "updateend", resolve); - sourceBuffer.appendBuffer(new Uint8Array(response)); - }); - }); - } - - function LoadMSE() { - var ms = new MediaSource(); - audio.src = URL.createObjectURL(ms); - - once(ms, "sourceopen", ()=>{ - DownloadMedia('short-audio-fragmented-cenc-without-pssh.mp4', 'audio/mp4; codecs="mp4a.40.2"', ms) - .then(() => { ms.endOfStream(); LoadEME();}); - }); - - audio.addEventListener("loadeddata", SimpleTest.finish); - } - - SetupEMEPref(LoadMSE); - - </script> - </pre> - </body> -</html> diff --git a/dom/media/test/test_eme_non_mse_fails.html b/dom/media/test/test_eme_non_mse_fails.html deleted file mode 100644 index ede3edc5f2..0000000000 --- a/dom/media/test/test_eme_non_mse_fails.html +++ /dev/null @@ -1,103 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Bug 1131392 - Test that EME does not work for non-MSE media</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> - <script type="text/javascript" src="manifest.js"></script> - <script type="text/javascript" src="eme.js"></script> -</head> -<body> -<pre id="test"> -<script class="testbody" type="text/javascript"> -var manager = new MediaTestManager; - -function DoSetMediaKeys(v, test) -{ - var options = [{ - initDataTypes: ["cenc"], - audioCapabilities: [{contentType: test.audioType}], - videoCapabilities: [{contentType: test.videoType}], - }]; - - return navigator.requestMediaKeySystemAccess(CLEARKEY_KEYSYSTEM, options) - - .then(function(keySystemAccess) { - return keySystemAccess.createMediaKeys(); - }) - - .catch(function() { - ok(false, token + " was not expecting failure (yet)"); - }) - - .then(function(mediaKeys) { - return v.setMediaKeys(mediaKeys); - }); -} - -function TestSetMediaKeys(test, token) -{ - manager.started(token); - - var v = document.createElement("video"); - - v.addEventListener("encrypted", function() { - ok(false, token + " should not fire encrypted event"); - }); - - var loadedMetadata = false; - v.addEventListener("loadedmetadata", function() { - loadedMetadata = true; - }); - - v.addEventListener("error", function() { - ok(true, token + " expected error event"); - ok(loadedMetadata, token + " expected loadedmetadata to have fired"); - manager.finished(token); - }); - - v.src = test.name; -} - -function TestSetSrc(test, token) -{ - manager.started(token); - - var v = document.createElement("video"); - v.addEventListener("error", function(err) { - ok(true, token + " got error setting src on video element, as expected"); - manager.finished(token); - }); - - DoSetMediaKeys(v, test) - - .then(function() { - v.src = test.name; - }) - - .catch(function() { - ok(false, token + " got error setting media keys"); - }); -} - -function startTest(test, token) -{ - TestSetMediaKeys(test, token + "_setMediaKeys"); - TestSetSrc(test, token + "_setSrc"); -} - -function beginTest() { - manager.runTests(gEMENonMSEFailTests, startTest); -} - -if (!IsMacOSSnowLeopardOrEarlier()) { - SimpleTest.waitForExplicitFinish(); - SetupEMEPref(beginTest); -} else { - todo(false, "Test disabled on this platform."); -} -</script> -</pre> -</body> -</html> - diff --git a/dom/media/test/test_eme_playback.html b/dom/media/test/test_eme_playback.html deleted file mode 100644 index a568402cd6..0000000000 --- a/dom/media/test/test_eme_playback.html +++ /dev/null @@ -1,188 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Test Encrypted Media Extensions</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> - <script type="text/javascript" src="manifest.js"></script> - <script type="text/javascript" src="http://test1.mochi.test:8888/tests/dom/media/test/eme.js"></script> -</head> -<body> -<pre id="test"> -<script class="testbody" type="text/javascript"> -var manager = new MediaTestManager; - -function ArrayBuffersEqual(a, b) { - if (a.byteLength != b.byteLength) { - return false; - } - var ua = new Uint8Array(a); - var ub = new Uint8Array(b); - for (var i = 0; i < ua.length; i++) { - if (ua[i] != ub[i]) { - return false; - } - } - return true; -} - -function KeysChangeFunc(session, keys, token) { - session.keyIdsReceived = []; - for (var keyid in keys) { - Log(token, "Set " + keyid + " to false in session[" + session.sessionId + "].keyIdsReceived"); - session.keyIdsReceived[keyid] = false; - } - return function(ev) { - var session = ev.target; - session.gotKeysChanged = true; - - var keyList = []; - var valueList = []; - var map = session.keyStatuses; - - // Test that accessing keys not known to the CDM has expected behaviour. - var absentKey = new Uint8Array([0xeb, 0xdd, 0x62, 0xf1, 0x68, 0x14, 0xd2, 0x7b, - 0x68, 0xef, 0x12, 0x2a, 0xfc, 0xe4, 0xae, 0x3c]); - is(map.has(absentKey), false, "Shouldn't have a key that's not in the media"); - is(map.get(absentKey), undefined, "Unknown keys should undefined status"); - - // Verify known keys have expected status. - for (var [key, val] of map.entries()) { - is(key.constructor, ArrayBuffer, "keyId should be ArrayBuffer"); - ok(map.has(key), "MediaKeyStatusMap.has() should work."); - is(map.get(key), val, "MediaKeyStatusMap.get() should work."); - keyList.push(key); - valueList.push(val); - is(val, "usable", token + ": key status should be usable"); - var kid = Base64ToHex(window.btoa(ArrayBufferToString(key))); - ok(kid in session.keyIdsReceived, TimeStamp(token) + " session[" + session.sessionId + "].keyIdsReceived contained " + kid + " as expected."); - session.keyIdsReceived[kid] = true; - } - - var index = 0; - for (var keyId of map.keys()) { - ok(ArrayBuffersEqual(keyId, keyList[index]), "MediaKeyStatusMap.keys() should correspond to entries"); - index++; - } - index = 0; - for (var val of map.values()) { - is(val, valueList[index], "MediaKeyStatusMap.values() should correspond to entries"); - index++; - } - } -} - -function startTest(test, token) -{ - manager.started(token); - - var sessions = []; - - var v = SetupEME(test, token, - { - onsessioncreated: function(session) { - sessions.push(session); - session.addEventListener("keystatuseschange", KeysChangeFunc(session, test.keys, token), false); - - session.numKeystatuseschangeEvents = 0; - session.numOnkeystatuseschangeEvents = 0; - - session.addEventListener("keystatuseschange", function() { - session.numKeystatuseschangeEvents += 1; - }); - session.onkeystatuseschange = function() { - session.numOnkeystatuseschangeEvents += 1; - }; - - session.numMessageEvents = 0; - session.numOnMessageEvents = 0; - session.addEventListener("message", function() { - session.numMessageEvents += 1; - }); - session.onmessage = function() { - session.numOnMessageEvents += 1; - }; - } - } - ); - - document.body.appendChild(v); - - var gotEncrypted = 0; - - v.addEventListener("encrypted", function(ev) { - gotEncrypted += 1; - }); - - v.addEventListener("loadedmetadata", function() { - ok(SpecialPowers.do_lookupGetter(v, "isEncrypted").apply(v), - TimeStamp(token) + " isEncrypted should be true"); - is(v.isEncrypted, undefined, "isEncrypted should not be accessible from content"); - }); - - v.addEventListener("ended", function(ev) { - ok(true, TimeStamp(token) + " got ended event"); - - is(gotEncrypted, test.sessionCount, - TimeStamp(token) + " encrypted events expected: " + test.sessionCount - + ", actual: " + gotEncrypted); - - ok(Math.abs(test.duration - v.duration) < 0.1, - TimeStamp(token) + " Duration of video should be corrrect"); - ok(Math.abs(test.duration - v.currentTime) < 0.1, - TimeStamp(token) + " Current time should be same as duration"); - - // Verify all sessions had all keys went sent to the CDM usable, and thus - // that we received keystatuseschange event(s). - is(sessions.length, test.sessionCount, TimeStamp(token) + " should have " - + test.sessionCount - + " session" + (test.sessionCount === 1 ? "" : "s")); - var keyIdsReceived = []; - for (var keyid in test.keys) { keyIdsReceived[keyid] = false; } - for (var i = 0; i < sessions.length; i++) { - var session = sessions[i]; - ok(session.gotKeysChanged, - TimeStamp(token) + " session[" + session.sessionId - + "] should have received at least one keychange event"); - for (var kid in session.keyIdsReceived) { - Log(token, "session[" + session.sessionId + "] key " + kid + " = " + (session.keyIdsReceived[kid] ? "true" : "false")); - if (session.keyIdsReceived[kid]) { keyIdsReceived[kid] = true; } - } - ok(session.numKeystatuseschangeEvents > 0, TimeStamp(token) + " should get key status changes"); - is(session.numKeystatuseschangeEvents, session.numOnkeystatuseschangeEvents, - TimeStamp(token) + " should have as many keystatuseschange event listener calls as event handler calls."); - - ok(session.numMessageEvents > 0, TimeStamp(token) + " should get message events"); - is(session.numMessageEvents, session.numOnMessageEvents, - TimeStamp(token) + " should have as many message event listener calls as event handler calls."); - } - for (var kid in keyIdsReceived) { - ok(keyIdsReceived[kid], TimeStamp(token) + " key with id " + kid + " was usable as expected"); - } - - v.closeSessions().then(() => manager.finished(token)); - }); - - LoadTest(test, v, token) - .then(function() { - v.play(); - }).catch(function() { - ok(false, token + " failed to load"); - manager.finished(token); - }); -} - -function beginTest() { - manager.runTests(gEMETests, startTest); -} - -if (!IsMacOSSnowLeopardOrEarlier()) { - SimpleTest.waitForExplicitFinish(); - SetupEMEPref(beginTest); -} else { - todo(false, "Test disabled on this platform."); -} -</script> -</pre> -</body> -</html> diff --git a/dom/media/test/test_eme_requestKeySystemAccess.html b/dom/media/test/test_eme_requestKeySystemAccess.html deleted file mode 100644 index 21ee91a68c..0000000000 --- a/dom/media/test/test_eme_requestKeySystemAccess.html +++ /dev/null @@ -1,484 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Test Encrypted Media Extensions</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> - <script type="text/javascript" src="manifest.js"></script> - <script type="text/javascript" src="eme.js"></script> -</head> -<body> -<pre id="test"> -<script class="testbody" type="text/javascript"> - -const SUPPORTED_LABEL = "pass label"; - -function ValidateConfig(name, expected, observed) { - info("ValidateConfig " + name); - info("expected cfg=" + JSON.stringify(expected)); - info("observed cfg=" + JSON.stringify(observed)); - - is(observed.label, expected.label, name + " label should match"); - if (expected.initDataTypes) { - ok(expected.initDataTypes.every((element, index, array) => observed.initDataTypes.includes(element)), name + " initDataTypes should match."); - } - - if (expected.audioCapabilities) { - ok(expected.audioCapabilities.length == 1, "Test function can only handle one capability."); - ok(observed.audioCapabilities.length == 1, "Test function can only handle one capability."); - is(observed.audioCapabilities[0].contentType, expected.audioCapabilities[0].contentType, name + " audioCapabilities should match."); - } - if (typeof expected.videoCapabilities !== 'undefined') { - info("expected.videoCapabilities=" + expected.videoCapabilities); - dump("expected.videoCapabilities=" + expected.videoCapabilities + "\n"); - ok(expected.videoCapabilities.length == 1, "Test function can only handle one capability."); - ok(observed.videoCapabilities.length == 1, "Test function can only handle one capability."); - is(observed.videoCapabilities[0].contentType, expected.videoCapabilities[0].contentType, name + " videoCapabilities should match."); - } - if (expected.sessionTypes) { - is(expected.sessionTypes.length, observed.sessionTypes.length, "Should have expected number of sessionTypes"); - for (var i = 0; i < expected.sessionTypes.length; i++) { - is(expected[i], observed[i], "Session type " + i + " should match"); - } - } -} - -function Test(test) { - var name = "'" + test.name + "'"; - return new Promise(function(resolve, reject) { - var p; - if (test.options) { - var keySystem = (test.keySystem !== undefined) ? test.keySystem : CLEARKEY_KEYSYSTEM; - p = navigator.requestMediaKeySystemAccess(keySystem, test.options); - } else { - p = navigator.requestMediaKeySystemAccess(keySystem); - } - p.then( - function(keySystemAccess) { - ok(test.shouldPass, name + " passed and was expected to " + (test.shouldPass ? "pass" : "fail")); - is(keySystemAccess.keySystem, CLEARKEY_KEYSYSTEM, "CDM keySystem should be in MediaKeySystemAccess.keySystem"); - ValidateConfig(name, test.expectedConfig, keySystemAccess.getConfiguration()); - resolve(); - }, - function(ex) { - if (test.shouldPass) { - info(name + " failed: " + ex); - } - ok(!test.shouldPass, name + " failed and was expected to " + (test.shouldPass ? "pass" : "fail")); - resolve(); - }); - }); -} - -var tests = [ - { - name: 'Empty keySystem string', - keySystem: '', - options: [ - { - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4'}], - } - ], - shouldPass: false, - }, - { - name: 'Empty options specified', - options: [ ], - shouldPass: false, - }, - { - name: 'Undefined options', - shouldPass: false, - }, - { - name: 'Basic MP4 cenc', - options: [ - { - label: SUPPORTED_LABEL, - initDataTypes: ['cenc'], - audioCapabilities: [{contentType: 'audio/mp4'}], - videoCapabilities: [{contentType: 'video/mp4'}], - } - ], - expectedConfig: { - label: SUPPORTED_LABEL, - initDataTypes: ['cenc'], - audioCapabilities: [{contentType: 'audio/mp4'}], - videoCapabilities: [{contentType: 'video/mp4'}], - }, - shouldPass: true, - }, - { - name: 'Invalid keysystem failure', - keySystem: 'bogusKeySystem', - options: [ - { - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4'}], - } - ], - shouldPass: false, - }, - { - name: 'Invalid initDataType', - options: [ - { - initDataTypes: ['bogus'], - audioCapabilities: [{contentType: 'audio/mp4'}], - } - ], - shouldPass: false, - }, - { - name: 'Valid initDataType after invalid', - options: [ - { - label: SUPPORTED_LABEL, - initDataTypes: ['bogus', 'invalid', 'cenc'], - audioCapabilities: [{contentType: 'audio/mp4'}], - } - ], - expectedConfig: { - label: SUPPORTED_LABEL, - initDataTypes: ['cenc'], - audioCapabilities: [{contentType: 'audio/mp4'}], - }, - shouldPass: true, - }, - { - name: 'Invalid videoType', - options: [ - { - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/bogus'}], - } - ], - shouldPass: false, - }, - { - name: 'Invalid distinctiveIdentifier fails', - options: [ - { - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4'}], - distinctiveIdentifier: 'bogus', - persistentState: 'bogus', - } - ], - shouldPass: false, - }, - { - name: 'distinctiveIdentifier is prohibited for ClearKey', - options: [ - { - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4'}], - distinctiveIdentifier: 'required', - } - ], - shouldPass: false, - }, - { - name: 'Invalid persistentState fails', - options: [ - { - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4'}], - persistentState: 'bogus', - } - ], - shouldPass: false, - }, - { - name: 'Invalid robustness unsupported', - options: [ - { - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4', robustness: 'very much so'}], - } - ], - shouldPass: false, - }, - { - name: 'Unexpected config entry should be ignored', - options: [ - { - label: SUPPORTED_LABEL, - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4'}], - unexpectedEntry: 'this should be ignored', - } - ], - expectedConfig: { - label: SUPPORTED_LABEL, - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4'}], - }, - shouldPass: true, - }, - { - name: 'Invalid option followed by valid', - options: [ - { - label: "this config should not be supported", - initDataTypes: ['bogus'], - }, - { - label: SUPPORTED_LABEL, - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4'}], - } - ], - expectedConfig: { - label: SUPPORTED_LABEL, - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4'}], - }, - shouldPass: true, - }, - { - name: 'Persistent-license should not be supported by ClearKey', - options: [ - { - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4'}], - sessionTypes: ['persistent-license'], - persistentState: 'optional', - } - ], - shouldPass: false, - }, - { - name: 'Persistent-usage-record should not be supported by ClearKey', - options: [ - { - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4'}], - sessionTypes: ['persistent-usage-record'], - persistentState: 'optional', - } - ], - shouldPass: false, - }, - { - name: 'MP4 audio container', - options: [ - { - label: SUPPORTED_LABEL, - initDataTypes: ['cenc'], - audioCapabilities: [{contentType: 'audio/mp4'}], - } - ], - expectedConfig: { - label: SUPPORTED_LABEL, - initDataTypes: ['cenc'], - audioCapabilities: [{contentType: 'audio/mp4'}], - }, - shouldPass: true, - }, - { - name: 'MP4 audio container with AAC-LC', - options: [ - { - label: SUPPORTED_LABEL, - initDataTypes: ['cenc'], - audioCapabilities: [{contentType: 'audio/mp4; codecs="mp4a.40.2"'}], - } - ], - expectedConfig: { - label: SUPPORTED_LABEL, - initDataTypes: ['cenc'], - audioCapabilities: [{contentType: 'audio/mp4; codecs="mp4a.40.2"'}], - }, - shouldPass: true, - }, - { - name: 'MP4 audio container with invalid codecs', - options: [ - { - initDataTypes: ['cenc'], - audioCapabilities: [{contentType: 'audio/mp4; codecs="bogus"'}], - } - ], - shouldPass: false, - }, - { - name: 'MP4 audio container with mp3 is unsupported', - options: [ - { - initDataTypes: ['cenc'], - audioCapabilities: [{contentType: 'audio/mp4; codecs="mp3"'}], - } - ], - shouldPass: false, - }, - { - name: 'MP4 video container type with an mp3 codec is unsupported', - options: [ - { - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4; codecs="mp3"'}], - } - ], - shouldPass: false, - }, - { - name: 'MP4 audio container type with a video codec is unsupported', - options: [ - { - initDataTypes: ['cenc'], - audioCapabilities: [{contentType: 'audio/mp4; codecs="avc1.42E01E"'}], - } - ], - shouldPass: false, - }, - { - name: 'MP4 video container with constrained baseline h.264', - options: [ - { - label: SUPPORTED_LABEL, - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4; codecs="avc1.42E01E"'}], - } - ], - expectedConfig: { - label: SUPPORTED_LABEL, - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4; codecs="avc1.42E01E"'}], - }, - shouldPass: true, - }, - { - name: 'MP4 video container with invalid codecs', - options: [ - { - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4; codecs="bogus"'}], - } - ], - shouldPass: false, - }, - { - name: 'MP4 video container with both audio and video codec type in videoType', - options: [ - { - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4; codecs="avc1.42E01E,mp4a.40.2"'}], - } - ], - shouldPass: false, - }, - { - name: 'MP4 audio and video type both specified', - options: [ - { - label: SUPPORTED_LABEL, - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4; codecs="avc1.42E01E"'}], - audioCapabilities: [{contentType: 'audio/mp4; codecs="mp4a.40.2"'}], - } - ], - expectedConfig: { - label: SUPPORTED_LABEL, - initDataTypes: ['cenc'], - videoCapabilities: [{contentType: 'video/mp4; codecs="avc1.42E01E"'}], - audioCapabilities: [{contentType: 'audio/mp4; codecs="mp4a.40.2"'}], - }, - shouldPass: true, - }, - { - name: 'Basic WebM video', - options: [ - { - label: SUPPORTED_LABEL, - initDataTypes: ['webm'], - videoCapabilities: [{contentType: 'video/webm'}], - } - ], - expectedConfig: { - label: SUPPORTED_LABEL, - initDataTypes: ['webm'], - videoCapabilities: [{contentType: 'video/webm'}], - }, - shouldPass: true, - }, - { - name: 'Basic WebM audio', - options: [ - { - label: SUPPORTED_LABEL, - initDataTypes: ['webm'], - audioCapabilities: [{contentType: 'audio/webm'}], - } - ], - expectedConfig: { - label: SUPPORTED_LABEL, - initDataTypes: ['webm'], - audioCapabilities: [{contentType: 'audio/webm'}], - }, - shouldPass: true, - }, - { - name: 'Webm with Vorbis audio and VP8 video.', - options: [ - { - label: SUPPORTED_LABEL, - initDataTypes: ['webm'], - videoCapabilities: [{contentType: 'video/webm;codecs="vp8"'}], - audioCapabilities: [{contentType: 'audio/webm;codecs="vorbis"'}], - } - ], - expectedConfig: { - label: SUPPORTED_LABEL, - initDataTypes: ['webm'], - videoCapabilities: [{contentType: 'video/webm;codecs="vp8"'}], - audioCapabilities: [{contentType: 'audio/webm;codecs="vorbis"'}], - }, - shouldPass: true, - }, - { - name: 'Webm with Vorbis audio and VP9 video.', - options: [ - { - label: SUPPORTED_LABEL, - initDataTypes: ['webm'], - videoCapabilities: [{contentType: 'video/webm;codecs="vp9"'}], - audioCapabilities: [{contentType: 'audio/webm;codecs="vorbis"'}], - } - ], - expectedConfig: { - label: SUPPORTED_LABEL, - initDataTypes: ['webm'], - videoCapabilities: [{contentType: 'video/webm;codecs="vp9"'}], - audioCapabilities: [{contentType: 'audio/webm;codecs="vorbis"'}], - }, - shouldPass: true, - }, - { - name: 'Webm with bogus video.', - options: [ - { - initDataTypes: ['webm'], - videoCapabilities: [{contentType: 'video/webm;codecs="bogus"'}], - } - ], - shouldPass: false, - }, -]; - -function beginTest() { - Promise.all(tests.map(Test)).then(function() { SimpleTest.finish(); }); -} - -if (!IsMacOSSnowLeopardOrEarlier()) { - SimpleTest.waitForExplicitFinish(); - SetupEMEPref(beginTest); -} else { - todo(false, "Test disabled on this platform."); -} - -</script> -</pre> -</body> -</html> diff --git a/dom/media/test/test_eme_request_notifications.html b/dom/media/test/test_eme_request_notifications.html deleted file mode 100644 index c2fab5b152..0000000000 --- a/dom/media/test/test_eme_request_notifications.html +++ /dev/null @@ -1,88 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Test Encrypted Media Extensions</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> - <script type="text/javascript" src="manifest.js"></script> - <script type="text/javascript" src="eme.js"></script> -</head> -<body> -<pre id="test"> -<script class="testbody" type="text/javascript"> -var manager = new MediaTestManager; - -function SetPrefs(prefs) { - return new Promise(function(resolve, reject) { - SpecialPowers.pushPrefEnv({"set": prefs}, function() { resolve(); }); - }); -} - -function observe() { - return new Promise(function(resolve, reject) { - var observer = function(subject, topic, data) { - SpecialPowers.Services.obs.removeObserver(observer, "mediakeys-request"); - resolve(JSON.parse(data).status); - }; - SpecialPowers.Services.obs.addObserver(observer, "mediakeys-request", false); - }); -} - -function Test(test) { - var p = test.prefs ? SetPrefs(test.prefs) : Promise.resolve(); - observedStatus = "nothing"; - var name = "'" + test.keySystem + "'"; - - var res = observe().then((status) => { - is(status, test.expectedStatus, name + " expected status"); - }); - - p.then(() => navigator.requestMediaKeySystemAccess(test.keySystem, gCencMediaKeySystemConfig)) - .then((keySystemAccess) => keySystemAccess.createMediaKeys()); - - return res; -} - -const isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1; - -var tests = [ - { - keySystem: CLEARKEY_KEYSYSTEM, - expectedStatus: 'cdm-created', - prefs: [["media.eme.enabled", false]] - }, - { - keySystem: "com.widevine.alpha", - expectedStatus: 'api-disabled', - prefs: [["media.eme.enabled", false]] - }, - { - keySystem: "com.widevine.alpha", - expectedStatus: (isWinXP ? 'cdm-not-supported' : 'cdm-disabled'), - prefs: [["media.eme.enabled", true], ["media.gmp-widevinecdm.enabled", false]] - }, - { - keySystem: "com.widevine.alpha", - expectedStatus: (isWinXP ? 'cdm-not-supported' : 'cdm-not-installed'), - prefs: [["media.eme.enabled", true], , ["media.gmp-widevinecdm.enabled", true]] - }, - { - keySystem: CLEARKEY_KEYSYSTEM, - expectedStatus: 'cdm-created', - prefs: [["media.eme.enabled", true]] - } -]; - -SetupEMEPref(function() { - tests.reduce(function(p,c,i,array) { - return p.then(function() { return Test(c); }); - }, Promise.resolve()).then(SimpleTest.finish); -}); - - -SimpleTest.waitForExplicitFinish(); - -</script> -</pre> -</body> -</html> diff --git a/dom/media/test/test_eme_session_callable_value.html b/dom/media/test/test_eme_session_callable_value.html deleted file mode 100644 index 5c5f51e307..0000000000 --- a/dom/media/test/test_eme_session_callable_value.html +++ /dev/null @@ -1,35 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Test Encrypted Media Extensions</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> - <script type="text/javascript" src="manifest.js"></script> - <script type="text/javascript" src="eme.js"></script> -</head> -<body> -<pre id="test"> -<script class="testbody" type="text/javascript"> - -function Test() { - navigator.requestMediaKeySystemAccess(CLEARKEY_KEYSYSTEM, gCencMediaKeySystemConfig) - .then(access => access.createMediaKeys()) - .then(mediaKeys => { - var initData = (new TextEncoder()).encode( 'this is an invalid license, and that is ok'); - var s = mediaKeys.createSession("temporary"); - s.generateRequest("cenc", initData); // ignore result. - // "update()" call should fail, because MediaKeySession is "not callable" - // yet, since CDM won't have had a chance to set the sessionId on MediaKeySession. - return s.update(initData); - }) - .then(()=>{ok(false, "An exception should be thrown; MediaKeySession should be not callable."); SimpleTest.finish();}, - ()=>{ok(true, "We expect this to fail; MediaKeySession should be not callable."); SimpleTest.finish();}); -} - -SimpleTest.waitForExplicitFinish(); -SetupEMEPref(Test); - -</script> -</pre> -</body> -</html> diff --git a/dom/media/test/test_eme_setMediaKeys_before_attach_MediaSource.html b/dom/media/test/test_eme_setMediaKeys_before_attach_MediaSource.html deleted file mode 100644 index 72bc77124d..0000000000 --- a/dom/media/test/test_eme_setMediaKeys_before_attach_MediaSource.html +++ /dev/null @@ -1,41 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Test Encrypted Media Extensions</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> - <script type="text/javascript" src="manifest.js"></script> - <script type="text/javascript" src="eme.js"></script> -</head> -<body> -<pre id="test"> -<script class="testbody" type="text/javascript"> - -function beginTest() { - var video = document.createElement("video"); - - navigator.requestMediaKeySystemAccess(CLEARKEY_KEYSYSTEM, gCencMediaKeySystemConfig) - .then(function(keySystemAccess) { - return keySystemAccess.createMediaKeys(); - }) - .then(mediaKeys => { - return video.setMediaKeys(mediaKeys); - }) - .then(() => { - var ms = new MediaSource(); - ms.addEventListener("sourceopen", ()=>{ok(true, "MediaSource should open"); SimpleTest.finish();}); - video.addEventListener("error", ()=>{ok(false, "Shouldn't error."); SimpleTest.finish();}); - video.src = URL.createObjectURL(ms); - }); -} - -if (!IsMacOSSnowLeopardOrEarlier()) { - SimpleTest.waitForExplicitFinish(); - SetupEMEPref(beginTest); -} else { - todo(false, "Test disabled on this platform."); -} -</script> -</pre> -</body> -</html> diff --git a/dom/media/test/test_eme_stream_capture_blocked_case1.html b/dom/media/test/test_eme_stream_capture_blocked_case1.html deleted file mode 100644 index 61e8d673f3..0000000000 --- a/dom/media/test/test_eme_stream_capture_blocked_case1.html +++ /dev/null @@ -1,52 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Test Encrypted Media Extensions</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> - <script type="text/javascript" src="manifest.js"></script> - <script type="text/javascript" src="eme.js"></script> -</head> -<body> -<pre id="test"> -<script class="testbody" type="text/javascript"> -var manager = new MediaTestManager; - -function startTest(test, token) -{ - // Three cases: - // 1. setting MediaKeys on an element captured by MediaElementSource should fail, and - // 2. creating a MediaElementSource on a media element with a MediaKeys should fail, and - // 3. capturing a media element with mozCaptureStream that has a MediaKeys should fail. - - // Case 1. setting MediaKeys on an element captured by MediaElementSource should fail. - var case1token = token + "_case1"; - var setKeysFailed = function() { - ok(true, TimeStamp(case1token) + " setMediaKeys failed as expected."); - manager.finished(case1token); - }; - var v1 = SetupEME(test, case1token, { onSetKeysFail: setKeysFailed }); - var context = new AudioContext(); - var node = context.createMediaElementSource(v1); - v1.addEventListener("loadeddata", function(ev) { - ok(false, TimeStamp(case1token) + " should never reach loadeddata, as setMediaKeys should fail"); - }); - manager.started(case1token); - LoadTestWithManagedLoadToken(test, v1, manager, case1token, - { onlyLoadFirstFragments:2, noEndOfStream:false }); -} - -function beginTest() { - manager.runTests(gEMETests, startTest); -} - -if (!IsMacOSSnowLeopardOrEarlier()) { - SimpleTest.waitForExplicitFinish(); - SetupEMEPref(beginTest); -} else { - todo(false, "Test disabled on this platform."); -} -</script> -</pre> -</body> -</html> diff --git a/dom/media/test/test_eme_stream_capture_blocked_case2.html b/dom/media/test/test_eme_stream_capture_blocked_case2.html deleted file mode 100644 index 48c8bf3e4a..0000000000 --- a/dom/media/test/test_eme_stream_capture_blocked_case2.html +++ /dev/null @@ -1,55 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Test Encrypted Media Extensions</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> - <script type="text/javascript" src="manifest.js"></script> - <script type="text/javascript" src="eme.js"></script> -</head> -<body> -<pre id="test"> -<script class="testbody" type="text/javascript"> -var manager = new MediaTestManager; - -function startTest(test, token) -{ - // Three cases: - // 1. setting MediaKeys on an element captured by MediaElementSource should fail, and - // 2. creating a MediaElementSource on a media element with a MediaKeys should fail, and - // 3. capturing a media element with mozCaptureStream that has a MediaKeys should fail. - - // Case 2. creating a MediaElementSource on a media element with a MediaKeys should fail. - var case2token = token + "_case2"; - var v2 = SetupEME(test, case2token); - v2.addEventListener("loadeddata", function(ev) { - ok(true, case2token + " should reach loadeddata"); - var threw = false; - try { - var context = new AudioContext(); - var node = context.createMediaElementSource(v2); - } catch (e) { - threw = true; - } - ok(threw, "Should throw an error creating a MediaElementSource on an EME video."); - manager.finished(case2token); - }); - manager.started(case2token); - LoadTestWithManagedLoadToken(test, v2, manager, case2token, - { onlyLoadFirstFragments:2, noEndOfStream:false }); -} - -function beginTest() { - manager.runTests(gEMETests, startTest); -} - -if (!IsMacOSSnowLeopardOrEarlier()) { - SimpleTest.waitForExplicitFinish(); - SetupEMEPref(beginTest); -} else { - todo(false, "Test disabled on this platform."); -} -</script> -</pre> -</body> -</html> diff --git a/dom/media/test/test_eme_stream_capture_blocked_case3.html b/dom/media/test/test_eme_stream_capture_blocked_case3.html deleted file mode 100644 index 1af4e0aadf..0000000000 --- a/dom/media/test/test_eme_stream_capture_blocked_case3.html +++ /dev/null @@ -1,54 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Test Encrypted Media Extensions</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> - <script type="text/javascript" src="manifest.js"></script> - <script type="text/javascript" src="eme.js"></script> -</head> -<body> -<pre id="test"> -<script class="testbody" type="text/javascript"> -var manager = new MediaTestManager; - -function startTest(test, token) -{ - // Three cases: - // 1. setting MediaKeys on an element captured by MediaElementSource should fail, and - // 2. creating a MediaElementSource on a media element with a MediaKeys should fail, and - // 3. capturing a media element with mozCaptureStream that has a MediaKeys should fail. - - // Case 3. capturing a media element with mozCaptureStream that has a MediaKeys should fail. - var case3token = token + "_case3"; - var v3 = SetupEME(test, case3token); - v3.addEventListener("loadeddata", function(ev) { - ok(true, TimeStamp(case3token) + " should reach loadeddata"); - var threw = false; - try { - var stream = v3.mozCaptureStreamUntilEnded(); - } catch (e) { - threw = true; - } - ok(threw, TimeStamp(case3token) + " Should throw an error calling mozCaptureStreamUntilEnded an EME video."); - manager.finished(case3token); - }); - manager.started(case3token); - LoadTestWithManagedLoadToken(test, v3, manager, case3token, - { onlyLoadFirstFragments:2, noEndOfStream:false }); -} - -function beginTest() { - manager.runTests(gEMETests, startTest); -} - -if (!IsMacOSSnowLeopardOrEarlier()) { - SimpleTest.waitForExplicitFinish(); - SetupEMEPref(beginTest); -} else { - todo(false, "Test disabled on this platform."); -} -</script> -</pre> -</body> -</html> diff --git a/dom/media/test/test_eme_waitingforkey.html b/dom/media/test/test_eme_waitingforkey.html deleted file mode 100644 index ce808342bb..0000000000 --- a/dom/media/test/test_eme_waitingforkey.html +++ /dev/null @@ -1,117 +0,0 @@ -<!DOCTYPE HTML> -<html> -<head> - <title>Test Encrypted Media Extensions</title> - <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> - <script type="text/javascript" src="manifest.js"></script> - <script type="text/javascript" src="http://test1.mochi.test:8888/tests/dom/media/test/eme.js"></script> -</head> -<body> -<pre id="test"> -<script class="testbody" type="text/javascript"> -var manager = new MediaTestManager; - -function startTest(test, token) -{ - // Test if the appropriate preconditions are met such that we can start - // prcoessing delayed sessions. - function TestIfDoneDelaying() - { - var got = "Got:"; - if (loaded) { got += " loaded,"; } - got += " " + gotEncrypted + "/" + test.sessionCount + " sessions,"; - got += " " + gotWaitingForKey + " waiting for key events" - if (loaded && gotEncrypted == test.sessionCount && gotWaitingForKey > 0) { - Log(token, got + " -> Update sessions with keys"); - params.ProcessSessions(); - } else { - Log(token, got + " -> Wait for more..."); - } - } - - manager.started(token); - - var updatedSessionsCount = 0; - var loaded = false; - - var params = { - // params will be populated with a ProcessSessions() callback, that can be - // called to process delayed sessions. - delaySessions: true, - // Function to be called once we start processing and updating sessions. - // This should only be called once the preconditions in TestIfDoneDealying - // are met. - onsessionupdated: function(session) { - updatedSessionsCount += 1; - if (updatedSessionsCount == test.sessionCount) { - info(TimeStamp(token) + " Updated all sessions, loading complete -> Play"); - v.play(); - } else { - info(TimeStamp(token) + " Updated " + updatedSessionsCount + "/" + test.sessionCount + " sessions so far"); - } - }, - }; - var v = SetupEME(test, token, params); - - document.body.appendChild(v); - - var gotEncrypted = 0; - var gotWaitingForKey = 0; - var gotOnwaitingforkey = 0; - - v.addEventListener("encrypted", function() { - gotEncrypted += 1; - TestIfDoneDelaying(); - }); - - v.addEventListener("waitingforkey", function() { - gotWaitingForKey += 1; - TestIfDoneDelaying() - }); - - v.onwaitingforkey = function() { - gotOnwaitingforkey += 1; - }; - - v.addEventListener("loadedmetadata", function() { - ok(SpecialPowers.do_lookupGetter(v, "isEncrypted").apply(v), - TimeStamp(token) + " isEncrypted should be true"); - is(v.isEncrypted, undefined, "isEncrypted should not be accessible from content"); - }); - - v.addEventListener("ended", function() { - ok(true, TimeStamp(token) + " got ended event"); - // We expect only one waitingForKey as we delay until all sessions are ready. - // I.e. one waitingForKey should be fired, after which, we process all sessions, - // so it should not be possible to be blocked by a key after that point. - ok(gotWaitingForKey == 1, "Expected number 1 wait, got: " + gotWaitingForKey); - ok(gotOnwaitingforkey == gotWaitingForKey, "Should have as many event listener calls as event handler calls, got: " + gotOnwaitingforkey); - - v.closeSessions().then(() => manager.finished(token)); - }); - - LoadTest(test, v, token) - .then(function() { - loaded = true; - TestIfDoneDelaying(); - }).catch(function() { - ok(false, token + " failed to load"); - manager.finished(token); - }); -} - -function beginTest() { - manager.runTests(gEMETests, startTest); -} - -if (!IsMacOSSnowLeopardOrEarlier()) { - SimpleTest.waitForExplicitFinish(); - SetupEMEPref(beginTest); -} else { - todo(false, "Test disabled on this platform."); -} -</script> -</pre> -</body> -</html> diff --git a/dom/media/webaudio/AudioContext.cpp b/dom/media/webaudio/AudioContext.cpp index 44285735be..9539133a4f 100755 --- a/dom/media/webaudio/AudioContext.cpp +++ b/dom/media/webaudio/AudioContext.cpp @@ -372,13 +372,6 @@ AudioContext::CreateMediaElementSource(HTMLMediaElement& aMediaElement, return nullptr; } -#ifdef MOZ_EME - if (aMediaElement.ContainsRestrictedContent()) { - aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return nullptr; - } -#endif - if (CheckClosed(aRv)) { return nullptr; } diff --git a/dom/webidl/HTMLMediaElement.webidl b/dom/webidl/HTMLMediaElement.webidl index ad31f38cbc..7f0f9f8571 100644 --- a/dom/webidl/HTMLMediaElement.webidl +++ b/dom/webidl/HTMLMediaElement.webidl @@ -153,24 +153,6 @@ partial interface HTMLMediaElement { attribute EventHandler onmozinterruptend; }; -#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<void> setMediaKeys(MediaKeys? mediaKeys); - - [Pref="media.eme.apiVisible"] - attribute EventHandler onencrypted; - - [Pref="media.eme.apiVisible"] - attribute EventHandler onwaitingforkey; -}; -#endif - // This is just for testing partial interface HTMLMediaElement { [Pref="media.useAudioChannelService.testing"] 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 057924bb73..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, MediaKeyMessageEventInit eventInitDict)] -interface MediaKeyMessageEvent : Event { - readonly attribute MediaKeyMessageType messageType; - [Throws] - readonly attribute ArrayBuffer message; -}; - -dictionary MediaKeyMessageEventInit : EventInit { - required MediaKeyMessageType messageType; - required ArrayBuffer message; -}; diff --git a/dom/webidl/MediaKeySession.webidl b/dom/webidl/MediaKeySession.webidl deleted file mode 100644 index 8ca5745c44..0000000000 --- a/dom/webidl/MediaKeySession.webidl +++ /dev/null @@ -1,47 +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<void> closed; - - readonly attribute MediaKeyStatusMap keyStatuses; - - attribute EventHandler onkeystatuseschange; - - attribute EventHandler onmessage; - - [NewObject] - Promise<void> generateRequest(DOMString initDataType, BufferSource initData); - - [NewObject] - Promise<boolean> load(DOMString sessionId); - - // session operations - [NewObject] - Promise<void> update(BufferSource response); - - [NewObject] - Promise<void> close(); - - [NewObject] - Promise<void> remove(); -}; diff --git a/dom/webidl/MediaKeyStatusMap.webidl b/dom/webidl/MediaKeyStatusMap.webidl deleted file mode 100644 index 1f34b5dc7c..0000000000 --- a/dom/webidl/MediaKeyStatusMap.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 MediaKeyStatus { - "usable", - "expired", - "released", - "output-restricted", - "output-downscaled", - "status-pending", - "internal-error" -}; - -[Pref="media.eme.apiVisible"] -interface MediaKeyStatusMap { - iterable<ArrayBuffer,MediaKeyStatus>; - readonly attribute unsigned long size; - boolean has (BufferSource keyId); - [Throws] - any get (BufferSource keyId); -}; diff --git a/dom/webidl/MediaKeySystemAccess.webidl b/dom/webidl/MediaKeySystemAccess.webidl deleted file mode 100644 index 01552e4490..0000000000 --- a/dom/webidl/MediaKeySystemAccess.webidl +++ /dev/null @@ -1,41 +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", - "not-allowed" -}; - -dictionary MediaKeySystemMediaCapability { - DOMString contentType = ""; - DOMString robustness = ""; -}; - -dictionary MediaKeySystemConfiguration { - DOMString label = ""; - sequence<DOMString> initDataTypes = []; - sequence<MediaKeySystemMediaCapability> audioCapabilities = []; - sequence<MediaKeySystemMediaCapability> videoCapabilities = []; - MediaKeysRequirement distinctiveIdentifier = "optional"; - MediaKeysRequirement persistentState = "optional"; - sequence<DOMString> sessionTypes; -}; - -[Pref="media.eme.apiVisible"] -interface MediaKeySystemAccess { - readonly attribute DOMString keySystem; - [NewObject] - MediaKeySystemConfiguration getConfiguration(); - [NewObject] - Promise<MediaKeys> createMediaKeys(); -}; diff --git a/dom/webidl/MediaKeys.webidl b/dom/webidl/MediaKeys.webidl deleted file mode 100644 index cb84cdab6d..0000000000 --- a/dom/webidl/MediaKeys.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. - */ - -// Note: "persistent-usage-record" session type is unsupported yet, as -// it's marked as "at risk" in the spec, and Chrome doesn't support it. -enum MediaKeySessionType { - "temporary", - "persistent-license", - // persistent-usage-record, -}; - -[Pref="media.eme.apiVisible"] -interface MediaKeys { - readonly attribute DOMString keySystem; - - [NewObject, Throws] - MediaKeySession createSession(optional MediaKeySessionType sessionType = "temporary"); - - [NewObject] - Promise<void> setServerCertificate((ArrayBufferView or ArrayBuffer) serverCertificate); -}; diff --git a/dom/webidl/MediaKeysRequestStatus.webidl b/dom/webidl/MediaKeysRequestStatus.webidl deleted file mode 100644 index 737372f664..0000000000 --- a/dom/webidl/MediaKeysRequestStatus.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/. - */ - -enum MediaKeySystemStatus { - "available", - "api-disabled", - "cdm-disabled", - "cdm-not-supported", - "cdm-not-installed", - "cdm-created", -}; - -/* Note: This dictionary and enum is only used by Gecko to convey messages - * to chrome JS code. It is not exposed to the web. - */ - -dictionary RequestMediaKeySystemAccessNotification { - required DOMString keySystem; - required MediaKeySystemStatus status; -}; diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl index 5f2ac63e1e..c91d262c0c 100644 --- a/dom/webidl/Navigator.webidl +++ b/dom/webidl/Navigator.webidl @@ -304,15 +304,6 @@ partial interface Navigator { readonly attribute LegacyMozTCPSocket mozTCPSocket; }; -#ifdef MOZ_EME -partial interface Navigator { - [Pref="media.eme.apiVisible", NewObject] - Promise<MediaKeySystemAccess> - requestMediaKeySystemAccess(DOMString keySystem, - sequence<MediaKeySystemConfiguration> supportedConfigurations); -}; -#endif - [NoInterfaceObject, Exposed=(Window,Worker)] interface NavigatorConcurrentHardware { readonly attribute unsigned long long hardwareConcurrency; diff --git a/dom/webidl/WidevineCDMManifest.webidl b/dom/webidl/WidevineCDMManifest.webidl deleted file mode 100644 index 83e14e0b0b..0000000000 --- a/dom/webidl/WidevineCDMManifest.webidl +++ /dev/null @@ -1,15 +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/.
- */
-
-dictionary WidevineCDMManifest {
- required DOMString name;
- required DOMString description;
- required DOMString version;
- required DOMString x-cdm-module-versions;
- required DOMString x-cdm-interface-versions;
- required DOMString x-cdm-host-versions;
- required DOMString x-cdm-codecs;
-};
diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 1cefdacabb..dfcc11182b 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -572,19 +572,6 @@ WEBIDL_FILES = [ 'XULElement.webidl', ] -if CONFIG['MOZ_EME']: - WEBIDL_FILES += [ - 'MediaEncryptedEvent.webidl', - 'MediaKeyError.webidl', - 'MediaKeyMessageEvent.webidl', - 'MediaKeys.webidl', - 'MediaKeySession.webidl', - 'MediaKeysRequestStatus.webidl', - 'MediaKeyStatusMap.webidl', - 'MediaKeySystemAccess.webidl', - 'WidevineCDMManifest.webidl', - ] - if CONFIG['MOZ_AUDIO_CHANNEL_MANAGER']: WEBIDL_FILES += [ 'AudioChannelManager.webidl', diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index b770e69fcb..f1a890aa45 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -7278,12 +7278,6 @@ nsLayoutUtils::SurfaceFromElement(HTMLVideoElement* aElement, (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 || diff --git a/media/gmp-clearkey/0.1/AnnexB.cpp b/media/gmp-clearkey/0.1/AnnexB.cpp deleted file mode 100644 index 952936deb2..0000000000 --- a/media/gmp-clearkey/0.1/AnnexB.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "AnnexB.h" -#include "BigEndian.h" - -#include <cstring> - -using mozilla::BigEndian; - -static const uint8_t kAnnexBDelimiter[] = { 0, 0, 0, 1 }; - -/* static */ void -AnnexB::ConvertFrameInPlace(std::vector<uint8_t>& aBuffer) -{ - for (size_t i = 0; i < aBuffer.size() - 4 - sizeof(kAnnexBDelimiter) + 1; ) { - uint32_t nalLen = BigEndian::readUint32(&aBuffer[i]); - memcpy(&aBuffer[i], kAnnexBDelimiter, sizeof(kAnnexBDelimiter)); - i += nalLen + 4; - } -} - -static void -ConvertParamSetToAnnexB(std::vector<uint8_t>::const_iterator& aIter, - size_t aCount, - std::vector<uint8_t>& aOutAnnexB) -{ - for (size_t i = 0; i < aCount; i++) { - aOutAnnexB.insert(aOutAnnexB.end(), kAnnexBDelimiter, - kAnnexBDelimiter + sizeof(kAnnexBDelimiter)); - - uint16_t len = BigEndian::readUint16(&*aIter); aIter += 2; - aOutAnnexB.insert(aOutAnnexB.end(), aIter, aIter + len); aIter += len; - } -} - -/* static */ void -AnnexB::ConvertConfig(const std::vector<uint8_t>& aBuffer, - std::vector<uint8_t>& aOutAnnexB) -{ - // Skip past irrelevant headers - auto it = aBuffer.begin() + 5; - - if (it >= aBuffer.end()) { - return; - } - - size_t count = *(it++) & 31; - - // Check that we have enough bytes for the Annex B conversion - // and the next size field. Bail if not. - if (it + count * 2 >= aBuffer.end()) { - return; - } - - ConvertParamSetToAnnexB(it, count, aOutAnnexB); - - // Check that we have enough bytes for the Annex B conversion. - count = *(it++); - if (it + count * 2 > aBuffer.end()) { - aOutAnnexB.clear(); - return; - } - - ConvertParamSetToAnnexB(it, count, aOutAnnexB); -} diff --git a/media/gmp-clearkey/0.1/AnnexB.h b/media/gmp-clearkey/0.1/AnnexB.h deleted file mode 100644 index 81ca87e0cf..0000000000 --- a/media/gmp-clearkey/0.1/AnnexB.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __AnnexB_h__ -#define __AnnexB_h__ - -#include <cstdint> -#include <vector> - -class AnnexB -{ -public: - static void ConvertFrameInPlace(std::vector<uint8_t>& aBuffer); - - static void ConvertConfig(const std::vector<uint8_t>& aBuffer, - std::vector<uint8_t>& aOutAnnexB); -}; - -#endif // __AnnexB_h__ diff --git a/media/gmp-clearkey/0.1/ArrayUtils.h b/media/gmp-clearkey/0.1/ArrayUtils.h deleted file mode 100644 index c5e17689e7..0000000000 --- a/media/gmp-clearkey/0.1/ArrayUtils.h +++ /dev/null @@ -1,23 +0,0 @@ -/* -* Copyright 2015, Mozilla Foundation and contributors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef __ArrayUtils_h__ -#define __ArrayUtils_h__ - -#define MOZ_ARRAY_LENGTH(array_) \ - (sizeof(array_)/sizeof(array_[0])) - -#endif diff --git a/media/gmp-clearkey/0.1/AudioDecoder.cpp b/media/gmp-clearkey/0.1/AudioDecoder.cpp deleted file mode 100644 index b02e1a8545..0000000000 --- a/media/gmp-clearkey/0.1/AudioDecoder.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <cstdint> -#include <limits> - -#include "AudioDecoder.h" -#include "ClearKeyDecryptionManager.h" -#include "ClearKeyUtils.h" -#include "gmp-task-utils.h" - -using namespace wmf; - -AudioDecoder::AudioDecoder(GMPAudioHost *aHostAPI) - : mHostAPI(aHostAPI) - , mCallback(nullptr) - , mWorkerThread(nullptr) - , mMutex(nullptr) - , mNumInputTasks(0) - , mHasShutdown(false) -{ - // We drop the ref in DecodingComplete(). - AddRef(); -} - -AudioDecoder::~AudioDecoder() -{ - if (mMutex) { - mMutex->Destroy(); - } -} - -void -AudioDecoder::InitDecode(const GMPAudioCodec& aConfig, - GMPAudioDecoderCallback* aCallback) -{ - mCallback = aCallback; - assert(mCallback); - mDecoder = new WMFAACDecoder(); - HRESULT hr = mDecoder->Init(aConfig.mChannelCount, - aConfig.mSamplesPerSecond, - (BYTE*)aConfig.mExtraData, - aConfig.mExtraDataLen); - LOG("[%p] AudioDecoder::InitializeAudioDecoder() hr=0x%x\n", this, hr); - if (FAILED(hr)) { - mCallback->Error(GMPGenericErr); - return; - } - auto err = GetPlatform()->createmutex(&mMutex); - if (GMP_FAILED(err)) { - mCallback->Error(GMPGenericErr); - return; - } -} - -void -AudioDecoder::EnsureWorker() -{ - if (!mWorkerThread) { - GetPlatform()->createthread(&mWorkerThread); - if (!mWorkerThread) { - mCallback->Error(GMPAllocErr); - return; - } - } -} - -void -AudioDecoder::Decode(GMPAudioSamples* aInput) -{ - EnsureWorker(); - { - AutoLock lock(mMutex); - mNumInputTasks++; - } - mWorkerThread->Post(WrapTaskRefCounted(this, - &AudioDecoder::DecodeTask, - aInput)); -} - -void -AudioDecoder::DecodeTask(GMPAudioSamples* aInput) -{ - HRESULT hr; - - { - AutoLock lock(mMutex); - mNumInputTasks--; - assert(mNumInputTasks >= 0); - } - - if (!aInput || !mHostAPI || !mDecoder) { - LOG("Decode job not set up correctly!"); - return; - } - - const uint8_t* inBuffer = aInput->Buffer(); - if (!inBuffer) { - LOG("No buffer for encoded samples!\n"); - return; - } - - const GMPEncryptedBufferMetadata* crypto = aInput->GetDecryptionData(); - std::vector<uint8_t> buffer(inBuffer, inBuffer + aInput->Size()); - if (crypto) { - // Plugin host should have set up its decryptor/key sessions - // before trying to decode! - GMPErr rv = - ClearKeyDecryptionManager::Get()->Decrypt(buffer, CryptoMetaData(crypto)); - - if (GMP_FAILED(rv)) { - CK_LOGE("Failed to decrypt with key id %08x...", *(uint32_t*)crypto->KeyId()); - MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::Error, rv)); - return; - } - } - - hr = mDecoder->Input(&buffer[0], - buffer.size(), - aInput->TimeStamp()); - - // We must delete the input sample! - GetPlatform()->runonmainthread(WrapTask(aInput, &GMPAudioSamples::Destroy)); - - SAMPLE_LOG("AudioDecoder::DecodeTask() Input ret hr=0x%x\n", hr); - if (FAILED(hr)) { - LOG("AudioDecoder::DecodeTask() decode failed ret=0x%x%s\n", - hr, - ((hr == MF_E_NOTACCEPTING) ? " (MF_E_NOTACCEPTING)" : "")); - return; - } - - while (hr == S_OK) { - CComPtr<IMFSample> output; - hr = mDecoder->Output(&output); - SAMPLE_LOG("AudioDecoder::DecodeTask() output ret=0x%x\n", hr); - if (hr == S_OK) { - ReturnOutput(output); - } - if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { - AutoLock lock(mMutex); - if (mNumInputTasks == 0) { - // We have run all input tasks. We *must* notify Gecko so that it will - // send us more data. - MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::InputDataExhausted)); - } - } else if (FAILED(hr)) { - LOG("AudioDecoder::DecodeTask() output failed hr=0x%x\n", hr); - } - } -} - -void -AudioDecoder::ReturnOutput(IMFSample* aSample) -{ - SAMPLE_LOG("[%p] AudioDecoder::ReturnOutput()\n", this); - assert(aSample); - - HRESULT hr; - - GMPAudioSamples* samples = nullptr; - mHostAPI->CreateSamples(kGMPAudioIS16Samples, &samples); - if (!samples) { - LOG("Failed to create i420 frame!\n"); - return; - } - - hr = MFToGMPSample(aSample, samples); - if (FAILED(hr)) { - samples->Destroy(); - LOG("Failed to prepare output sample!"); - return; - } - ENSURE(SUCCEEDED(hr), /*void*/); - - MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::Decoded, samples)); -} - -HRESULT -AudioDecoder::MFToGMPSample(IMFSample* aInput, - GMPAudioSamples* aOutput) -{ - ENSURE(aInput != nullptr, E_POINTER); - ENSURE(aOutput != nullptr, E_POINTER); - - HRESULT hr; - CComPtr<IMFMediaBuffer> mediaBuffer; - - hr = aInput->ConvertToContiguousBuffer(&mediaBuffer); - ENSURE(SUCCEEDED(hr), hr); - - BYTE* data = nullptr; // Note: *data will be owned by the IMFMediaBuffer, we don't need to free it. - DWORD maxLength = 0, currentLength = 0; - hr = mediaBuffer->Lock(&data, &maxLength, ¤tLength); - ENSURE(SUCCEEDED(hr), hr); - - auto err = aOutput->SetBufferSize(currentLength); - ENSURE(GMP_SUCCEEDED(err), E_FAIL); - - memcpy(aOutput->Buffer(), data, currentLength); - - mediaBuffer->Unlock(); - - LONGLONG hns = 0; - hr = aInput->GetSampleTime(&hns); - ENSURE(SUCCEEDED(hr), hr); - aOutput->SetTimeStamp(HNsToUsecs(hns)); - aOutput->SetChannels(mDecoder->Channels()); - aOutput->SetRate(mDecoder->Rate()); - - return S_OK; -} - -void -AudioDecoder::Reset() -{ - if (mDecoder) { - mDecoder->Reset(); - } - if (mCallback) { - mCallback->ResetComplete(); - } -} - -void -AudioDecoder::DrainTask() -{ - mDecoder->Drain(); - - // Return any pending output. - HRESULT hr = S_OK; - while (hr == S_OK) { - CComPtr<IMFSample> output; - hr = mDecoder->Output(&output); - SAMPLE_LOG("AudioDecoder::DrainTask() output ret=0x%x\n", hr); - if (hr == S_OK) { - ReturnOutput(output); - } - } - MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::DrainComplete)); -} - -void -AudioDecoder::Drain() -{ - if (!mDecoder) { - return; - } - EnsureWorker(); - mWorkerThread->Post(WrapTaskRefCounted(this, - &AudioDecoder::DrainTask)); -} - -void -AudioDecoder::DecodingComplete() -{ - if (mWorkerThread) { - mWorkerThread->Join(); - } - mHasShutdown = true; - - // Release the reference we added in the constructor. There may be - // WrapRefCounted tasks that also hold references to us, and keep - // us alive a little longer. - Release(); -} - -void -AudioDecoder::MaybeRunOnMainThread(GMPTask* aTask) -{ - class MaybeRunTask : public GMPTask - { - public: - MaybeRunTask(AudioDecoder* aDecoder, GMPTask* aTask) - : mDecoder(aDecoder), mTask(aTask) - { } - - virtual void Run(void) { - if (mDecoder->HasShutdown()) { - CK_LOGD("Trying to dispatch to main thread after AudioDecoder has shut down"); - return; - } - - mTask->Run(); - } - - virtual void Destroy() - { - mTask->Destroy(); - delete this; - } - - private: - RefPtr<AudioDecoder> mDecoder; - GMPTask* mTask; - }; - - GetPlatform()->runonmainthread(new MaybeRunTask(this, aTask)); -} diff --git a/media/gmp-clearkey/0.1/AudioDecoder.h b/media/gmp-clearkey/0.1/AudioDecoder.h deleted file mode 100644 index 98915bb7a7..0000000000 --- a/media/gmp-clearkey/0.1/AudioDecoder.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __AudioDecoder_h__ -#define __AudioDecoder_h__ - -#include "gmp-audio-decode.h" -#include "gmp-audio-host.h" -#include "gmp-task-utils.h" -#include "WMFAACDecoder.h" -#include "RefCounted.h" - -#include "mfobjects.h" - -class AudioDecoder : public GMPAudioDecoder - , public RefCounted -{ -public: - AudioDecoder(GMPAudioHost *aHostAPI); - - virtual void InitDecode(const GMPAudioCodec& aCodecSettings, - GMPAudioDecoderCallback* aCallback) override; - - virtual void Decode(GMPAudioSamples* aEncodedSamples); - - virtual void Reset() override; - - virtual void Drain() override; - - virtual void DecodingComplete() override; - - bool HasShutdown() { return mHasShutdown; } - -private: - virtual ~AudioDecoder(); - - void EnsureWorker(); - - void DecodeTask(GMPAudioSamples* aEncodedSamples); - void DrainTask(); - - void ReturnOutput(IMFSample* aSample); - - HRESULT MFToGMPSample(IMFSample* aSample, - GMPAudioSamples* aAudioFrame); - - void MaybeRunOnMainThread(GMPTask* aTask); - - GMPAudioHost *mHostAPI; // host-owned, invalid at DecodingComplete - GMPAudioDecoderCallback* mCallback; // host-owned, invalid at DecodingComplete - GMPThread* mWorkerThread; - GMPMutex* mMutex; - wmf::AutoPtr<wmf::WMFAACDecoder> mDecoder; - - int32_t mNumInputTasks; - - bool mHasShutdown; -}; - -#endif // __AudioDecoder_h__ diff --git a/media/gmp-clearkey/0.1/BigEndian.h b/media/gmp-clearkey/0.1/BigEndian.h deleted file mode 100644 index 853cd4a025..0000000000 --- a/media/gmp-clearkey/0.1/BigEndian.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __BigEndian_h__ -#define __BigEndian_h__ - -#include <stdint.h> - -namespace mozilla { - -class BigEndian { -public: - - static uint32_t readUint32(const void* aPtr) { - const uint8_t* p = reinterpret_cast<const uint8_t*>(aPtr); - return uint32_t(p[0]) << 24 | - uint32_t(p[1]) << 16 | - uint32_t(p[2]) << 8 | - uint32_t(p[3]); - } - - static uint16_t readUint16(const void* aPtr) { - const uint8_t* p = reinterpret_cast<const uint8_t*>(aPtr); - return uint32_t(p[0]) << 8 | - uint32_t(p[1]); - } - - static uint64_t readUint64(const void* aPtr) { - const uint8_t* p = reinterpret_cast<const uint8_t*>(aPtr); - return uint64_t(p[0]) << 56 | - uint64_t(p[1]) << 48 | - uint64_t(p[2]) << 40 | - uint64_t(p[3]) << 32 | - uint64_t(p[4]) << 24 | - uint64_t(p[5]) << 16 | - uint64_t(p[6]) << 8 | - uint64_t(p[7]); - } - - static void writeUint64(void* aPtr, uint64_t aValue) { - uint8_t* p = reinterpret_cast<uint8_t*>(aPtr); - p[0] = uint8_t(aValue >> 56) & 0xff; - p[1] = uint8_t(aValue >> 48) & 0xff; - p[2] = uint8_t(aValue >> 40) & 0xff; - p[3] = uint8_t(aValue >> 32) & 0xff; - p[4] = uint8_t(aValue >> 24) & 0xff; - p[5] = uint8_t(aValue >> 16) & 0xff; - p[6] = uint8_t(aValue >> 8) & 0xff; - p[7] = uint8_t(aValue) & 0xff; - } -}; - -} // namespace mozilla - -#endif // __BigEndian_h__ diff --git a/media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.cpp b/media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.cpp deleted file mode 100644 index ed1cac7388..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ClearKeyAsyncShutdown.h" -#include "gmp-task-utils.h" - -ClearKeyAsyncShutdown::ClearKeyAsyncShutdown(GMPAsyncShutdownHost *aHostAPI) - : mHost(aHostAPI) -{ - CK_LOGD("ClearKeyAsyncShutdown::ClearKeyAsyncShutdown"); - AddRef(); -} - -ClearKeyAsyncShutdown::~ClearKeyAsyncShutdown() -{ - CK_LOGD("ClearKeyAsyncShutdown::~ClearKeyAsyncShutdown"); -} - -void ShutdownTask(ClearKeyAsyncShutdown* aSelf, GMPAsyncShutdownHost* aHost) -{ - // Dumb implementation that just immediately reports completion. - // Real GMPs should ensure they are properly shutdown. - CK_LOGD("ClearKeyAsyncShutdown::BeginShutdown calling ShutdownComplete"); - aHost->ShutdownComplete(); - aSelf->Release(); -} - -void ClearKeyAsyncShutdown::BeginShutdown() -{ - CK_LOGD("ClearKeyAsyncShutdown::BeginShutdown dispatching asynchronous shutdown task"); - GetPlatform()->runonmainthread(WrapTaskNM(ShutdownTask, this, mHost)); -} diff --git a/media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.h b/media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.h deleted file mode 100644 index b828aae41d..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeyAsyncShutdown_h__ -#define __ClearKeyAsyncShutdown_h__ - -#include "gmp-api/gmp-async-shutdown.h" -#include "RefCounted.h" - -class ClearKeyAsyncShutdown : public GMPAsyncShutdown - , public RefCounted -{ -public: - explicit ClearKeyAsyncShutdown(GMPAsyncShutdownHost *aHostAPI); - - void BeginShutdown() override; - -private: - virtual ~ClearKeyAsyncShutdown(); - - GMPAsyncShutdownHost* mHost; -}; - -#endif // __ClearKeyAsyncShutdown_h__ diff --git a/media/gmp-clearkey/0.1/ClearKeyBase64.cpp b/media/gmp-clearkey/0.1/ClearKeyBase64.cpp deleted file mode 100644 index c4c530a341..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyBase64.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ClearKeyBase64.h" - -#include <algorithm> - -using namespace std; - -/** -* Take a base64-encoded string, convert (in-place) each character to its -* corresponding value in the [0x00, 0x3f] range, and truncate any padding. -*/ -static bool -Decode6Bit(string& aStr) -{ - for (size_t i = 0; i < aStr.length(); i++) { - if (aStr[i] >= 'A' && aStr[i] <= 'Z') { - aStr[i] -= 'A'; - } - else if (aStr[i] >= 'a' && aStr[i] <= 'z') { - aStr[i] -= 'a' - 26; - } - else if (aStr[i] >= '0' && aStr[i] <= '9') { - aStr[i] -= '0' - 52; - } - else if (aStr[i] == '-' || aStr[i] == '+') { - aStr[i] = 62; - } - else if (aStr[i] == '_' || aStr[i] == '/') { - aStr[i] = 63; - } - else { - // Truncate '=' padding at the end of the aString. - if (aStr[i] != '=') { - aStr.erase(i, string::npos); - return false; - } - aStr[i] = '\0'; - aStr.resize(i); - break; - } - } - - return true; -} - -bool -DecodeBase64(const string& aEncoded, vector<uint8_t>& aOutDecoded) -{ - if (aEncoded.empty()) { - aOutDecoded.clear(); - return true; - } - if (aEncoded.size() == 1) { - // Invalid Base64 encoding. - return false; - } - string encoded = aEncoded; - if (!Decode6Bit(encoded)) { - return false; - } - - // The number of bytes we haven't yet filled in the current byte, mod 8. - int shift = 0; - - aOutDecoded.resize((encoded.size() * 3) / 4); - vector<uint8_t>::iterator out = aOutDecoded.begin(); - for (size_t i = 0; i < encoded.length(); i++) { - if (!shift) { - *out = encoded[i] << 2; - } - else { - *out |= encoded[i] >> (6 - shift); - out++; - if (out == aOutDecoded.end()) { - // Hit last 6bit octed in encoded, which is padding and can be ignored. - break; - } - *out = encoded[i] << (shift + 2); - } - shift = (shift + 2) % 8; - } - - return true; -}
\ No newline at end of file diff --git a/media/gmp-clearkey/0.1/ClearKeyBase64.h b/media/gmp-clearkey/0.1/ClearKeyBase64.h deleted file mode 100644 index c0c928813d..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyBase64.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeyBase64_h__ -#define __ClearKeyBase64_h__ - -#include <vector> -#include <string> -#include <stdint.h> - -// Decodes a base64 encoded string. Returns true on success. -bool -DecodeBase64(const std::string& aEncoded, std::vector<uint8_t>& aOutDecoded); - -#endif diff --git a/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp b/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp deleted file mode 100644 index 87b316563e..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <string.h> -#include <vector> - -#include "ClearKeyDecryptionManager.h" -#include "psshparser/PsshParser.h" -#include "gmp-api/gmp-decryption.h" -#include "mozilla/CheckedInt.h" -#include <assert.h> - -class ClearKeyDecryptor : public RefCounted -{ -public: - ClearKeyDecryptor(); - - void InitKey(const Key& aKey); - bool HasKey() const { return !!mKey.size(); } - - GMPErr Decrypt(uint8_t* aBuffer, uint32_t aBufferSize, - const CryptoMetaData& aMetadata); - - const Key& DecryptionKey() const { return mKey; } - -private: - ~ClearKeyDecryptor(); - - Key mKey; -}; - - -/* static */ ClearKeyDecryptionManager* ClearKeyDecryptionManager::sInstance = nullptr; - -/* static */ ClearKeyDecryptionManager* -ClearKeyDecryptionManager::Get() -{ - if (!sInstance) { - sInstance = new ClearKeyDecryptionManager(); - } - return sInstance; -} - -ClearKeyDecryptionManager::ClearKeyDecryptionManager() -{ - CK_LOGD("ClearKeyDecryptionManager::ClearKeyDecryptionManager"); -} - -ClearKeyDecryptionManager::~ClearKeyDecryptionManager() -{ - CK_LOGD("ClearKeyDecryptionManager::~ClearKeyDecryptionManager"); - - sInstance = nullptr; - - for (auto it = mDecryptors.begin(); it != mDecryptors.end(); it++) { - it->second->Release(); - } - mDecryptors.clear(); -} - -bool -ClearKeyDecryptionManager::HasSeenKeyId(const KeyId& aKeyId) const -{ - CK_LOGD("ClearKeyDecryptionManager::SeenKeyId %s", mDecryptors.find(aKeyId) != mDecryptors.end() ? "t" : "f"); - return mDecryptors.find(aKeyId) != mDecryptors.end(); -} - -bool -ClearKeyDecryptionManager::IsExpectingKeyForKeyId(const KeyId& aKeyId) const -{ - CK_LOGD("ClearKeyDecryptionManager::IsExpectingKeyForId %08x...", *(uint32_t*)&aKeyId[0]); - const auto& decryptor = mDecryptors.find(aKeyId); - return decryptor != mDecryptors.end() && !decryptor->second->HasKey(); -} - -bool -ClearKeyDecryptionManager::HasKeyForKeyId(const KeyId& aKeyId) const -{ - CK_LOGD("ClearKeyDecryptionManager::HasKeyForKeyId"); - const auto& decryptor = mDecryptors.find(aKeyId); - return decryptor != mDecryptors.end() && decryptor->second->HasKey(); -} - -const Key& -ClearKeyDecryptionManager::GetDecryptionKey(const KeyId& aKeyId) -{ - assert(HasKeyForKeyId(aKeyId)); - return mDecryptors[aKeyId]->DecryptionKey(); -} - -void -ClearKeyDecryptionManager::InitKey(KeyId aKeyId, Key aKey) -{ - CK_LOGD("ClearKeyDecryptionManager::InitKey %08x...", *(uint32_t*)&aKeyId[0]); - if (IsExpectingKeyForKeyId(aKeyId)) { - mDecryptors[aKeyId]->InitKey(aKey); - } -} - -void -ClearKeyDecryptionManager::ExpectKeyId(KeyId aKeyId) -{ - CK_LOGD("ClearKeyDecryptionManager::ExpectKeyId %08x...", *(uint32_t*)&aKeyId[0]); - if (!HasSeenKeyId(aKeyId)) { - mDecryptors[aKeyId] = new ClearKeyDecryptor(); - } - mDecryptors[aKeyId]->AddRef(); -} - -void -ClearKeyDecryptionManager::ReleaseKeyId(KeyId aKeyId) -{ - CK_LOGD("ClearKeyDecryptionManager::ReleaseKeyId"); - assert(HasSeenKeyId(aKeyId)); - - ClearKeyDecryptor* decryptor = mDecryptors[aKeyId]; - if (!decryptor->Release()) { - mDecryptors.erase(aKeyId); - } -} - -GMPErr -ClearKeyDecryptionManager::Decrypt(std::vector<uint8_t>& aBuffer, - const CryptoMetaData& aMetadata) -{ - return Decrypt(&aBuffer[0], aBuffer.size(), aMetadata); -} - -GMPErr -ClearKeyDecryptionManager::Decrypt(uint8_t* aBuffer, uint32_t aBufferSize, - const CryptoMetaData& aMetadata) -{ - CK_LOGD("ClearKeyDecryptionManager::Decrypt"); - if (!HasKeyForKeyId(aMetadata.mKeyId)) { - return GMPNoKeyErr; - } - - return mDecryptors[aMetadata.mKeyId]->Decrypt(aBuffer, aBufferSize, aMetadata); -} - -ClearKeyDecryptor::ClearKeyDecryptor() -{ - CK_LOGD("ClearKeyDecryptor ctor"); -} - -ClearKeyDecryptor::~ClearKeyDecryptor() -{ - if (HasKey()) { - CK_LOGD("ClearKeyDecryptor dtor; key = %08x...", *(uint32_t*)&mKey[0]); - } else { - CK_LOGD("ClearKeyDecryptor dtor"); - } -} - -void -ClearKeyDecryptor::InitKey(const Key& aKey) -{ - mKey = aKey; -} - -GMPErr -ClearKeyDecryptor::Decrypt(uint8_t* aBuffer, uint32_t aBufferSize, - const CryptoMetaData& aMetadata) -{ - CK_LOGD("ClearKeyDecryptor::Decrypt"); - // If the sample is split up into multiple encrypted subsamples, we need to - // stitch them into one continuous buffer for decryption. - std::vector<uint8_t> tmp(aBufferSize); - - if (aMetadata.NumSubsamples()) { - // Take all encrypted parts of subsamples and stitch them into one - // continuous encrypted buffer. - static_assert(sizeof(uintptr_t) == sizeof(uint8_t*), - "We need uintptr_t to be exactly the same size as a pointer"); - mozilla::CheckedInt<uintptr_t> data = reinterpret_cast<uintptr_t>(aBuffer); - const uintptr_t endBuffer = - reinterpret_cast<uintptr_t>(aBuffer + aBufferSize); - uint8_t* iter = &tmp[0]; - for (size_t i = 0; i < aMetadata.NumSubsamples(); i++) { - data += aMetadata.mClearBytes[i]; - if (!data.isValid() || data.value() > endBuffer) { - // Trying to read past the end of the buffer! - return GMPCryptoErr; - } - const uint32_t& cipherBytes = aMetadata.mCipherBytes[i]; - mozilla::CheckedInt<uintptr_t> dataAfterCipher = data + cipherBytes; - if (!dataAfterCipher.isValid() || dataAfterCipher.value() > endBuffer) { - // Trying to read past the end of the buffer! - return GMPCryptoErr; - } - - memcpy(iter, reinterpret_cast<uint8_t*>(data.value()), cipherBytes); - - data = dataAfterCipher; - iter += cipherBytes; - } - - tmp.resize((size_t)(iter - &tmp[0])); - } else { - memcpy(&tmp[0], aBuffer, aBufferSize); - } - - assert(aMetadata.mIV.size() == 8 || aMetadata.mIV.size() == 16); - std::vector<uint8_t> iv(aMetadata.mIV); - iv.insert(iv.end(), CENC_KEY_LEN - aMetadata.mIV.size(), 0); - - ClearKeyUtils::DecryptAES(mKey, tmp, iv); - - if (aMetadata.NumSubsamples()) { - // Take the decrypted buffer, split up into subsamples, and insert those - // subsamples back into their original position in the original buffer. - uint8_t* data = aBuffer; - uint8_t* iter = &tmp[0]; - for (size_t i = 0; i < aMetadata.NumSubsamples(); i++) { - data += aMetadata.mClearBytes[i]; - uint32_t cipherBytes = aMetadata.mCipherBytes[i]; - - memcpy(data, iter, cipherBytes); - - data += cipherBytes; - iter += cipherBytes; - } - } else { - memcpy(aBuffer, &tmp[0], aBufferSize); - } - - return GMPNoErr; -} diff --git a/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.h b/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.h deleted file mode 100644 index 7a6c9a5607..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeyDecryptionManager_h__ -#define __ClearKeyDecryptionManager_h__ - -#include <map> - -#include "ClearKeyUtils.h" -#include "RefCounted.h" - -class ClearKeyDecryptor; - -class CryptoMetaData { -public: - CryptoMetaData() {} - - explicit CryptoMetaData(const GMPEncryptedBufferMetadata* aCrypto) - { - Init(aCrypto); - } - - void Init(const GMPEncryptedBufferMetadata* aCrypto) - { - if (!aCrypto) { - assert(!IsValid()); - return; - } - Assign(mKeyId, aCrypto->KeyId(), aCrypto->KeyIdSize()); - Assign(mIV, aCrypto->IV(), aCrypto->IVSize()); - Assign(mClearBytes, aCrypto->ClearBytes(), aCrypto->NumSubsamples()); - Assign(mCipherBytes, aCrypto->CipherBytes(), aCrypto->NumSubsamples()); - } - - bool IsValid() const { - return !mKeyId.empty() && - !mIV.empty() && - !mCipherBytes.empty() && - !mClearBytes.empty(); - } - - size_t NumSubsamples() const { - assert(mClearBytes.size() == mCipherBytes.size()); - return mClearBytes.size(); - } - - std::vector<uint8_t> mKeyId; - std::vector<uint8_t> mIV; - std::vector<uint16_t> mClearBytes; - std::vector<uint32_t> mCipherBytes; -}; - -class ClearKeyDecryptionManager : public RefCounted -{ -private: - ClearKeyDecryptionManager(); - ~ClearKeyDecryptionManager(); - - static ClearKeyDecryptionManager* sInstance; - -public: - static ClearKeyDecryptionManager* Get(); - - bool HasSeenKeyId(const KeyId& aKeyId) const; - bool HasKeyForKeyId(const KeyId& aKeyId) const; - - const Key& GetDecryptionKey(const KeyId& aKeyId); - - // Create a decryptor for the given KeyId if one does not already exist. - void InitKey(KeyId aKeyId, Key aKey); - void ExpectKeyId(KeyId aKeyId); - void ReleaseKeyId(KeyId aKeyId); - - // Decrypts buffer *in place*. - GMPErr Decrypt(uint8_t* aBuffer, uint32_t aBufferSize, - const CryptoMetaData& aMetadata); - GMPErr Decrypt(std::vector<uint8_t>& aBuffer, - const CryptoMetaData& aMetadata); - - void Shutdown(); - -private: - bool IsExpectingKeyForKeyId(const KeyId& aKeyId) const; - - std::map<KeyId, ClearKeyDecryptor*> mDecryptors; -}; - -#endif // __ClearKeyDecryptionManager_h__ diff --git a/media/gmp-clearkey/0.1/ClearKeyPersistence.cpp b/media/gmp-clearkey/0.1/ClearKeyPersistence.cpp deleted file mode 100644 index 2e14d822ee..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyPersistence.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ClearKeyPersistence.h" -#include "ClearKeyUtils.h" -#include "ClearKeyStorage.h" -#include "ClearKeySessionManager.h" -#include "RefCounted.h" - -#include <stdint.h> -#include <string.h> -#include <set> -#include <vector> -#include <sstream> -#include <assert.h> - -using namespace std; - -// Whether we've loaded the persistent session ids from GMPStorage yet. -enum PersistentKeyState { - UNINITIALIZED, - LOADING, - LOADED -}; -static PersistentKeyState sPersistentKeyState = UNINITIALIZED; - -// Set of session Ids of the persistent sessions created or residing in -// storage. -static set<uint32_t> sPersistentSessionIds; - -static vector<GMPTask*> sTasksBlockedOnSessionIdLoad; - -static void -ReadAllRecordsFromIterator(GMPRecordIterator* aRecordIterator, - void* aUserArg, - GMPErr aStatus) -{ - assert(sPersistentKeyState == LOADING); - if (GMP_SUCCEEDED(aStatus)) { - // Extract the record names which are valid uint32_t's; they're - // the persistent session ids. - const char* name = nullptr; - uint32_t len = 0; - while (GMP_SUCCEEDED(aRecordIterator->GetName(&name, &len))) { - if (ClearKeyUtils::IsValidSessionId(name, len)) { - assert(name[len] == 0); - sPersistentSessionIds.insert(atoi(name)); - } - aRecordIterator->NextRecord(); - } - } - sPersistentKeyState = LOADED; - aRecordIterator->Close(); - - for (size_t i = 0; i < sTasksBlockedOnSessionIdLoad.size(); i++) { - sTasksBlockedOnSessionIdLoad[i]->Run(); - sTasksBlockedOnSessionIdLoad[i]->Destroy(); - } - sTasksBlockedOnSessionIdLoad.clear(); -} - -/* static */ void -ClearKeyPersistence::EnsureInitialized() -{ - if (sPersistentKeyState == UNINITIALIZED) { - sPersistentKeyState = LOADING; - if (GMP_FAILED(EnumRecordNames(&ReadAllRecordsFromIterator))) { - sPersistentKeyState = LOADED; - } - } -} - -/* static */ string -ClearKeyPersistence::GetNewSessionId(GMPSessionType aSessionType) -{ - static uint32_t sNextSessionId = 1; - - // Ensure we don't re-use a session id that was persisted. - while (Contains(sPersistentSessionIds, sNextSessionId)) { - sNextSessionId++; - } - - string sessionId; - stringstream ss; - ss << sNextSessionId; - ss >> sessionId; - - if (aSessionType == kGMPPersistentSession) { - sPersistentSessionIds.insert(sNextSessionId); - } - - sNextSessionId++; - - return sessionId; -} - - -class CreateSessionTask : public GMPTask { -public: - CreateSessionTask(ClearKeySessionManager* aTarget, - uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const string& aInitDataType, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType) - : mTarget(aTarget) - , mCreateSessionToken(aCreateSessionToken) - , mPromiseId(aPromiseId) - , mInitDataType(aInitDataType) - , mSessionType(aSessionType) - { - mInitData.insert(mInitData.end(), - aInitData, - aInitData + aInitDataSize); - } - virtual void Run() override { - mTarget->CreateSession(mCreateSessionToken, - mPromiseId, - mInitDataType.c_str(), - mInitDataType.size(), - &mInitData.front(), - mInitData.size(), - mSessionType); - } - virtual void Destroy() override { - delete this; - } -private: - RefPtr<ClearKeySessionManager> mTarget; - uint32_t mCreateSessionToken; - uint32_t mPromiseId; - const string mInitDataType; - vector<uint8_t> mInitData; - GMPSessionType mSessionType; -}; - - -/* static */ bool -ClearKeyPersistence::DeferCreateSessionIfNotReady(ClearKeySessionManager* aInstance, - uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const string& aInitDataType, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType) -{ - if (sPersistentKeyState >= LOADED) { - return false; - } - GMPTask* t = new CreateSessionTask(aInstance, - aCreateSessionToken, - aPromiseId, - aInitDataType, - aInitData, - aInitDataSize, - aSessionType); - sTasksBlockedOnSessionIdLoad.push_back(t); - return true; -} - -class LoadSessionTask : public GMPTask { -public: - LoadSessionTask(ClearKeySessionManager* aTarget, - uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) - : mTarget(aTarget) - , mPromiseId(aPromiseId) - , mSessionId(aSessionId, aSessionId + aSessionIdLength) - { - } - virtual void Run() override { - mTarget->LoadSession(mPromiseId, - mSessionId.c_str(), - mSessionId.size()); - } - virtual void Destroy() override { - delete this; - } -private: - RefPtr<ClearKeySessionManager> mTarget; - uint32_t mPromiseId; - string mSessionId; -}; - -/* static */ bool -ClearKeyPersistence::DeferLoadSessionIfNotReady(ClearKeySessionManager* aInstance, - uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) -{ - if (sPersistentKeyState >= LOADED) { - return false; - } - GMPTask* t = new LoadSessionTask(aInstance, - aPromiseId, - aSessionId, - aSessionIdLength); - sTasksBlockedOnSessionIdLoad.push_back(t); - return true; -} - -/* static */ bool -ClearKeyPersistence::IsPersistentSessionId(const string& aSessionId) -{ - return Contains(sPersistentSessionIds, atoi(aSessionId.c_str())); -} - -class LoadSessionFromKeysTask : public ReadContinuation { -public: - LoadSessionFromKeysTask(ClearKeySessionManager* aTarget, - const string& aSessionId, - uint32_t aPromiseId) - : mTarget(aTarget) - , mSessionId(aSessionId) - , mPromiseId(aPromiseId) - { - } - - virtual void ReadComplete(GMPErr aStatus, - const uint8_t* aData, - uint32_t aLength) override - { - mTarget->PersistentSessionDataLoaded(aStatus, mPromiseId, mSessionId, aData, aLength); - } -private: - RefPtr<ClearKeySessionManager> mTarget; - string mSessionId; - uint32_t mPromiseId; -}; - -/* static */ void -ClearKeyPersistence::LoadSessionData(ClearKeySessionManager* aInstance, - const string& aSid, - uint32_t aPromiseId) -{ - LoadSessionFromKeysTask* loadTask = - new LoadSessionFromKeysTask(aInstance, aSid, aPromiseId); - ReadData(aSid, loadTask); -} - -/* static */ void -ClearKeyPersistence::PersistentSessionRemoved(const string& aSessionId) -{ - sPersistentSessionIds.erase(atoi(aSessionId.c_str())); -} diff --git a/media/gmp-clearkey/0.1/ClearKeyPersistence.h b/media/gmp-clearkey/0.1/ClearKeyPersistence.h deleted file mode 100644 index ddab9f783c..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyPersistence.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeyPersistence_h__ -#define __ClearKeyPersistence_h__ - -#include <string> -#include "gmp-api/gmp-decryption.h" - -class ClearKeySessionManager; - -class ClearKeyPersistence { -public: - static void EnsureInitialized(); - - static std::string GetNewSessionId(GMPSessionType aSessionType); - - static bool DeferCreateSessionIfNotReady(ClearKeySessionManager* aInstance, - uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const std::string& aInitDataType, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType); - - static bool DeferLoadSessionIfNotReady(ClearKeySessionManager* aInstance, - uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength); - - static bool IsPersistentSessionId(const std::string& aSid); - - static void LoadSessionData(ClearKeySessionManager* aInstance, - const std::string& aSid, - uint32_t aPromiseId); - - static void PersistentSessionRemoved(const std::string& aSid); -}; - -#endif // __ClearKeyPersistence_h__ diff --git a/media/gmp-clearkey/0.1/ClearKeySession.cpp b/media/gmp-clearkey/0.1/ClearKeySession.cpp deleted file mode 100644 index fb45dd2ebf..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeySession.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "BigEndian.h" -#include "ClearKeyDecryptionManager.h" -#include "ClearKeySession.h" -#include "ClearKeyUtils.h" -#include "ClearKeyStorage.h" -#include "psshparser/PsshParser.h" -#include "gmp-task-utils.h" -#include "gmp-api/gmp-decryption.h" -#include <assert.h> -#include <string.h> - -using namespace mozilla; - -ClearKeySession::ClearKeySession(const std::string& aSessionId, - GMPDecryptorCallback* aCallback, - GMPSessionType aSessionType) - : mSessionId(aSessionId) - , mCallback(aCallback) - , mSessionType(aSessionType) -{ - CK_LOGD("ClearKeySession ctor %p", this); -} - -ClearKeySession::~ClearKeySession() -{ - CK_LOGD("ClearKeySession dtor %p", this); - - std::vector<GMPMediaKeyInfo> key_infos; - for (const KeyId& keyId : mKeyIds) { - assert(ClearKeyDecryptionManager::Get()->HasSeenKeyId(keyId)); - ClearKeyDecryptionManager::Get()->ReleaseKeyId(keyId); - key_infos.push_back(GMPMediaKeyInfo(&keyId[0], keyId.size(), kGMPUnknown)); - } - mCallback->BatchedKeyStatusChanged(&mSessionId[0], mSessionId.size(), - key_infos.data(), key_infos.size()); -} - -void -ClearKeySession::Init(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const std::string& aInitDataType, - const uint8_t* aInitData, uint32_t aInitDataSize) -{ - CK_LOGD("ClearKeySession::Init"); - - if (aInitDataType == "cenc") { - ParseCENCInitData(aInitData, aInitDataSize, mKeyIds); - } else if (aInitDataType == "keyids") { - ClearKeyUtils::ParseKeyIdsInitData(aInitData, aInitDataSize, mKeyIds); - } else if (aInitDataType == "webm" && aInitDataSize <= kMaxWebmInitDataSize) { - // "webm" initData format is simply the raw bytes of the keyId. - vector<uint8_t> keyId; - keyId.assign(aInitData, aInitData+aInitDataSize); - mKeyIds.push_back(keyId); - } - - if (!mKeyIds.size()) { - const char message[] = "Couldn't parse init data"; - mCallback->RejectPromise(aPromiseId, kGMPTypeError, message, strlen(message)); - return; - } - - mCallback->SetSessionId(aCreateSessionToken, &mSessionId[0], mSessionId.length()); - - mCallback->ResolvePromise(aPromiseId); -} - -GMPSessionType -ClearKeySession::Type() const -{ - return mSessionType; -} - -void -ClearKeySession::AddKeyId(const KeyId& aKeyId) -{ - mKeyIds.push_back(aKeyId); -} diff --git a/media/gmp-clearkey/0.1/ClearKeySession.h b/media/gmp-clearkey/0.1/ClearKeySession.h deleted file mode 100644 index 2783b2253b..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeySession.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeySession_h__ -#define __ClearKeySession_h__ - -#include "ClearKeyUtils.h" -#include "gmp-api/gmp-decryption.h" - -class GMPBuffer; -class GMPDecryptorCallback; -class GMPDecryptorHost; -class GMPEncryptedBufferMetadata; - -class ClearKeySession -{ -public: - explicit ClearKeySession(const std::string& aSessionId, - GMPDecryptorCallback* aCallback, - GMPSessionType aSessionType); - - ~ClearKeySession(); - - const std::vector<KeyId>& GetKeyIds() const { return mKeyIds; } - - void Init(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const string& aInitDataType, - const uint8_t* aInitData, uint32_t aInitDataSize); - - GMPSessionType Type() const; - - void AddKeyId(const KeyId& aKeyId); - - const std::string& Id() const { return mSessionId; } - -private: - const std::string mSessionId; - std::vector<KeyId> mKeyIds; - - GMPDecryptorCallback* mCallback; - const GMPSessionType mSessionType; -}; - -#endif // __ClearKeySession_h__ diff --git a/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp b/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp deleted file mode 100644 index 4dbb062992..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdint.h> -#include <stdio.h> -#include <string.h> - -#include "ClearKeyDecryptionManager.h" -#include "ClearKeySessionManager.h" -#include "ClearKeyUtils.h" -#include "ClearKeyStorage.h" -#include "ClearKeyPersistence.h" -#include "gmp-task-utils.h" -#include <assert.h> - -using namespace std; - -ClearKeySessionManager::ClearKeySessionManager() - : mDecryptionManager(ClearKeyDecryptionManager::Get()) -{ - CK_LOGD("ClearKeySessionManager ctor %p", this); - AddRef(); - - if (GetPlatform()->createthread(&mThread) != GMPNoErr) { - CK_LOGD("failed to create thread in clearkey cdm"); - mThread = nullptr; - } -} - -ClearKeySessionManager::~ClearKeySessionManager() -{ - CK_LOGD("ClearKeySessionManager dtor %p", this); -} - -void -ClearKeySessionManager::Init(GMPDecryptorCallback* aCallback, - bool aDistinctiveIdentifierAllowed, - bool aPersistentStateAllowed) -{ - CK_LOGD("ClearKeySessionManager::Init"); - mCallback = aCallback; - ClearKeyPersistence::EnsureInitialized(); -} - -void -ClearKeySessionManager::CreateSession(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const char* aInitDataType, - uint32_t aInitDataTypeSize, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType) -{ - CK_LOGD("ClearKeySessionManager::CreateSession type:%s", aInitDataType); - - string initDataType(aInitDataType, aInitDataType + aInitDataTypeSize); - // initDataType must be "cenc", "keyids", or "webm". - if (initDataType != "cenc" && - initDataType != "keyids" && - initDataType != "webm") { - string message = "'" + initDataType + "' is an initDataType unsupported by ClearKey"; - mCallback->RejectPromise(aPromiseId, kGMPNotSupportedError, - message.c_str(), message.size()); - return; - } - - if (ClearKeyPersistence::DeferCreateSessionIfNotReady(this, - aCreateSessionToken, - aPromiseId, - initDataType, - aInitData, - aInitDataSize, - aSessionType)) { - return; - } - - string sessionId = ClearKeyPersistence::GetNewSessionId(aSessionType); - assert(mSessions.find(sessionId) == mSessions.end()); - - ClearKeySession* session = new ClearKeySession(sessionId, mCallback, aSessionType); - session->Init(aCreateSessionToken, aPromiseId, initDataType, aInitData, aInitDataSize); - mSessions[sessionId] = session; - - const vector<KeyId>& sessionKeys = session->GetKeyIds(); - vector<KeyId> neededKeys; - for (auto it = sessionKeys.begin(); it != sessionKeys.end(); it++) { - // Need to request this key ID from the client. We always send a key - // request, whether or not another session has sent a request with the same - // key ID. Otherwise a script can end up waiting for another script to - // respond to the request (which may not necessarily happen). - neededKeys.push_back(*it); - mDecryptionManager->ExpectKeyId(*it); - } - - if (neededKeys.empty()) { - CK_LOGD("No keys needed from client."); - return; - } - - // Send a request for needed key data. - string request; - ClearKeyUtils::MakeKeyRequest(neededKeys, request, aSessionType); - mCallback->SessionMessage(&sessionId[0], sessionId.length(), - kGMPLicenseRequest, - (uint8_t*)&request[0], request.length()); -} - -void -ClearKeySessionManager::LoadSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) -{ - CK_LOGD("ClearKeySessionManager::LoadSession"); - - if (!ClearKeyUtils::IsValidSessionId(aSessionId, aSessionIdLength)) { - mCallback->ResolveLoadSessionPromise(aPromiseId, false); - return; - } - - if (ClearKeyPersistence::DeferLoadSessionIfNotReady(this, - aPromiseId, - aSessionId, - aSessionIdLength)) { - return; - } - - string sid(aSessionId, aSessionId + aSessionIdLength); - if (!ClearKeyPersistence::IsPersistentSessionId(sid)) { - mCallback->ResolveLoadSessionPromise(aPromiseId, false); - return; - } - - // Callsback PersistentSessionDataLoaded with results... - ClearKeyPersistence::LoadSessionData(this, sid, aPromiseId); -} - -void -ClearKeySessionManager::PersistentSessionDataLoaded(GMPErr aStatus, - uint32_t aPromiseId, - const string& aSessionId, - const uint8_t* aKeyData, - uint32_t aKeyDataSize) -{ - CK_LOGD("ClearKeySessionManager::PersistentSessionDataLoaded"); - if (GMP_FAILED(aStatus) || - Contains(mSessions, aSessionId) || - (aKeyDataSize % (2 * CENC_KEY_LEN)) != 0) { - mCallback->ResolveLoadSessionPromise(aPromiseId, false); - return; - } - - ClearKeySession* session = new ClearKeySession(aSessionId, - mCallback, - kGMPPersistentSession); - mSessions[aSessionId] = session; - - uint32_t numKeys = aKeyDataSize / (2 * CENC_KEY_LEN); - - vector<GMPMediaKeyInfo> key_infos; - vector<KeyIdPair> keyPairs; - for (uint32_t i = 0; i < numKeys; i ++) { - const uint8_t* base = aKeyData + 2 * CENC_KEY_LEN * i; - - KeyIdPair keyPair; - - keyPair.mKeyId = KeyId(base, base + CENC_KEY_LEN); - assert(keyPair.mKeyId.size() == CENC_KEY_LEN); - - keyPair.mKey = Key(base + CENC_KEY_LEN, base + 2 * CENC_KEY_LEN); - assert(keyPair.mKey.size() == CENC_KEY_LEN); - - session->AddKeyId(keyPair.mKeyId); - - mDecryptionManager->ExpectKeyId(keyPair.mKeyId); - mDecryptionManager->InitKey(keyPair.mKeyId, keyPair.mKey); - mKeyIds.insert(keyPair.mKey); - - keyPairs.push_back(keyPair); - key_infos.push_back(GMPMediaKeyInfo(&keyPairs[i].mKeyId[0], - keyPairs[i].mKeyId.size(), - kGMPUsable)); - } - mCallback->BatchedKeyStatusChanged(&aSessionId[0], aSessionId.size(), - key_infos.data(), key_infos.size()); - - mCallback->ResolveLoadSessionPromise(aPromiseId, true); -} - -void -ClearKeySessionManager::UpdateSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength, - const uint8_t* aResponse, - uint32_t aResponseSize) -{ - CK_LOGD("ClearKeySessionManager::UpdateSession"); - string sessionId(aSessionId, aSessionId + aSessionIdLength); - - auto itr = mSessions.find(sessionId); - if (itr == mSessions.end() || !(itr->second)) { - CK_LOGW("ClearKey CDM couldn't resolve session ID in UpdateSession."); - mCallback->RejectPromise(aPromiseId, kGMPNotFoundError, nullptr, 0); - return; - } - ClearKeySession* session = itr->second; - - // Verify the size of session response. - if (aResponseSize >= kMaxSessionResponseLength) { - CK_LOGW("Session response size is not within a reasonable size."); - mCallback->RejectPromise(aPromiseId, kGMPTypeError, nullptr, 0); - return; - } - - // Parse the response for any (key ID, key) pairs. - vector<KeyIdPair> keyPairs; - if (!ClearKeyUtils::ParseJWK(aResponse, aResponseSize, keyPairs, session->Type())) { - CK_LOGW("ClearKey CDM failed to parse JSON Web Key."); - mCallback->RejectPromise(aPromiseId, kGMPTypeError, nullptr, 0); - return; - } - - vector<GMPMediaKeyInfo> key_infos; - for (size_t i = 0; i < keyPairs.size(); i++) { - KeyIdPair& keyPair = keyPairs[i]; - mDecryptionManager->InitKey(keyPair.mKeyId, keyPair.mKey); - mKeyIds.insert(keyPair.mKeyId); - key_infos.push_back(GMPMediaKeyInfo(&keyPair.mKeyId[0], - keyPair.mKeyId.size(), - kGMPUsable)); - } - mCallback->BatchedKeyStatusChanged(aSessionId, aSessionIdLength, - key_infos.data(), key_infos.size()); - - if (session->Type() != kGMPPersistentSession) { - mCallback->ResolvePromise(aPromiseId); - return; - } - - // Store the keys on disk. We store a record whose name is the sessionId, - // and simply append each keyId followed by its key. - vector<uint8_t> keydata; - Serialize(session, keydata); - GMPTask* resolve = WrapTask(mCallback, &GMPDecryptorCallback::ResolvePromise, aPromiseId); - static const char* message = "Couldn't store cenc key init data"; - GMPTask* reject = WrapTask(mCallback, - &GMPDecryptorCallback::RejectPromise, - aPromiseId, - kGMPInvalidStateError, - message, - strlen(message)); - StoreData(sessionId, keydata, resolve, reject); -} - -void -ClearKeySessionManager::Serialize(const ClearKeySession* aSession, - std::vector<uint8_t>& aOutKeyData) -{ - const std::vector<KeyId>& keyIds = aSession->GetKeyIds(); - for (size_t i = 0; i < keyIds.size(); i++) { - const KeyId& keyId = keyIds[i]; - if (!mDecryptionManager->HasKeyForKeyId(keyId)) { - continue; - } - assert(keyId.size() == CENC_KEY_LEN); - aOutKeyData.insert(aOutKeyData.end(), keyId.begin(), keyId.end()); - const Key& key = mDecryptionManager->GetDecryptionKey(keyId); - assert(key.size() == CENC_KEY_LEN); - aOutKeyData.insert(aOutKeyData.end(), key.begin(), key.end()); - } -} - -void -ClearKeySessionManager::CloseSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) -{ - CK_LOGD("ClearKeySessionManager::CloseSession"); - - string sessionId(aSessionId, aSessionId + aSessionIdLength); - auto itr = mSessions.find(sessionId); - if (itr == mSessions.end()) { - CK_LOGW("ClearKey CDM couldn't close non-existent session."); - mCallback->RejectPromise(aPromiseId, kGMPNotFoundError, nullptr, 0); - return; - } - - ClearKeySession* session = itr->second; - assert(session); - - ClearInMemorySessionData(session); - mCallback->SessionClosed(aSessionId, aSessionIdLength); - mCallback->ResolvePromise(aPromiseId); -} - -void -ClearKeySessionManager::ClearInMemorySessionData(ClearKeySession* aSession) -{ - mSessions.erase(aSession->Id()); - delete aSession; -} - -void -ClearKeySessionManager::RemoveSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) -{ - CK_LOGD("ClearKeySessionManager::RemoveSession"); - string sessionId(aSessionId, aSessionId + aSessionIdLength); - auto itr = mSessions.find(sessionId); - if (itr == mSessions.end()) { - CK_LOGW("ClearKey CDM couldn't remove non-existent session."); - mCallback->RejectPromise(aPromiseId, kGMPNotFoundError, nullptr, 0); - return; - } - - ClearKeySession* session = itr->second; - assert(session); - string sid = session->Id(); - bool isPersistent = session->Type() == kGMPPersistentSession; - ClearInMemorySessionData(session); - - if (!isPersistent) { - mCallback->ResolvePromise(aPromiseId); - return; - } - - ClearKeyPersistence::PersistentSessionRemoved(sid); - - // Overwrite the record storing the sessionId's key data with a zero - // length record to delete it. - vector<uint8_t> emptyKeydata; - GMPTask* resolve = WrapTask(mCallback, &GMPDecryptorCallback::ResolvePromise, aPromiseId); - static const char* message = "Could not remove session"; - GMPTask* reject = WrapTask(mCallback, - &GMPDecryptorCallback::RejectPromise, - aPromiseId, - kGMPInvalidAccessError, - message, - strlen(message)); - StoreData(sessionId, emptyKeydata, resolve, reject); -} - -void -ClearKeySessionManager::SetServerCertificate(uint32_t aPromiseId, - const uint8_t* aServerCert, - uint32_t aServerCertSize) -{ - // ClearKey CDM doesn't support this method by spec. - CK_LOGD("ClearKeySessionManager::SetServerCertificate"); - mCallback->RejectPromise(aPromiseId, kGMPNotSupportedError, - nullptr /* message */, 0 /* messageLen */); -} - -void -ClearKeySessionManager::Decrypt(GMPBuffer* aBuffer, - GMPEncryptedBufferMetadata* aMetadata) -{ - CK_LOGD("ClearKeySessionManager::Decrypt"); - - if (!mThread) { - CK_LOGW("No decrypt thread"); - mCallback->Decrypted(aBuffer, GMPGenericErr); - return; - } - - mThread->Post(WrapTaskRefCounted(this, - &ClearKeySessionManager::DoDecrypt, - aBuffer, aMetadata)); -} - -void -ClearKeySessionManager::DoDecrypt(GMPBuffer* aBuffer, - GMPEncryptedBufferMetadata* aMetadata) -{ - CK_LOGD("ClearKeySessionManager::DoDecrypt"); - - GMPErr rv = mDecryptionManager->Decrypt(aBuffer->Data(), aBuffer->Size(), - CryptoMetaData(aMetadata)); - CK_LOGD("DeDecrypt finished with code %x\n", rv); - mCallback->Decrypted(aBuffer, rv); -} - -void -ClearKeySessionManager::Shutdown() -{ - CK_LOGD("ClearKeySessionManager::Shutdown %p", this); - - for (auto it = mSessions.begin(); it != mSessions.end(); it++) { - delete it->second; - } - mSessions.clear(); -} - -void -ClearKeySessionManager::DecryptingComplete() -{ - CK_LOGD("ClearKeySessionManager::DecryptingComplete %p", this); - - GMPThread* thread = mThread; - thread->Join(); - - Shutdown(); - mDecryptionManager = nullptr; - Release(); -} diff --git a/media/gmp-clearkey/0.1/ClearKeySessionManager.h b/media/gmp-clearkey/0.1/ClearKeySessionManager.h deleted file mode 100644 index 041b3f0362..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeySessionManager.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeyDecryptor_h__ -#define __ClearKeyDecryptor_h__ - -#include <map> -#include <set> -#include <string> -#include <vector> - -#include "ClearKeyDecryptionManager.h" -#include "ClearKeySession.h" -#include "ClearKeyUtils.h" -#include "gmp-api/gmp-decryption.h" -#include "RefCounted.h" - -class ClearKeySessionManager final : public GMPDecryptor - , public RefCounted -{ -public: - ClearKeySessionManager(); - - virtual void Init(GMPDecryptorCallback* aCallback, - bool aDistinctiveIdentifierAllowed, - bool aPersistentStateAllowed) override; - - virtual void CreateSession(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const char* aInitDataType, - uint32_t aInitDataTypeSize, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType) override; - - virtual void LoadSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) override; - - virtual void UpdateSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength, - const uint8_t* aResponse, - uint32_t aResponseSize) override; - - virtual void CloseSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) override; - - virtual void RemoveSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) override; - - virtual void SetServerCertificate(uint32_t aPromiseId, - const uint8_t* aServerCert, - uint32_t aServerCertSize) override; - - virtual void Decrypt(GMPBuffer* aBuffer, - GMPEncryptedBufferMetadata* aMetadata) override; - - virtual void DecryptingComplete() override; - - void PersistentSessionDataLoaded(GMPErr aStatus, - uint32_t aPromiseId, - const std::string& aSessionId, - const uint8_t* aKeyData, - uint32_t aKeyDataSize); - -private: - ~ClearKeySessionManager(); - - void DoDecrypt(GMPBuffer* aBuffer, GMPEncryptedBufferMetadata* aMetadata); - void Shutdown(); - - void ClearInMemorySessionData(ClearKeySession* aSession); - void Serialize(const ClearKeySession* aSession, std::vector<uint8_t>& aOutKeyData); - - RefPtr<ClearKeyDecryptionManager> mDecryptionManager; - - GMPDecryptorCallback* mCallback; - GMPThread* mThread; - - std::set<KeyId> mKeyIds; - std::map<std::string, ClearKeySession*> mSessions; -}; - -#endif // __ClearKeyDecryptor_h__ diff --git a/media/gmp-clearkey/0.1/ClearKeyStorage.cpp b/media/gmp-clearkey/0.1/ClearKeyStorage.cpp deleted file mode 100644 index 0db51c9b7e..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyStorage.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ClearKeyStorage.h" -#include "ClearKeyUtils.h" - -#include "gmp-task-utils.h" - -#include <assert.h> -#include "ArrayUtils.h" - -#include <vector> - -static GMPErr -RunOnMainThread(GMPTask* aTask) -{ - return GetPlatform()->runonmainthread(aTask); -} - -GMPErr -OpenRecord(const char* aName, - uint32_t aNameLength, - GMPRecord** aOutRecord, - GMPRecordClient* aClient) -{ - return GetPlatform()->createrecord(aName, aNameLength, aOutRecord, aClient); -} - -class WriteRecordClient : public GMPRecordClient { -public: - /* - * This function will take the memory ownership of the parameters and - * delete them when done. - */ - static void Write(const std::string& aRecordName, - const std::vector<uint8_t>& aData, - GMPTask* aOnSuccess, - GMPTask* aOnFailure) { - (new WriteRecordClient(aData, aOnSuccess, aOnFailure))->Do(aRecordName); - } - - virtual void OpenComplete(GMPErr aStatus) override { - if (GMP_FAILED(aStatus) || - GMP_FAILED(mRecord->Write(&mData.front(), mData.size()))) { - Done(mOnFailure, mOnSuccess); - } - } - - virtual void ReadComplete(GMPErr aStatus, - const uint8_t* aData, - uint32_t aDataSize) override { - assert(false); // Should not reach here. - } - - virtual void WriteComplete(GMPErr aStatus) override { - if (GMP_FAILED(aStatus)) { - Done(mOnFailure, mOnSuccess); - } else { - Done(mOnSuccess, mOnFailure); - } - } - -private: - WriteRecordClient(const std::vector<uint8_t>& aData, - GMPTask* aOnSuccess, - GMPTask* aOnFailure) - : mRecord(nullptr) - , mOnSuccess(aOnSuccess) - , mOnFailure(aOnFailure) - , mData(aData) {} - - void Do(const std::string& aName) { - auto err = OpenRecord(aName.c_str(), aName.size(), &mRecord, this); - if (GMP_FAILED(err) || - GMP_FAILED(mRecord->Open())) { - Done(mOnFailure, mOnSuccess); - } - } - - void Done(GMPTask* aToRun, GMPTask* aToDestroy) { - // Note: Call Close() before running continuation, in case the - // continuation tries to open the same record; if we call Close() - // after running the continuation, the Close() call will arrive - // just after the Open() call succeeds, immediately closing the - // record we just opened. - if (mRecord) { - mRecord->Close(); - } - aToDestroy->Destroy(); - RunOnMainThread(aToRun); - delete this; - } - - GMPRecord* mRecord; - GMPTask* mOnSuccess; - GMPTask* mOnFailure; - const std::vector<uint8_t> mData; -}; - -void -StoreData(const std::string& aRecordName, - const std::vector<uint8_t>& aData, - GMPTask* aOnSuccess, - GMPTask* aOnFailure) -{ - WriteRecordClient::Write(aRecordName, aData, aOnSuccess, aOnFailure); -} - -class ReadRecordClient : public GMPRecordClient { -public: - /* - * This function will take the memory ownership of the parameters and - * delete them when done. - */ - static void Read(const std::string& aRecordName, - ReadContinuation* aContinuation) { - assert(aContinuation); - (new ReadRecordClient(aContinuation))->Do(aRecordName); - } - - virtual void OpenComplete(GMPErr aStatus) override { - auto err = aStatus; - if (GMP_FAILED(err) || - GMP_FAILED(err = mRecord->Read())) { - Done(err, nullptr, 0); - } - } - - virtual void ReadComplete(GMPErr aStatus, - const uint8_t* aData, - uint32_t aDataSize) override { - Done(aStatus, aData, aDataSize); - } - - virtual void WriteComplete(GMPErr aStatus) override { - assert(false); // Should not reach here. - } - -private: - explicit ReadRecordClient(ReadContinuation* aContinuation) - : mRecord(nullptr) - , mContinuation(aContinuation) {} - - void Do(const std::string& aName) { - auto err = OpenRecord(aName.c_str(), aName.size(), &mRecord, this); - if (GMP_FAILED(err) || - GMP_FAILED(err = mRecord->Open())) { - Done(err, nullptr, 0); - } - } - - void Done(GMPErr err, const uint8_t* aData, uint32_t aDataSize) { - // Note: Call Close() before running continuation, in case the - // continuation tries to open the same record; if we call Close() - // after running the continuation, the Close() call will arrive - // just after the Open() call succeeds, immediately closing the - // record we just opened. - if (mRecord) { - mRecord->Close(); - } - mContinuation->ReadComplete(err, aData, aDataSize); - delete mContinuation; - delete this; - } - - GMPRecord* mRecord; - ReadContinuation* mContinuation; -}; - -void -ReadData(const std::string& aRecordName, - ReadContinuation* aContinuation) -{ - ReadRecordClient::Read(aRecordName, aContinuation); -} - -GMPErr -EnumRecordNames(RecvGMPRecordIteratorPtr aRecvIteratorFunc) -{ - return GetPlatform()->getrecordenumerator(aRecvIteratorFunc, nullptr); -} diff --git a/media/gmp-clearkey/0.1/ClearKeyStorage.h b/media/gmp-clearkey/0.1/ClearKeyStorage.h deleted file mode 100644 index 695f67d9ea..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyStorage.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeyStorage_h__ -#define __ClearKeyStorage_h__ - -#include "gmp-api/gmp-errors.h" -#include "gmp-api/gmp-platform.h" -#include <string> -#include <vector> -#include <stdint.h> - -class GMPTask; - -// Responsible for ensuring that both aOnSuccess and aOnFailure are destroyed. -void StoreData(const std::string& aRecordName, - const std::vector<uint8_t>& aData, - GMPTask* aOnSuccess, - GMPTask* aOnFailure); - -class ReadContinuation { -public: - virtual void ReadComplete(GMPErr aStatus, - const uint8_t* aData, - uint32_t aLength) = 0; - virtual ~ReadContinuation() {} -}; - -// Deletes aContinuation after running it to report the result. -void ReadData(const std::string& aSessionId, - ReadContinuation* aContinuation); - -GMPErr EnumRecordNames(RecvGMPRecordIteratorPtr aRecvIteratorFunc); - -#endif // __ClearKeyStorage_h__ diff --git a/media/gmp-clearkey/0.1/ClearKeyUtils.cpp b/media/gmp-clearkey/0.1/ClearKeyUtils.cpp deleted file mode 100644 index b99a50a4dc..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyUtils.cpp +++ /dev/null @@ -1,541 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <algorithm> -#include <ctype.h> -#include <stdarg.h> -#include <stdint.h> -#include <vector> - -#include "ClearKeyUtils.h" -#include "ClearKeyBase64.h" -#include "ArrayUtils.h" -#include <assert.h> -#include <memory.h> -#include "BigEndian.h" -#include "openaes/oaes_lib.h" - -using namespace std; - -void -CK_Log(const char* aFmt, ...) -{ - va_list ap; - - va_start(ap, aFmt); - vprintf(aFmt, ap); - va_end(ap); - - printf("\n"); - fflush(stdout); -} - -static void -IncrementIV(vector<uint8_t>& aIV) { - using mozilla::BigEndian; - - assert(aIV.size() == 16); - BigEndian::writeUint64(&aIV[8], BigEndian::readUint64(&aIV[8]) + 1); -} - -/* static */ void -ClearKeyUtils::DecryptAES(const vector<uint8_t>& aKey, - vector<uint8_t>& aData, vector<uint8_t>& aIV) -{ - assert(aIV.size() == CENC_KEY_LEN); - assert(aKey.size() == CENC_KEY_LEN); - - OAES_CTX* aes = oaes_alloc(); - oaes_key_import_data(aes, &aKey[0], aKey.size()); - oaes_set_option(aes, OAES_OPTION_ECB, nullptr); - - for (size_t i = 0; i < aData.size(); i += CENC_KEY_LEN) { - size_t encLen; - oaes_encrypt(aes, &aIV[0], CENC_KEY_LEN, nullptr, &encLen); - - vector<uint8_t> enc(encLen); - oaes_encrypt(aes, &aIV[0], CENC_KEY_LEN, &enc[0], &encLen); - - assert(encLen >= 2 * OAES_BLOCK_SIZE + CENC_KEY_LEN); - size_t blockLen = min(aData.size() - i, CENC_KEY_LEN); - for (size_t j = 0; j < blockLen; j++) { - aData[i + j] ^= enc[2 * OAES_BLOCK_SIZE + j]; - } - IncrementIV(aIV); - } - - oaes_free(&aes); -} - -/** - * ClearKey expects all Key IDs to be base64 encoded with non-standard alphabet - * and padding. - */ -static bool -EncodeBase64Web(vector<uint8_t> aBinary, string& aEncoded) -{ - const char sAlphabet[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - const uint8_t sMask = 0x3f; - - aEncoded.resize((aBinary.size() * 8 + 5) / 6); - - // Pad binary data in case there's rubbish past the last byte. - aBinary.push_back(0); - - // Number of bytes not consumed in the previous character - uint32_t shift = 0; - - auto out = aEncoded.begin(); - auto data = aBinary.begin(); - for (string::size_type i = 0; i < aEncoded.length(); i++) { - if (shift) { - out[i] = (*data << (6 - shift)) & sMask; - data++; - } else { - out[i] = 0; - } - - out[i] += (*data >> (shift + 2)) & sMask; - shift = (shift + 2) % 8; - - // Cast idx to size_t before using it as an array-index, - // to pacify clang 'Wchar-subscripts' warning: - size_t idx = static_cast<size_t>(out[i]); - assert(idx < MOZ_ARRAY_LENGTH(sAlphabet)); // out of bounds index for 'sAlphabet' - out[i] = sAlphabet[idx]; - } - - return true; -} - -/* static */ void -ClearKeyUtils::MakeKeyRequest(const vector<KeyId>& aKeyIDs, - string& aOutRequest, - GMPSessionType aSessionType) -{ - assert(aKeyIDs.size() && aOutRequest.empty()); - - aOutRequest.append("{\"kids\":["); - for (size_t i = 0; i < aKeyIDs.size(); i++) { - if (i) { - aOutRequest.append(","); - } - aOutRequest.append("\""); - - string base64key; - EncodeBase64Web(aKeyIDs[i], base64key); - aOutRequest.append(base64key); - - aOutRequest.append("\""); - } - aOutRequest.append("],\"type\":"); - - aOutRequest.append("\""); - aOutRequest.append(SessionTypeToString(aSessionType)); - aOutRequest.append("\"}"); -} - -#define EXPECT_SYMBOL(CTX, X) do { \ - if (GetNextSymbol(CTX) != (X)) { \ - CK_LOGE("Unexpected symbol in JWK parser"); \ - return false; \ - } \ -} while (false) - -struct ParserContext { - const uint8_t* mIter; - const uint8_t* mEnd; -}; - -static uint8_t -PeekSymbol(ParserContext& aCtx) -{ - for (; aCtx.mIter < aCtx.mEnd; (aCtx.mIter)++) { - if (!isspace(*aCtx.mIter)) { - return *aCtx.mIter; - } - } - - return 0; -} - -static uint8_t -GetNextSymbol(ParserContext& aCtx) -{ - uint8_t sym = PeekSymbol(aCtx); - aCtx.mIter++; - return sym; -} - -static bool SkipToken(ParserContext& aCtx); - -static bool -SkipString(ParserContext& aCtx) -{ - EXPECT_SYMBOL(aCtx, '"'); - for (uint8_t sym = GetNextSymbol(aCtx); sym; sym = GetNextSymbol(aCtx)) { - if (sym == '\\') { - sym = GetNextSymbol(aCtx); - } else if (sym == '"') { - return true; - } - } - - return false; -} - -/** - * Skip whole object and values it contains. - */ -static bool -SkipObject(ParserContext& aCtx) -{ - EXPECT_SYMBOL(aCtx, '{'); - - if (PeekSymbol(aCtx) == '}') { - GetNextSymbol(aCtx); - return true; - } - - while (true) { - if (!SkipString(aCtx)) return false; - EXPECT_SYMBOL(aCtx, ':'); - if (!SkipToken(aCtx)) return false; - - if (PeekSymbol(aCtx) == '}') { - GetNextSymbol(aCtx); - return true; - } - EXPECT_SYMBOL(aCtx, ','); - } - - return false; -} - -/** - * Skip array value and the values it contains. - */ -static bool -SkipArray(ParserContext& aCtx) -{ - EXPECT_SYMBOL(aCtx, '['); - - if (PeekSymbol(aCtx) == ']') { - GetNextSymbol(aCtx); - return true; - } - - while (SkipToken(aCtx)) { - if (PeekSymbol(aCtx) == ']') { - GetNextSymbol(aCtx); - return true; - } - EXPECT_SYMBOL(aCtx, ','); - } - - return false; -} - -/** - * Skip unquoted literals like numbers, |true|, and |null|. - * (XXX and anything else that matches /([:alnum:]|[+-.])+/) - */ -static bool -SkipLiteral(ParserContext& aCtx) -{ - for (; aCtx.mIter < aCtx.mEnd; aCtx.mIter++) { - if (!isalnum(*aCtx.mIter) && - *aCtx.mIter != '.' && *aCtx.mIter != '-' && *aCtx.mIter != '+') { - return true; - } - } - - return false; -} - -static bool -SkipToken(ParserContext& aCtx) -{ - uint8_t startSym = PeekSymbol(aCtx); - if (startSym == '"') { - CK_LOGD("JWK parser skipping string"); - return SkipString(aCtx); - } else if (startSym == '{') { - CK_LOGD("JWK parser skipping object"); - return SkipObject(aCtx); - } else if (startSym == '[') { - CK_LOGD("JWK parser skipping array"); - return SkipArray(aCtx); - } else { - CK_LOGD("JWK parser skipping literal"); - return SkipLiteral(aCtx); - } - - return false; -} - -static bool -GetNextLabel(ParserContext& aCtx, string& aOutLabel) -{ - EXPECT_SYMBOL(aCtx, '"'); - - const uint8_t* start = aCtx.mIter; - for (uint8_t sym = GetNextSymbol(aCtx); sym; sym = GetNextSymbol(aCtx)) { - if (sym == '\\') { - GetNextSymbol(aCtx); - continue; - } - - if (sym == '"') { - aOutLabel.assign(start, aCtx.mIter - 1); - return true; - } - } - - return false; -} - -static bool -ParseKeyObject(ParserContext& aCtx, KeyIdPair& aOutKey) -{ - EXPECT_SYMBOL(aCtx, '{'); - - // Reject empty objects as invalid licenses. - if (PeekSymbol(aCtx) == '}') { - GetNextSymbol(aCtx); - return false; - } - - string keyId; - string key; - - while (true) { - string label; - string value; - - if (!GetNextLabel(aCtx, label)) { - return false; - } - - EXPECT_SYMBOL(aCtx, ':'); - if (label == "kty") { - if (!GetNextLabel(aCtx, value)) return false; - // By spec, type must be "oct". - if (value != "oct") return false; - } else if (label == "k" && PeekSymbol(aCtx) == '"') { - // if this isn't a string we will fall through to the SkipToken() path. - if (!GetNextLabel(aCtx, key)) return false; - } else if (label == "kid" && PeekSymbol(aCtx) == '"') { - if (!GetNextLabel(aCtx, keyId)) return false; - } else { - if (!SkipToken(aCtx)) return false; - } - - uint8_t sym = PeekSymbol(aCtx); - if (!sym || sym == '}') { - break; - } - EXPECT_SYMBOL(aCtx, ','); - } - - return !key.empty() && - !keyId.empty() && - DecodeBase64(keyId, aOutKey.mKeyId) && - DecodeBase64(key, aOutKey.mKey) && - GetNextSymbol(aCtx) == '}'; -} - -static bool -ParseKeys(ParserContext& aCtx, vector<KeyIdPair>& aOutKeys) -{ - // Consume start of array. - EXPECT_SYMBOL(aCtx, '['); - - while (true) { - KeyIdPair key; - if (!ParseKeyObject(aCtx, key)) { - CK_LOGE("Failed to parse key object"); - return false; - } - - assert(!key.mKey.empty() && !key.mKeyId.empty()); - aOutKeys.push_back(key); - - uint8_t sym = PeekSymbol(aCtx); - if (!sym || sym == ']') { - break; - } - - EXPECT_SYMBOL(aCtx, ','); - } - - return GetNextSymbol(aCtx) == ']'; -} - -/* static */ bool -ClearKeyUtils::ParseJWK(const uint8_t* aKeyData, uint32_t aKeyDataSize, - vector<KeyIdPair>& aOutKeys, - GMPSessionType aSessionType) -{ - ParserContext ctx; - ctx.mIter = aKeyData; - ctx.mEnd = aKeyData + aKeyDataSize; - - // Consume '{' from start of object. - EXPECT_SYMBOL(ctx, '{'); - - while (true) { - string label; - // Consume member key. - if (!GetNextLabel(ctx, label)) return false; - EXPECT_SYMBOL(ctx, ':'); - - if (label == "keys") { - // Parse "keys" array. - if (!ParseKeys(ctx, aOutKeys)) return false; - } else if (label == "type") { - // Consume type string. - string type; - if (!GetNextLabel(ctx, type)) return false; - if (type != SessionTypeToString(aSessionType)) { - return false; - } - } else { - SkipToken(ctx); - } - - // Check for end of object. - if (PeekSymbol(ctx) == '}') { - break; - } - - // Consume ',' between object members. - EXPECT_SYMBOL(ctx, ','); - } - - // Consume '}' from end of object. - EXPECT_SYMBOL(ctx, '}'); - - return true; -} - -static bool -ParseKeyIds(ParserContext& aCtx, vector<KeyId>& aOutKeyIds) -{ - // Consume start of array. - EXPECT_SYMBOL(aCtx, '['); - - while (true) { - string label; - vector<uint8_t> keyId; - if (!GetNextLabel(aCtx, label) || !DecodeBase64(label, keyId)) { - return false; - } - if (!keyId.empty() && keyId.size() <= kMaxKeyIdsLength) { - aOutKeyIds.push_back(keyId); - } - - uint8_t sym = PeekSymbol(aCtx); - if (!sym || sym == ']') { - break; - } - - EXPECT_SYMBOL(aCtx, ','); - } - - return GetNextSymbol(aCtx) == ']'; -} - - -/* static */ bool -ClearKeyUtils::ParseKeyIdsInitData(const uint8_t* aInitData, - uint32_t aInitDataSize, - vector<KeyId>& aOutKeyIds) -{ - ParserContext ctx; - ctx.mIter = aInitData; - ctx.mEnd = aInitData + aInitDataSize; - - // Consume '{' from start of object. - EXPECT_SYMBOL(ctx, '{'); - - while (true) { - string label; - // Consume member kids. - if (!GetNextLabel(ctx, label)) return false; - EXPECT_SYMBOL(ctx, ':'); - - if (label == "kids") { - // Parse "kids" array. - if (!ParseKeyIds(ctx, aOutKeyIds) || - aOutKeyIds.empty()) { - return false; - } - } else { - SkipToken(ctx); - } - - // Check for end of object. - if (PeekSymbol(ctx) == '}') { - break; - } - - // Consume ',' between object members. - EXPECT_SYMBOL(ctx, ','); - } - - // Consume '}' from end of object. - EXPECT_SYMBOL(ctx, '}'); - - return true; -} - -/* static */ const char* -ClearKeyUtils::SessionTypeToString(GMPSessionType aSessionType) -{ - switch (aSessionType) { - case kGMPTemporySession: return "temporary"; - case kGMPPersistentSession: return "persistent-license"; - default: { - assert(false); // Should not reach here. - return "invalid"; - } - } -} - -/* static */ bool -ClearKeyUtils::IsValidSessionId(const char* aBuff, uint32_t aLength) -{ - if (aLength > 10) { - // 10 is the max number of characters in UINT32_MAX when - // represented as a string; ClearKey session ids are integers. - return false; - } - for (uint32_t i = 0; i < aLength; i++) { - if (!isdigit(aBuff[i])) { - return false; - } - } - return true; -} - -GMPMutex* GMPCreateMutex() { - GMPMutex* mutex; - auto err = GetPlatform()->createmutex(&mutex); - assert(mutex); - return GMP_FAILED(err) ? nullptr : mutex; -} diff --git a/media/gmp-clearkey/0.1/ClearKeyUtils.h b/media/gmp-clearkey/0.1/ClearKeyUtils.h deleted file mode 100644 index fc29b92119..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyUtils.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeyUtils_h__ -#define __ClearKeyUtils_h__ - -#include <stdint.h> -#include <string> -#include <vector> -#include <assert.h> -#include "gmp-api/gmp-decryption.h" - -#if 0 -void CK_Log(const char* aFmt, ...); -#define CK_LOGE(...) CK_Log(__VA_ARGS__) -#define CK_LOGD(...) CK_Log(__VA_ARGS__) -#define CK_LOGW(...) CK_Log(__VA_ARGS__) -#else -#define CK_LOGE(...) -#define CK_LOGD(...) -#define CK_LOGW(...) -#endif - -struct GMPPlatformAPI; -extern GMPPlatformAPI* GetPlatform(); - -typedef std::vector<uint8_t> KeyId; -typedef std::vector<uint8_t> Key; - -// The session response size should be within a reasonable limit. -// The size 64 KB is referenced from web-platform-test. -static const uint32_t kMaxSessionResponseLength = 65536; - -// Provide limitation for KeyIds length and webm initData size. -static const uint32_t kMaxWebmInitDataSize = 65536; -static const uint32_t kMaxKeyIdsLength = 512; - -struct KeyIdPair -{ - KeyId mKeyId; - Key mKey; -}; - -class ClearKeyUtils -{ -public: - static void DecryptAES(const std::vector<uint8_t>& aKey, - std::vector<uint8_t>& aData, std::vector<uint8_t>& aIV); - - static bool ParseKeyIdsInitData(const uint8_t* aInitData, - uint32_t aInitDataSize, - std::vector<KeyId>& aOutKeyIds); - - static void MakeKeyRequest(const std::vector<KeyId>& aKeyIds, - std::string& aOutRequest, - GMPSessionType aSessionType); - - static bool ParseJWK(const uint8_t* aKeyData, uint32_t aKeyDataSize, - std::vector<KeyIdPair>& aOutKeys, - GMPSessionType aSessionType); - static const char* SessionTypeToString(GMPSessionType aSessionType); - - static bool IsValidSessionId(const char* aBuff, uint32_t aLength); -}; - -template<class Container, class Element> -inline bool -Contains(const Container& aContainer, const Element& aElement) -{ - return aContainer.find(aElement) != aContainer.end(); -} - -class AutoLock { -public: - explicit AutoLock(GMPMutex* aMutex) - : mMutex(aMutex) - { - assert(aMutex); - if (mMutex) { - mMutex->Acquire(); - } - } - ~AutoLock() { - if (mMutex) { - mMutex->Release(); - } - } -private: - GMPMutex* mMutex; -}; - -GMPMutex* GMPCreateMutex(); - -template<typename T> -inline void -Assign(std::vector<T>& aVec, const T* aData, size_t aLength) -{ - aVec.assign(aData, aData + aLength); -} - -#endif // __ClearKeyUtils_h__ diff --git a/media/gmp-clearkey/0.1/RefCounted.h b/media/gmp-clearkey/0.1/RefCounted.h deleted file mode 100644 index 6da6942958..0000000000 --- a/media/gmp-clearkey/0.1/RefCounted.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __RefCount_h__ -#define __RefCount_h__ - -#include <stdint.h> -#include <assert.h> -#include "ClearKeyUtils.h" - -#if defined(_MSC_VER) -#include <atomic> -typedef std::atomic<uint32_t> AtomicRefCount; -#else -class AtomicRefCount { -public: - explicit AtomicRefCount(uint32_t aValue) - : mCount(aValue) - , mMutex(GMPCreateMutex()) - { - assert(mMutex); - } - ~AtomicRefCount() - { - if (mMutex) { - mMutex->Destroy(); - } - } - uint32_t operator--() { - AutoLock lock(mMutex); - return --mCount; - } - uint32_t operator++() { - AutoLock lock(mMutex); - return ++mCount; - } - operator uint32_t() { - AutoLock lock(mMutex); - return mCount; - } -private: - uint32_t mCount; - GMPMutex* mMutex; -}; -#endif - -// Note: Thread safe. -class RefCounted { -public: - void AddRef() { - ++mRefCount; - } - - uint32_t Release() { - uint32_t newCount = --mRefCount; - if (!newCount) { - delete this; - } - return newCount; - } - -protected: - RefCounted() - : mRefCount(0) - { - } - virtual ~RefCounted() - { - assert(!mRefCount); - } - AtomicRefCount mRefCount; -}; - -template<class T> -class RefPtr { -public: - explicit RefPtr(T* aPtr) : mPtr(nullptr) { - Assign(aPtr); - } - ~RefPtr() { - Assign(nullptr); - } - T* operator->() const { return mPtr; } - - RefPtr& operator=(T* aVal) { - Assign(aVal); - return *this; - } - -private: - void Assign(T* aPtr) { - if (mPtr) { - mPtr->Release(); - } - mPtr = aPtr; - if (mPtr) { - aPtr->AddRef(); - } - } - T* mPtr; -}; - -#endif // __RefCount_h__ diff --git a/media/gmp-clearkey/0.1/VideoDecoder.cpp b/media/gmp-clearkey/0.1/VideoDecoder.cpp deleted file mode 100644 index a3f25402b1..0000000000 --- a/media/gmp-clearkey/0.1/VideoDecoder.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <cstdint> -#include <limits> - -#include "AnnexB.h" -#include "BigEndian.h" -#include "ClearKeyDecryptionManager.h" -#include "ClearKeyUtils.h" -#include "gmp-task-utils.h" -#include "VideoDecoder.h" - -using namespace wmf; - -VideoDecoder::VideoDecoder(GMPVideoHost *aHostAPI) - : mHostAPI(aHostAPI) - , mCallback(nullptr) - , mWorkerThread(nullptr) - , mMutex(nullptr) - , mNumInputTasks(0) - , mSentExtraData(false) - , mIsFlushing(false) - , mHasShutdown(false) -{ - // We drop the ref in DecodingComplete(). - AddRef(); -} - -VideoDecoder::~VideoDecoder() -{ - if (mMutex) { - mMutex->Destroy(); - } -} - -void -VideoDecoder::InitDecode(const GMPVideoCodec& aCodecSettings, - const uint8_t* aCodecSpecific, - uint32_t aCodecSpecificLength, - GMPVideoDecoderCallback* aCallback, - int32_t aCoreCount) -{ - mCallback = aCallback; - assert(mCallback); - mDecoder = new WMFH264Decoder(); - HRESULT hr = mDecoder->Init(aCoreCount); - if (FAILED(hr)) { - CK_LOGD("VideoDecoder::InitDecode failed to init WMFH264Decoder"); - mCallback->Error(GMPGenericErr); - return; - } - - auto err = GetPlatform()->createmutex(&mMutex); - if (GMP_FAILED(err)) { - CK_LOGD("VideoDecoder::InitDecode failed to create GMPMutex"); - mCallback->Error(GMPGenericErr); - return; - } - - // The first byte is mPacketizationMode, which is only relevant for - // WebRTC/OpenH264 usecase. - const uint8_t* avcc = aCodecSpecific + 1; - const uint8_t* avccEnd = aCodecSpecific + aCodecSpecificLength; - mExtraData.insert(mExtraData.end(), avcc, avccEnd); - - AnnexB::ConvertConfig(mExtraData, mAnnexB); -} - -void -VideoDecoder::EnsureWorker() -{ - if (!mWorkerThread) { - GetPlatform()->createthread(&mWorkerThread); - if (!mWorkerThread) { - mCallback->Error(GMPAllocErr); - return; - } - } -} - -void -VideoDecoder::Decode(GMPVideoEncodedFrame* aInputFrame, - bool aMissingFrames, - const uint8_t* aCodecSpecificInfo, - uint32_t aCodecSpecificInfoLength, - int64_t aRenderTimeMs) -{ - if (aInputFrame->BufferType() != GMP_BufferLength32) { - // Gecko should only send frames with 4 byte NAL sizes to GMPs. - mCallback->Error(GMPGenericErr); - return; - } - - EnsureWorker(); - - { - AutoLock lock(mMutex); - mNumInputTasks++; - } - - // Note: we don't need the codec specific info on a per-frame basis. - // It's mostly useful for WebRTC use cases. - - // Make a copy of the data, so we can release aInputFrame ASAP, - // to avoid too many shmem handles being held by the GMP process. - // If the GMP process holds on to too many shmem handles, the Gecko - // side can fail to allocate a shmem to send more input. This is - // particularly a problem in Gecko mochitests, which can open multiple - // actors at once which share the same pool of shmems. - DecodeData* data = new DecodeData(); - Assign(data->mBuffer, aInputFrame->Buffer(), aInputFrame->Size()); - data->mTimestamp = aInputFrame->TimeStamp(); - data->mDuration = aInputFrame->Duration(); - data->mIsKeyframe = (aInputFrame->FrameType() == kGMPKeyFrame); - const GMPEncryptedBufferMetadata* crypto = aInputFrame->GetDecryptionData(); - if (crypto) { - data->mCrypto.Init(crypto); - } - aInputFrame->Destroy(); - mWorkerThread->Post(WrapTaskRefCounted(this, - &VideoDecoder::DecodeTask, - data)); -} - -void -VideoDecoder::DecodeTask(DecodeData* aData) -{ - CK_LOGD("VideoDecoder::DecodeTask"); - AutoPtr<DecodeData> d(aData); - HRESULT hr; - - { - AutoLock lock(mMutex); - mNumInputTasks--; - assert(mNumInputTasks >= 0); - } - - if (mIsFlushing) { - CK_LOGD("VideoDecoder::DecodeTask rejecting frame: flushing."); - return; - } - - if (!aData || !mHostAPI || !mDecoder) { - CK_LOGE("Decode job not set up correctly!"); - return; - } - - std::vector<uint8_t>& buffer = aData->mBuffer; - if (aData->mCrypto.IsValid()) { - // Plugin host should have set up its decryptor/key sessions - // before trying to decode! - GMPErr rv = - ClearKeyDecryptionManager::Get()->Decrypt(buffer, aData->mCrypto); - - if (GMP_FAILED(rv)) { - MaybeRunOnMainThread(WrapTask(mCallback, &GMPVideoDecoderCallback::Error, rv)); - return; - } - } - - AnnexB::ConvertFrameInPlace(buffer); - - if (aData->mIsKeyframe) { - // We must send the SPS and PPS to Windows Media Foundation's decoder. - // Note: We do this *after* decryption, otherwise the subsample info - // would be incorrect. - buffer.insert(buffer.begin(), mAnnexB.begin(), mAnnexB.end()); - } - - hr = mDecoder->Input(buffer.data(), - buffer.size(), - aData->mTimestamp, - aData->mDuration); - - CK_LOGD("VideoDecoder::DecodeTask() Input ret hr=0x%x\n", hr); - if (FAILED(hr)) { - CK_LOGE("VideoDecoder::DecodeTask() decode failed ret=0x%x%s\n", - hr, - ((hr == MF_E_NOTACCEPTING) ? " (MF_E_NOTACCEPTING)" : "")); - return; - } - - while (hr == S_OK) { - CComPtr<IMFSample> output; - hr = mDecoder->Output(&output); - CK_LOGD("VideoDecoder::DecodeTask() output ret=0x%x\n", hr); - if (hr == S_OK) { - MaybeRunOnMainThread( - WrapTaskRefCounted(this, - &VideoDecoder::ReturnOutput, - CComPtr<IMFSample>(output), - mDecoder->GetFrameWidth(), - mDecoder->GetFrameHeight(), - mDecoder->GetStride())); - } - if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { - AutoLock lock(mMutex); - if (mNumInputTasks == 0) { - // We have run all input tasks. We *must* notify Gecko so that it will - // send us more data. - MaybeRunOnMainThread( - WrapTask(mCallback, - &GMPVideoDecoderCallback::InputDataExhausted)); - } - } - if (FAILED(hr)) { - CK_LOGE("VideoDecoder::DecodeTask() output failed hr=0x%x\n", hr); - } - } -} - -void -VideoDecoder::ReturnOutput(IMFSample* aSample, - int32_t aWidth, - int32_t aHeight, - int32_t aStride) -{ - CK_LOGD("[%p] VideoDecoder::ReturnOutput()\n", this); - assert(aSample); - - HRESULT hr; - - GMPVideoFrame* f = nullptr; - auto err = mHostAPI->CreateFrame(kGMPI420VideoFrame, &f); - if (GMP_FAILED(err) || !f) { - CK_LOGE("Failed to create i420 frame!\n"); - return; - } - if (HasShutdown()) { - // Note: GMPVideoHost::CreateFrame() can process messages before returning, - // including a message that calls VideoDecoder::DecodingComplete(), i.e. - // we can shutdown during the call! - CK_LOGD("Shutdown while waiting on GMPVideoHost::CreateFrame()!\n"); - f->Destroy(); - return; - } - - auto vf = static_cast<GMPVideoi420Frame*>(f); - - hr = SampleToVideoFrame(aSample, aWidth, aHeight, aStride, vf); - ENSURE(SUCCEEDED(hr), /*void*/); - - mCallback->Decoded(vf); -} - -HRESULT -VideoDecoder::SampleToVideoFrame(IMFSample* aSample, - int32_t aWidth, - int32_t aHeight, - int32_t aStride, - GMPVideoi420Frame* aVideoFrame) -{ - ENSURE(aSample != nullptr, E_POINTER); - ENSURE(aVideoFrame != nullptr, E_POINTER); - - HRESULT hr; - CComPtr<IMFMediaBuffer> mediaBuffer; - - // Must convert to contiguous mediaBuffer to use IMD2DBuffer interface. - hr = aSample->ConvertToContiguousBuffer(&mediaBuffer); - ENSURE(SUCCEEDED(hr), hr); - - // Try and use the IMF2DBuffer interface if available, otherwise fallback - // to the IMFMediaBuffer interface. Apparently IMF2DBuffer is more efficient, - // but only some systems (Windows 8?) support it. - BYTE* data = nullptr; - LONG stride = 0; - CComPtr<IMF2DBuffer> twoDBuffer; - hr = mediaBuffer->QueryInterface(static_cast<IMF2DBuffer**>(&twoDBuffer)); - if (SUCCEEDED(hr)) { - hr = twoDBuffer->Lock2D(&data, &stride); - ENSURE(SUCCEEDED(hr), hr); - } else { - hr = mediaBuffer->Lock(&data, NULL, NULL); - ENSURE(SUCCEEDED(hr), hr); - stride = aStride; - } - - // The V and U planes are stored 16-row-aligned, so we need to add padding - // to the row heights to ensure the Y'CbCr planes are referenced properly. - // YV12, planar format: [YYYY....][VVVV....][UUUU....] - // i.e., Y, then V, then U. - uint32_t padding = 0; - if (aHeight % 16 != 0) { - padding = 16 - (aHeight % 16); - } - int32_t y_size = stride * (aHeight + padding); - int32_t v_size = stride * (aHeight + padding) / 4; - int32_t halfStride = (stride + 1) / 2; - int32_t halfHeight = (aHeight + 1) / 2; - - auto err = aVideoFrame->CreateEmptyFrame(stride, aHeight, stride, halfStride, halfStride); - ENSURE(GMP_SUCCEEDED(err), E_FAIL); - - err = aVideoFrame->SetWidth(aWidth); - ENSURE(GMP_SUCCEEDED(err), E_FAIL); - err = aVideoFrame->SetHeight(aHeight); - ENSURE(GMP_SUCCEEDED(err), E_FAIL); - - uint8_t* outBuffer = aVideoFrame->Buffer(kGMPYPlane); - ENSURE(outBuffer != nullptr, E_FAIL); - assert(aVideoFrame->AllocatedSize(kGMPYPlane) >= stride*aHeight); - memcpy(outBuffer, data, stride*aHeight); - - outBuffer = aVideoFrame->Buffer(kGMPUPlane); - ENSURE(outBuffer != nullptr, E_FAIL); - assert(aVideoFrame->AllocatedSize(kGMPUPlane) >= halfStride*halfHeight); - memcpy(outBuffer, data+y_size, halfStride*halfHeight); - - outBuffer = aVideoFrame->Buffer(kGMPVPlane); - ENSURE(outBuffer != nullptr, E_FAIL); - assert(aVideoFrame->AllocatedSize(kGMPVPlane) >= halfStride*halfHeight); - memcpy(outBuffer, data + y_size + v_size, halfStride*halfHeight); - - if (twoDBuffer) { - twoDBuffer->Unlock2D(); - } else { - mediaBuffer->Unlock(); - } - - LONGLONG hns = 0; - hr = aSample->GetSampleTime(&hns); - ENSURE(SUCCEEDED(hr), hr); - aVideoFrame->SetTimestamp(HNsToUsecs(hns)); - - hr = aSample->GetSampleDuration(&hns); - ENSURE(SUCCEEDED(hr), hr); - aVideoFrame->SetDuration(HNsToUsecs(hns)); - - return S_OK; -} - -void -VideoDecoder::ResetCompleteTask() -{ - mIsFlushing = false; - if (mCallback) { - MaybeRunOnMainThread(WrapTask(mCallback, - &GMPVideoDecoderCallback::ResetComplete)); - } -} - -void -VideoDecoder::Reset() -{ - mIsFlushing = true; - if (mDecoder) { - mDecoder->Reset(); - } - - // Schedule ResetComplete callback to run after existing frames have been - // flushed out of the task queue. - EnsureWorker(); - mWorkerThread->Post(WrapTaskRefCounted(this, - &VideoDecoder::ResetCompleteTask)); -} - -void -VideoDecoder::DrainTask() -{ - mDecoder->Drain(); - - // Return any pending output. - HRESULT hr = S_OK; - while (hr == S_OK) { - CComPtr<IMFSample> output; - hr = mDecoder->Output(&output); - CK_LOGD("VideoDecoder::DrainTask() output ret=0x%x\n", hr); - if (hr == S_OK) { - MaybeRunOnMainThread( - WrapTaskRefCounted(this, - &VideoDecoder::ReturnOutput, - CComPtr<IMFSample>(output), - mDecoder->GetFrameWidth(), - mDecoder->GetFrameHeight(), - mDecoder->GetStride())); - } - } - MaybeRunOnMainThread(WrapTask(mCallback, &GMPVideoDecoderCallback::DrainComplete)); -} - -void -VideoDecoder::Drain() -{ - if (!mDecoder) { - if (mCallback) { - mCallback->DrainComplete(); - } - return; - } - EnsureWorker(); - mWorkerThread->Post(WrapTaskRefCounted(this, - &VideoDecoder::DrainTask)); -} - -void -VideoDecoder::DecodingComplete() -{ - if (mWorkerThread) { - mWorkerThread->Join(); - } - mHasShutdown = true; - - // Release the reference we added in the constructor. There may be - // WrapRefCounted tasks that also hold references to us, and keep - // us alive a little longer. - Release(); -} - -void -VideoDecoder::MaybeRunOnMainThread(GMPTask* aTask) -{ - class MaybeRunTask : public GMPTask - { - public: - MaybeRunTask(VideoDecoder* aDecoder, GMPTask* aTask) - : mDecoder(aDecoder), mTask(aTask) - { } - - virtual void Run(void) { - if (mDecoder->HasShutdown()) { - CK_LOGD("Trying to dispatch to main thread after VideoDecoder has shut down"); - return; - } - - mTask->Run(); - } - - virtual void Destroy() - { - mTask->Destroy(); - delete this; - } - - private: - RefPtr<VideoDecoder> mDecoder; - GMPTask* mTask; - }; - - GetPlatform()->runonmainthread(new MaybeRunTask(this, aTask)); -} diff --git a/media/gmp-clearkey/0.1/VideoDecoder.h b/media/gmp-clearkey/0.1/VideoDecoder.h deleted file mode 100644 index cf021efd73..0000000000 --- a/media/gmp-clearkey/0.1/VideoDecoder.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __VideoDecoder_h__ -#define __VideoDecoder_h__ - -#include <atomic> - -#include "gmp-task-utils.h" -#include "gmp-video-decode.h" -#include "gmp-video-host.h" -#include "WMFH264Decoder.h" - -#include "mfobjects.h" - -class VideoDecoder : public GMPVideoDecoder - , public RefCounted -{ -public: - VideoDecoder(GMPVideoHost *aHostAPI); - - virtual void InitDecode(const GMPVideoCodec& aCodecSettings, - const uint8_t* aCodecSpecific, - uint32_t aCodecSpecificLength, - GMPVideoDecoderCallback* aCallback, - int32_t aCoreCount) override; - - virtual void Decode(GMPVideoEncodedFrame* aInputFrame, - bool aMissingFrames, - const uint8_t* aCodecSpecific, - uint32_t aCodecSpecificLength, - int64_t aRenderTimeMs = -1); - - virtual void Reset() override; - - virtual void Drain() override; - - virtual void DecodingComplete() override; - - bool HasShutdown() { return mHasShutdown; } - -private: - - virtual ~VideoDecoder(); - - void EnsureWorker(); - - void DrainTask(); - - struct DecodeData { - DecodeData() - : mTimestamp(0) - , mDuration(0) - , mIsKeyframe(false) - {} - std::vector<uint8_t> mBuffer; - uint64_t mTimestamp; - uint64_t mDuration; - bool mIsKeyframe; - CryptoMetaData mCrypto; - }; - - void DecodeTask(DecodeData* aData); - - void ResetCompleteTask(); - - void ReturnOutput(IMFSample* aSample, - int32_t aWidth, - int32_t aHeight, - int32_t aStride); - - HRESULT SampleToVideoFrame(IMFSample* aSample, - int32_t aWidth, - int32_t aHeight, - int32_t aStride, - GMPVideoi420Frame* aVideoFrame); - - void MaybeRunOnMainThread(GMPTask* aTask); - - GMPVideoHost *mHostAPI; // host-owned, invalid at DecodingComplete - GMPVideoDecoderCallback* mCallback; // host-owned, invalid at DecodingComplete - GMPThread* mWorkerThread; - GMPMutex* mMutex; - wmf::AutoPtr<wmf::WMFH264Decoder> mDecoder; - - std::vector<uint8_t> mExtraData; - std::vector<uint8_t> mAnnexB; - - int32_t mNumInputTasks; - bool mSentExtraData; - - std::atomic<bool> mIsFlushing; - - bool mHasShutdown; -}; - -#endif // __VideoDecoder_h__ diff --git a/media/gmp-clearkey/0.1/WMFAACDecoder.cpp b/media/gmp-clearkey/0.1/WMFAACDecoder.cpp deleted file mode 100644 index 495f840e8d..0000000000 --- a/media/gmp-clearkey/0.1/WMFAACDecoder.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "WMFAACDecoder.h" -#include <algorithm> -#include <stdint.h> -#include <vector> - -using std::vector; - -namespace wmf { - -WMFAACDecoder::WMFAACDecoder() - : mDecoder(nullptr) - , mChannels(0) - , mRate(0) -{ - memset(&mInputStreamInfo, 0, sizeof(MFT_INPUT_STREAM_INFO)); - memset(&mOutputStreamInfo, 0, sizeof(MFT_OUTPUT_STREAM_INFO)); -} - -WMFAACDecoder::~WMFAACDecoder() -{ - Reset(); -} - -HRESULT -AACAudioSpecificConfigToUserData(BYTE* aAudioSpecConfig, UINT32 aConfigLength, - BYTE** aOutUserData, UINT32* aOutUserDataLength) -{ - // For MFAudioFormat_AAC, MF_MT_USER_DATA - // Contains the portion of the HEAACWAVEINFO structure that appears - // after the WAVEFORMATEX structure (that is, after the wfx member). - // This is followed by the AudioSpecificConfig() data, as defined - // by ISO/IEC 14496-3. - // ... - // The length of the AudioSpecificConfig() data is 2 bytes for AAC-LC - // or HE-AAC with implicit signaling of SBR/PS. It is more than 2 bytes - // for HE-AAC with explicit signaling of SBR/PS. - // - // The value of audioObjectType as defined in AudioSpecificConfig() - // must be 2, indicating AAC-LC. The value of extensionAudioObjectType - // must be 5 for SBR or 29 for PS. - // - // See: - // http://msdn.microsoft.com/en-us/library/windows/desktop/dd742784%28v=vs.85%29.aspx - // - // HEAACWAVEINFO structure: - // typedef struct heaacwaveinfo_tag { - // WAVEFORMATEX wfx; - // WORD wPayloadType; - // WORD wAudioProfileLevelIndication; - // WORD wStructType; - // WORD wReserved1; - // DWORD dwReserved2; - // } - const UINT32 heeInfoLen = 4 * sizeof(WORD) + sizeof(DWORD); - BYTE heeInfo[heeInfoLen] = {0}; - WORD* w = (WORD*)heeInfo; - w[0] = 0x0; // Payload type raw AAC - w[1] = 0; // Profile level unspecified - - const UINT32 len = heeInfoLen + aConfigLength; - BYTE* data = new BYTE[len]; - memcpy(data, heeInfo, heeInfoLen); - memcpy(data+heeInfoLen, aAudioSpecConfig, aConfigLength); - *aOutUserData = data; - *aOutUserDataLength = len; - return S_OK; -} - -HRESULT -WMFAACDecoder::Init(int32_t aChannelCount, - int32_t aSampleRate, - BYTE* aAACAudioSpecificConfig, - UINT32 aAudioConfigLength) -{ - HRESULT hr; - - // AAC decoder is in msauddecmft on Win8, and msmpeg2adec in earlier versions. - hr = CreateMFT(CLSID_CMSAACDecMFT, - WMFDecoderDllNameFor(AAC), - mDecoder); - if (FAILED(hr)) { - hr = CreateMFT(CLSID_CMSAACDecMFT, - WMFDecoderDllNameFor(AAC), - mDecoder); - if (FAILED(hr)) { - LOG("Failed to create AAC decoder\n"); - return E_FAIL; - } - } - - BYTE* userData = nullptr; - UINT32 userDataLength; - hr = AACAudioSpecificConfigToUserData(aAACAudioSpecificConfig, - aAudioConfigLength, - &userData, - &userDataLength); - ENSURE(SUCCEEDED(hr), hr); - hr = SetDecoderInputType(aChannelCount, aSampleRate, userData, userDataLength); - delete userData; - ENSURE(SUCCEEDED(hr), hr); - - hr = SetDecoderOutputType(); - ENSURE(SUCCEEDED(hr), hr); - - hr = SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); - ENSURE(SUCCEEDED(hr), hr); - - hr = SendMFTMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0); - ENSURE(SUCCEEDED(hr), hr); - - hr = mDecoder->GetInputStreamInfo(0, &mInputStreamInfo); - ENSURE(SUCCEEDED(hr), hr); - - hr = mDecoder->GetOutputStreamInfo(0, &mOutputStreamInfo); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFAACDecoder::SetDecoderInputType(int32_t aChannelCount, - int32_t aSampleRate, - BYTE* aUserData, - UINT32 aUserDataLength) -{ - HRESULT hr; - - CComPtr<IMFMediaType> type; - hr = MFCreateMediaType(&type); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_AAC); - ENSURE(SUCCEEDED(hr), hr); - - mRate = aSampleRate; - hr = type->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, mRate); - ENSURE(SUCCEEDED(hr), hr); - - mChannels = aChannelCount; - hr = type->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, mChannels); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->SetBlob(MF_MT_USER_DATA, aUserData, aUserDataLength); - ENSURE(SUCCEEDED(hr), hr); - - hr = mDecoder->SetInputType(0, type, 0); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFAACDecoder::SetDecoderOutputType() -{ - HRESULT hr; - - CComPtr<IMFMediaType> type; - - UINT32 typeIndex = 0; - while (type = nullptr, SUCCEEDED(mDecoder->GetOutputAvailableType(0, typeIndex++, &type))) { - GUID subtype; - hr = type->GetGUID(MF_MT_SUBTYPE, &subtype); - if (FAILED(hr)) { - continue; - } - if (subtype == MFAudioFormat_PCM) { - hr = mDecoder->SetOutputType(0, type, 0); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &mChannels); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &mRate); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; - } - } - - return E_FAIL; -} - -HRESULT -WMFAACDecoder::SendMFTMessage(MFT_MESSAGE_TYPE aMsg, UINT32 aData) -{ - ENSURE(mDecoder != nullptr, E_POINTER); - HRESULT hr = mDecoder->ProcessMessage(aMsg, aData); - ENSURE(SUCCEEDED(hr), hr); - return S_OK; -} - -HRESULT -WMFAACDecoder::CreateInputSample(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp, - IMFSample** aOutSample) -{ - HRESULT hr; - CComPtr<IMFSample> sample = nullptr; - hr = MFCreateSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - CComPtr<IMFMediaBuffer> buffer = nullptr; - int32_t bufferSize = std::max<uint32_t>(uint32_t(mInputStreamInfo.cbSize), aDataSize); - UINT32 alignment = (mInputStreamInfo.cbAlignment > 1) ? mInputStreamInfo.cbAlignment - 1 : 0; - hr = MFCreateAlignedMemoryBuffer(bufferSize, alignment, &buffer); - ENSURE(SUCCEEDED(hr), hr); - - DWORD maxLength = 0; - DWORD currentLength = 0; - BYTE* dst = nullptr; - hr = buffer->Lock(&dst, &maxLength, ¤tLength); - ENSURE(SUCCEEDED(hr), hr); - - // Copy data into sample's buffer. - memcpy(dst, aData, aDataSize); - - hr = buffer->Unlock(); - ENSURE(SUCCEEDED(hr), hr); - - hr = buffer->SetCurrentLength(aDataSize); - ENSURE(SUCCEEDED(hr), hr); - - hr = sample->AddBuffer(buffer); - ENSURE(SUCCEEDED(hr), hr); - - hr = sample->SetSampleTime(UsecsToHNs(aTimestamp)); - ENSURE(SUCCEEDED(hr), hr); - - *aOutSample = sample.Detach(); - - return S_OK; -} - -HRESULT -WMFAACDecoder::CreateOutputSample(IMFSample** aOutSample) -{ - HRESULT hr; - CComPtr<IMFSample> sample = nullptr; - hr = MFCreateSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - CComPtr<IMFMediaBuffer> buffer = nullptr; - int32_t bufferSize = mOutputStreamInfo.cbSize; - UINT32 alignment = (mOutputStreamInfo.cbAlignment > 1) ? mOutputStreamInfo.cbAlignment - 1 : 0; - hr = MFCreateAlignedMemoryBuffer(bufferSize, alignment, &buffer); - ENSURE(SUCCEEDED(hr), hr); - - hr = sample->AddBuffer(buffer); - ENSURE(SUCCEEDED(hr), hr); - - *aOutSample = sample.Detach(); - - return S_OK; -} - - -HRESULT -WMFAACDecoder::GetOutputSample(IMFSample** aOutSample) -{ - HRESULT hr; - // We allocate samples for MFT output. - MFT_OUTPUT_DATA_BUFFER output = {0}; - - CComPtr<IMFSample> sample = nullptr; - hr = CreateOutputSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - output.pSample = sample; - - DWORD status = 0; - hr = mDecoder->ProcessOutput(0, 1, &output, &status); - CComPtr<IMFCollection> events = output.pEvents; // Ensure this is released. - - if (hr == MF_E_TRANSFORM_STREAM_CHANGE) { - // Type change. Probably geometric apperature change. - hr = SetDecoderOutputType(); - ENSURE(SUCCEEDED(hr), hr); - - return GetOutputSample(aOutSample); - } else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT || !sample) { - return MF_E_TRANSFORM_NEED_MORE_INPUT; - } - // Treat other errors as fatal. - ENSURE(SUCCEEDED(hr), hr); - - assert(sample); - - *aOutSample = sample.Detach(); - return S_OK; -} - -HRESULT -WMFAACDecoder::Input(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp) -{ - CComPtr<IMFSample> input = nullptr; - HRESULT hr = CreateInputSample(aData, aDataSize, aTimestamp, &input); - ENSURE(SUCCEEDED(hr) && input!=nullptr, hr); - - hr = mDecoder->ProcessInput(0, input, 0); - if (hr == MF_E_NOTACCEPTING) { - // MFT *already* has enough data to produce a sample. Retrieve it. - LOG("ProcessInput returned MF_E_NOTACCEPTING\n"); - return MF_E_NOTACCEPTING; - } - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFAACDecoder::Output(IMFSample** aOutput) -{ - CComPtr<IMFSample> outputSample = nullptr; - HRESULT hr = GetOutputSample(&outputSample); - if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { - return MF_E_TRANSFORM_NEED_MORE_INPUT; - } - // Treat other errors as fatal. - ENSURE(SUCCEEDED(hr) && outputSample, hr); - - *aOutput = outputSample.Detach(); - - return S_OK; -} - -HRESULT -WMFAACDecoder::Reset() -{ - HRESULT hr = SendMFTMessage(MFT_MESSAGE_COMMAND_FLUSH, 0); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFAACDecoder::Drain() -{ - HRESULT hr = SendMFTMessage(MFT_MESSAGE_COMMAND_DRAIN, 0); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -} diff --git a/media/gmp-clearkey/0.1/WMFAACDecoder.h b/media/gmp-clearkey/0.1/WMFAACDecoder.h deleted file mode 100644 index 3099eeea28..0000000000 --- a/media/gmp-clearkey/0.1/WMFAACDecoder.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if !defined(WMFAACDecoder_h_) -#define WMFAACDecoder_h_ - -#include "WMFUtils.h" - -namespace wmf { - -class WMFAACDecoder { -public: - WMFAACDecoder(); - ~WMFAACDecoder(); - - HRESULT Init(int32_t aChannelCount, - int32_t aSampleRate, - BYTE* aUserData, - UINT32 aUserDataLength); - - HRESULT Input(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp); - - HRESULT Output(IMFSample** aOutput); - - HRESULT Reset(); - - HRESULT Drain(); - - UINT32 Channels() const { return mChannels; } - UINT32 Rate() const { return mRate; } - -private: - - HRESULT GetOutputSample(IMFSample** aOutSample); - HRESULT CreateOutputSample(IMFSample** aOutSample); - HRESULT CreateInputSample(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp, - IMFSample** aOutSample); - - HRESULT SetDecoderInputType(int32_t aChannelCount, - int32_t aSampleRate, - BYTE* aUserData, - UINT32 aUserDataLength); - HRESULT SetDecoderOutputType(); - HRESULT SendMFTMessage(MFT_MESSAGE_TYPE aMsg, UINT32 aData); - - MFT_INPUT_STREAM_INFO mInputStreamInfo; - MFT_OUTPUT_STREAM_INFO mOutputStreamInfo; - - CComPtr<IMFTransform> mDecoder; - - UINT32 mChannels; - UINT32 mRate; -}; - -} - -#endif diff --git a/media/gmp-clearkey/0.1/WMFH264Decoder.cpp b/media/gmp-clearkey/0.1/WMFH264Decoder.cpp deleted file mode 100644 index 8a3ed4fff4..0000000000 --- a/media/gmp-clearkey/0.1/WMFH264Decoder.cpp +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "WMFH264Decoder.h" -#include <algorithm> -#include <codecapi.h> - -namespace wmf { - -WMFH264Decoder::WMFH264Decoder() - : mDecoder(nullptr) -{ - memset(&mInputStreamInfo, 0, sizeof(MFT_INPUT_STREAM_INFO)); - memset(&mOutputStreamInfo, 0, sizeof(MFT_OUTPUT_STREAM_INFO)); -} - -WMFH264Decoder::~WMFH264Decoder() -{ -} - -HRESULT -WMFH264Decoder::Init(int32_t aCoreCount) -{ - HRESULT hr; - - hr = CreateMFT(__uuidof(CMSH264DecoderMFT), - WMFDecoderDllNameFor(H264), - mDecoder); - if (FAILED(hr)) { - // Windows 7 Enterprise Server N (which is what Mozilla's mochitests run - // on) need a different CLSID to instantiate the H.264 decoder. - hr = CreateMFT(CLSID_CMSH264DecMFT, - WMFDecoderDllNameFor(H264), - mDecoder); - } - ENSURE(SUCCEEDED(hr), hr); - - CComPtr<IMFAttributes> attr; - hr = mDecoder->GetAttributes(&attr); - ENSURE(SUCCEEDED(hr), hr); - hr = attr->SetUINT32(CODECAPI_AVDecNumWorkerThreads, - GetNumThreads(aCoreCount)); - ENSURE(SUCCEEDED(hr), hr); - - hr = SetDecoderInputType(); - ENSURE(SUCCEEDED(hr), hr); - - hr = SetDecoderOutputType(); - ENSURE(SUCCEEDED(hr), hr); - - hr = SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); - ENSURE(SUCCEEDED(hr), hr); - - hr = SendMFTMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0); - ENSURE(SUCCEEDED(hr), hr); - - hr = mDecoder->GetInputStreamInfo(0, &mInputStreamInfo); - ENSURE(SUCCEEDED(hr), hr); - - hr = mDecoder->GetOutputStreamInfo(0, &mOutputStreamInfo); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFH264Decoder::ConfigureVideoFrameGeometry(IMFMediaType* aMediaType) -{ - ENSURE(aMediaType != nullptr, E_POINTER); - HRESULT hr; - - IntRect pictureRegion; - hr = wmf::GetPictureRegion(aMediaType, pictureRegion); - ENSURE(SUCCEEDED(hr), hr); - - UINT32 width = 0, height = 0; - hr = MFGetAttributeSize(aMediaType, MF_MT_FRAME_SIZE, &width, &height); - ENSURE(SUCCEEDED(hr), hr); - ENSURE(width <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); - ENSURE(height <= mozilla::MAX_VIDEO_HEIGHT, E_FAIL); - - UINT32 stride = 0; - hr = GetDefaultStride(aMediaType, &stride); - ENSURE(SUCCEEDED(hr), hr); - ENSURE(stride <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); - - // Success! Save state. - mStride = stride; - mVideoWidth = width; - mVideoHeight = height; - mPictureRegion = pictureRegion; - - LOG("WMFH264Decoder frame geometry frame=(%u,%u) stride=%u picture=(%d, %d, %d, %d)\n", - width, height, - mStride, - mPictureRegion.x, mPictureRegion.y, mPictureRegion.width, mPictureRegion.height); - - return S_OK; -} - -int32_t -WMFH264Decoder::GetFrameWidth() const -{ - return mVideoWidth; -} - -int32_t -WMFH264Decoder::GetFrameHeight() const -{ - return mVideoHeight; -} - -const IntRect& -WMFH264Decoder::GetPictureRegion() const -{ - return mPictureRegion; -} - -int32_t -WMFH264Decoder::GetStride() const -{ - return mStride; -} - -HRESULT -WMFH264Decoder::SetDecoderInputType() -{ - HRESULT hr; - - CComPtr<IMFMediaType> type; - hr = MFCreateMediaType(&type); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_MixedInterlaceOrProgressive); - ENSURE(SUCCEEDED(hr), hr); - - hr = mDecoder->SetInputType(0, type, 0); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFH264Decoder::SetDecoderOutputType() -{ - HRESULT hr; - - CComPtr<IMFMediaType> type; - - UINT32 typeIndex = 0; - while (type = nullptr, SUCCEEDED(mDecoder->GetOutputAvailableType(0, typeIndex++, &type))) { - GUID subtype; - hr = type->GetGUID(MF_MT_SUBTYPE, &subtype); - if (FAILED(hr)) { - continue; - } - if (subtype == MFVideoFormat_I420 || subtype == MFVideoFormat_IYUV) { - // On Windows 7 Enterprise N the MFT reports it reports IYUV instead - // of I420. Other Windows' report I420. The formats are the same, so - // support both. - hr = mDecoder->SetOutputType(0, type, 0); - ENSURE(SUCCEEDED(hr), hr); - - hr = ConfigureVideoFrameGeometry(type); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; - } - } - - return E_FAIL; -} - -HRESULT -WMFH264Decoder::SendMFTMessage(MFT_MESSAGE_TYPE aMsg, UINT32 aData) -{ - ENSURE(mDecoder != nullptr, E_POINTER); - HRESULT hr = mDecoder->ProcessMessage(aMsg, aData); - ENSURE(SUCCEEDED(hr), hr); - return S_OK; -} - -HRESULT -WMFH264Decoder::CreateInputSample(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp, - Microseconds aDuration, - IMFSample** aOutSample) -{ - HRESULT hr; - CComPtr<IMFSample> sample; - hr = MFCreateSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - CComPtr<IMFMediaBuffer> buffer; - int32_t bufferSize = std::max<uint32_t>(uint32_t(mInputStreamInfo.cbSize), aDataSize); - UINT32 alignment = (mInputStreamInfo.cbAlignment > 1) ? mInputStreamInfo.cbAlignment - 1 : 0; - hr = MFCreateAlignedMemoryBuffer(bufferSize, alignment, &buffer); - ENSURE(SUCCEEDED(hr), hr); - - DWORD maxLength = 0; - DWORD currentLength = 0; - BYTE* dst = nullptr; - hr = buffer->Lock(&dst, &maxLength, ¤tLength); - ENSURE(SUCCEEDED(hr), hr); - - // Copy data into sample's buffer. - memcpy(dst, aData, aDataSize); - - hr = buffer->Unlock(); - ENSURE(SUCCEEDED(hr), hr); - - hr = buffer->SetCurrentLength(aDataSize); - ENSURE(SUCCEEDED(hr), hr); - - hr = sample->AddBuffer(buffer); - ENSURE(SUCCEEDED(hr), hr); - - hr = sample->SetSampleTime(UsecsToHNs(aTimestamp)); - ENSURE(SUCCEEDED(hr), hr); - - sample->SetSampleDuration(UsecsToHNs(aDuration)); - - *aOutSample = sample.Detach(); - - return S_OK; -} - -HRESULT -WMFH264Decoder::CreateOutputSample(IMFSample** aOutSample) -{ - HRESULT hr; - CComPtr<IMFSample> sample; - hr = MFCreateSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - CComPtr<IMFMediaBuffer> buffer; - int32_t bufferSize = mOutputStreamInfo.cbSize; - UINT32 alignment = (mOutputStreamInfo.cbAlignment > 1) ? mOutputStreamInfo.cbAlignment - 1 : 0; - hr = MFCreateAlignedMemoryBuffer(bufferSize, alignment, &buffer); - ENSURE(SUCCEEDED(hr), hr); - - hr = sample->AddBuffer(buffer); - ENSURE(SUCCEEDED(hr), hr); - - *aOutSample = sample.Detach(); - - return S_OK; -} - - -HRESULT -WMFH264Decoder::GetOutputSample(IMFSample** aOutSample) -{ - HRESULT hr; - // We allocate samples for MFT output. - MFT_OUTPUT_DATA_BUFFER output = {0}; - - CComPtr<IMFSample> sample; - hr = CreateOutputSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - output.pSample = sample; - - DWORD status = 0; - hr = mDecoder->ProcessOutput(0, 1, &output, &status); - //LOG(L"WMFH264Decoder::GetOutputSample() ProcessOutput returned 0x%x\n", hr); - CComPtr<IMFCollection> events = output.pEvents; // Ensure this is released. - - if (hr == MF_E_TRANSFORM_STREAM_CHANGE) { - // Type change. Probably geometric apperature change. - hr = SetDecoderOutputType(); - ENSURE(SUCCEEDED(hr), hr); - - return GetOutputSample(aOutSample); - } else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { - return MF_E_TRANSFORM_NEED_MORE_INPUT; - } - // Treat other errors as fatal. - ENSURE(SUCCEEDED(hr), hr); - - assert(sample); - - // output.pSample - *aOutSample = sample.Detach(); // AddRefs - return S_OK; -} - -HRESULT -WMFH264Decoder::Input(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp, - Microseconds aDuration) -{ - HRESULT hr; - CComPtr<IMFSample> input = nullptr; - hr = CreateInputSample(aData, aDataSize, aTimestamp, aDuration, &input); - ENSURE(SUCCEEDED(hr) && input!=nullptr, hr); - - hr = mDecoder->ProcessInput(0, input, 0); - if (hr == MF_E_NOTACCEPTING) { - // MFT *already* has enough data to produce a sample. Retrieve it. - LOG("ProcessInput returned MF_E_NOTACCEPTING\n"); - return MF_E_NOTACCEPTING; - } - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFH264Decoder::Output(IMFSample** aOutput) -{ - HRESULT hr; - CComPtr<IMFSample> outputSample; - hr = GetOutputSample(&outputSample); - if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { - return MF_E_TRANSFORM_NEED_MORE_INPUT; - } - // Treat other errors as fatal. - ENSURE(SUCCEEDED(hr) && outputSample, hr); - - *aOutput = outputSample.Detach(); - - return S_OK; -} - -HRESULT -WMFH264Decoder::Reset() -{ - HRESULT hr = SendMFTMessage(MFT_MESSAGE_COMMAND_FLUSH, 0); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFH264Decoder::Drain() -{ - HRESULT hr = SendMFTMessage(MFT_MESSAGE_COMMAND_DRAIN, 0); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -} // namespace wmf diff --git a/media/gmp-clearkey/0.1/WMFH264Decoder.h b/media/gmp-clearkey/0.1/WMFH264Decoder.h deleted file mode 100644 index 91b7e046ff..0000000000 --- a/media/gmp-clearkey/0.1/WMFH264Decoder.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if !defined(WMFH264Decoder_h_) -#define WMFH264Decoder_h_ - -#include "WMFUtils.h" - -namespace wmf { - -class WMFH264Decoder { -public: - WMFH264Decoder(); - ~WMFH264Decoder(); - - HRESULT Init(int32_t aCoreCount); - - HRESULT Input(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp, - Microseconds aDuration); - - HRESULT Output(IMFSample** aOutput); - - HRESULT Reset(); - - int32_t GetFrameWidth() const; - int32_t GetFrameHeight() const; - const IntRect& GetPictureRegion() const; - int32_t GetStride() const; - - HRESULT Drain(); - -private: - - HRESULT SetDecoderInputType(); - HRESULT SetDecoderOutputType(); - HRESULT SendMFTMessage(MFT_MESSAGE_TYPE aMsg, UINT32 aData); - - HRESULT CreateInputSample(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp, - Microseconds aDuration, - IMFSample** aOutSample); - - HRESULT CreateOutputSample(IMFSample** aOutSample); - - HRESULT GetOutputSample(IMFSample** aOutSample); - HRESULT ConfigureVideoFrameGeometry(IMFMediaType* aMediaType); - - MFT_INPUT_STREAM_INFO mInputStreamInfo; - MFT_OUTPUT_STREAM_INFO mOutputStreamInfo; - - CComPtr<IMFTransform> mDecoder; - - int32_t mVideoWidth; - int32_t mVideoHeight; - IntRect mPictureRegion; - int32_t mStride; - -}; - -} // namespace wmf - -#endif diff --git a/media/gmp-clearkey/0.1/WMFSymbols.h b/media/gmp-clearkey/0.1/WMFSymbols.h deleted file mode 100644 index 60a0a6854b..0000000000 --- a/media/gmp-clearkey/0.1/WMFSymbols.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -MFPLAT_FUNC(MFCreateSample, "mfplat.dll"); -MFPLAT_FUNC(MFCreateAlignedMemoryBuffer, "mfplat.dll"); -MFPLAT_FUNC(MFGetStrideForBitmapInfoHeader, "evr.dll"); -MFPLAT_FUNC(MFCreateMediaType, "mfplat.dll"); diff --git a/media/gmp-clearkey/0.1/WMFUtils.cpp b/media/gmp-clearkey/0.1/WMFUtils.cpp deleted file mode 100644 index cb3cfe9fc9..0000000000 --- a/media/gmp-clearkey/0.1/WMFUtils.cpp +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "WMFUtils.h" -#include "ClearKeyUtils.h" -#include <versionhelpers.h> - -#include <algorithm> -#include <stdio.h> - -#define INITGUID -#include <guiddef.h> - -#pragma comment(lib, "mfuuid.lib") -#pragma comment(lib, "wmcodecdspuuid") - -void LOG(const char* format, ...) -{ -#ifdef WMF_DECODER_LOG - va_list args; - va_start(args, format); - vprintf(format, args); -#endif -} - -#ifdef WMF_MUST_DEFINE_AAC_MFT_CLSID -// Some SDK versions don't define the AAC decoder CLSID. -// {32D186A7-218F-4C75-8876-DD77273A8999} -DEFINE_GUID(CLSID_CMSAACDecMFT, 0x32D186A7, 0x218F, 0x4C75, 0x88, 0x76, 0xDD, 0x77, 0x27, 0x3A, 0x89, 0x99); -#endif - -DEFINE_GUID(CLSID_CMSH264DecMFT, 0x62CE7E72, 0x4C71, 0x4d20, 0xB1, 0x5D, 0x45, 0x28, 0x31, 0xA8, 0x7D, 0x9D); - -namespace wmf { - - -#define MFPLAT_FUNC(_func, _dllname) \ - decltype(::_func)* _func; -#include "WMFSymbols.h" -#undef MFPLAT_FUNC - -static bool -LinkMfplat() -{ - static bool sInitDone = false; - static bool sInitOk = false; - if (!sInitDone) { - sInitDone = true; - HMODULE handle; - -#define MFPLAT_FUNC(_func, _dllname) \ - handle = GetModuleHandleA(_dllname); \ - if (!(_func = (decltype(_func))(GetProcAddress(handle, #_func)))) { \ - return false; \ - } - -#include "WMFSymbols.h" -#undef MFPLAT_FUNC - sInitOk = true; - } - return sInitOk; -} - -const char* -WMFDecoderDllNameFor(CodecType aCodec) -{ - if (aCodec == H264) { - // For H.264 decoding, we need msmpeg2vdec.dll on Win 7 & 8, - // and mfh264dec.dll on Vista. - if (IsWindows7OrGreater()) { - return "msmpeg2vdec.dll"; - } else { - return "mfh264dec.dll"; - } - } else if (aCodec == AAC) { - // For AAC decoding, we need to use msauddecmft.dll on Win8, - // msmpeg2adec.dll on Win7, and msheaacdec.dll on Vista. - if (IsWindows8OrGreater()) { - return "msauddecmft.dll"; - } else if (IsWindows7OrGreater()) { - return "msmpeg2adec.dll"; - } else { - return "mfheaacdec.dll"; - } - } else { - return ""; - } -} - - -bool -EnsureLibs() -{ - static bool sInitDone = false; - static bool sInitOk = false; - if (!sInitDone) { - sInitOk = LinkMfplat() && - !!GetModuleHandleA(WMFDecoderDllNameFor(AAC)) && - !!GetModuleHandleA(WMFDecoderDllNameFor(H264)); - sInitDone = true; - } - return sInitOk; -} - -int32_t -MFOffsetToInt32(const MFOffset& aOffset) -{ - return int32_t(aOffset.value + (aOffset.fract / 65536.0f)); -} - -// Gets the sub-region of the video frame that should be displayed. -// See: http://msdn.microsoft.com/en-us/library/windows/desktop/bb530115(v=vs.85).aspx -HRESULT -GetPictureRegion(IMFMediaType* aMediaType, IntRect& aOutPictureRegion) -{ - // Determine if "pan and scan" is enabled for this media. If it is, we - // only display a region of the video frame, not the entire frame. - BOOL panScan = MFGetAttributeUINT32(aMediaType, MF_MT_PAN_SCAN_ENABLED, FALSE); - - // If pan and scan mode is enabled. Try to get the display region. - HRESULT hr = E_FAIL; - MFVideoArea videoArea; - memset(&videoArea, 0, sizeof(MFVideoArea)); - if (panScan) { - hr = aMediaType->GetBlob(MF_MT_PAN_SCAN_APERTURE, - (UINT8*)&videoArea, - sizeof(MFVideoArea), - NULL); - } - - // If we're not in pan-and-scan mode, or the pan-and-scan region is not set, - // check for a minimimum display aperture. - if (!panScan || hr == MF_E_ATTRIBUTENOTFOUND) { - hr = aMediaType->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE, - (UINT8*)&videoArea, - sizeof(MFVideoArea), - NULL); - } - - if (hr == MF_E_ATTRIBUTENOTFOUND) { - // Minimum display aperture is not set, for "backward compatibility with - // some components", check for a geometric aperture. - hr = aMediaType->GetBlob(MF_MT_GEOMETRIC_APERTURE, - (UINT8*)&videoArea, - sizeof(MFVideoArea), - NULL); - } - - if (SUCCEEDED(hr)) { - // The media specified a picture region, return it. - IntRect picture = IntRect(MFOffsetToInt32(videoArea.OffsetX), - MFOffsetToInt32(videoArea.OffsetY), - videoArea.Area.cx, - videoArea.Area.cy); - ENSURE(picture.width <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); - ENSURE(picture.height <= mozilla::MAX_VIDEO_HEIGHT, E_FAIL); - aOutPictureRegion = picture; - return S_OK; - } - - // No picture region defined, fall back to using the entire video area. - UINT32 width = 0, height = 0; - hr = MFGetAttributeSize(aMediaType, MF_MT_FRAME_SIZE, &width, &height); - ENSURE(SUCCEEDED(hr), hr); - ENSURE(width <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); - ENSURE(height <= mozilla::MAX_VIDEO_HEIGHT, E_FAIL); - aOutPictureRegion = IntRect(0, 0, width, height); - return S_OK; -} - - -HRESULT -GetDefaultStride(IMFMediaType *aType, uint32_t* aOutStride) -{ - // Try to get the default stride from the media type. - UINT32 stride = 0; - HRESULT hr = aType->GetUINT32(MF_MT_DEFAULT_STRIDE, &stride); - if (SUCCEEDED(hr)) { - ENSURE(stride <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); - *aOutStride = stride; - return S_OK; - } - - // Stride attribute not set, calculate it. - GUID subtype = GUID_NULL; - uint32_t width = 0; - uint32_t height = 0; - - hr = aType->GetGUID(MF_MT_SUBTYPE, &subtype); - ENSURE(SUCCEEDED(hr), hr); - - hr = MFGetAttributeSize(aType, MF_MT_FRAME_SIZE, &width, &height); - ENSURE(SUCCEEDED(hr), hr); - ENSURE(width <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); - ENSURE(height <= mozilla::MAX_VIDEO_HEIGHT, E_FAIL); - - LONG lstride = 0; - hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, width, &lstride); - ENSURE(SUCCEEDED(hr), hr); - ENSURE(lstride <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); - ENSURE(lstride >= 0, E_FAIL); - *aOutStride = lstride; - - return hr; -} - -void dump(const uint8_t* data, uint32_t len, const char* filename) -{ - FILE* f = 0; - fopen_s(&f, filename, "wb"); - fwrite(data, len, 1, f); - fclose(f); -} - -HRESULT -CreateMFT(const CLSID& clsid, - const char* aDllName, - CComPtr<IMFTransform>& aOutMFT) -{ - HMODULE module = ::GetModuleHandleA(aDllName); - if (!module) { - LOG("Failed to get %S\n", aDllName); - return E_FAIL; - } - - typedef HRESULT (WINAPI* DllGetClassObjectFnPtr)(const CLSID& clsid, - const IID& iid, - void** object); - - DllGetClassObjectFnPtr GetClassObjPtr = - reinterpret_cast<DllGetClassObjectFnPtr>(GetProcAddress(module, "DllGetClassObject")); - if (!GetClassObjPtr) { - LOG("Failed to get DllGetClassObject\n"); - return E_FAIL; - } - - CComPtr<IClassFactory> classFactory; - HRESULT hr = GetClassObjPtr(clsid, - __uuidof(IClassFactory), - reinterpret_cast<void**>(static_cast<IClassFactory**>(&classFactory))); - if (FAILED(hr)) { - LOG("Failed to get H264 IClassFactory\n"); - return E_FAIL; - } - - hr = classFactory->CreateInstance(NULL, - __uuidof(IMFTransform), - reinterpret_cast<void**>(static_cast<IMFTransform**>(&aOutMFT))); - if (FAILED(hr)) { - LOG("Failed to get create MFT\n"); - return E_FAIL; - } - - return S_OK; -} - -int32_t -GetNumThreads(int32_t aCoreCount) -{ - return aCoreCount > 4 ? -1 : (std::max)(aCoreCount - 1, 1); -} - -} // namespace diff --git a/media/gmp-clearkey/0.1/WMFUtils.h b/media/gmp-clearkey/0.1/WMFUtils.h deleted file mode 100644 index 51d46d70d4..0000000000 --- a/media/gmp-clearkey/0.1/WMFUtils.h +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __WMFUtils_h__ -#define __WMFUtils_h__ - -#include <cstdint> -#include <string> - -#include <assert.h> -#include <mfapi.h> -#include <mferror.h> -#include <mfobjects.h> -#include <mftransform.h> -#include <wmcodecdsp.h> -#include "VideoLimits.h" - -#include "gmp-platform.h" - -void LOG(const char* format, ...); - -#ifdef LOG_SAMPLE_DECODE -#define SAMPLE_LOG LOG -#else -#define SAMPLE_LOG(...) -#endif - -#ifndef CLSID_CMSAACDecMFT -#define WMF_MUST_DEFINE_AAC_MFT_CLSID -extern "C" const CLSID CLSID_CMSAACDecMFT; -#endif - -extern "C" const CLSID CLSID_CMSH264DecMFT; - -namespace wmf { - -// Reimplementation of CComPtr to reduce dependence on system -// shared libraries. -template<class T> -class CComPtr { -public: - CComPtr(CComPtr&& aOther) : mPtr(aOther.Detach()) { } - CComPtr& operator=(CComPtr&& other) { mPtr = other.Detach(); } - - CComPtr(const CComPtr& aOther) : mPtr(nullptr) { Set(aOther.Get()); } - CComPtr() : mPtr(nullptr) { } - CComPtr(T* const & aPtr) : mPtr(nullptr) { Set(aPtr); } - CComPtr(const std::nullptr_t& aNullPtr) : mPtr(aNullPtr) { } - T** operator&() { return &mPtr; } - T* operator->(){ return mPtr; } - operator T*() { return mPtr; } - T* operator=(T* const & aPtr) { return Set(aPtr); } - T* operator=(const std::nullptr_t& aPtr) { return mPtr = aPtr; } - - T* Get() const { return mPtr; } - - T* Detach() { - T* tmp = mPtr; - mPtr = nullptr; - return tmp; - } - - ~CComPtr() { - if (mPtr) { - mPtr->Release(); - } - mPtr = nullptr; - } - -private: - - T* Set(T* aPtr) { - if (mPtr == aPtr) { - return aPtr; - } - if (mPtr) { - mPtr->Release(); - } - mPtr = aPtr; - if (mPtr) { - mPtr->AddRef(); - } - return mPtr; - } - - T* mPtr; -}; - -class IntRect { -public: - IntRect(int32_t _x, int32_t _y, int32_t _w, int32_t _h) - : x(_x), y(_y), width(_w), height(_h) {} - IntRect() - : x(0), y(0), width(0), height(0) {} - int32_t x; - int32_t y; - int32_t width; - int32_t height; -}; - -typedef int64_t Microseconds; - -#ifdef ENSURE -#undef ENSURE -#endif - -#define ENSURE(condition, ret) \ -{ if (!(condition)) { LOG("##condition## FAILED %S:%d\n", __FILE__, __LINE__); return ret; } } - -#define GMP_SUCCEEDED(x) ((x) == GMPNoErr) -#define GMP_FAILED(x) ((x) != GMPNoErr) - -#define MFPLAT_FUNC(_func, _dllname) \ - extern decltype(::_func)* _func; -#include "WMFSymbols.h" -#undef MFPLAT_FUNC - -bool -EnsureLibs(); - -HRESULT -GetPictureRegion(IMFMediaType* aMediaType, IntRect& aOutPictureRegion); - -HRESULT -GetDefaultStride(IMFMediaType *aType, uint32_t* aOutStride); - -// Converts from microseconds to hundreds of nanoseconds. -// We use microseconds for our timestamps, whereas WMF uses -// hundreds of nanoseconds. -inline int64_t -UsecsToHNs(int64_t aUsecs) { - return aUsecs * 10; -} - -// Converts from hundreds of nanoseconds to microseconds. -// We use microseconds for our timestamps, whereas WMF uses -// hundreds of nanoseconds. -inline int64_t -HNsToUsecs(int64_t hNanoSecs) { - return hNanoSecs / 10; -} - -inline std::string narrow(std::wstring &wide) { - std::string ns(wide.begin(), wide.end()); - return ns; -} - -inline std::wstring widen(std::string &narrow) { - std::wstring ws(narrow.begin(), narrow.end()); - return ws; -} - -#define ARRAY_LENGTH(array_) \ - (sizeof(array_)/sizeof(array_[0])) - -template<class Type> -class AutoPtr { -public: - AutoPtr() - : mPtr(nullptr) - { - } - - AutoPtr(AutoPtr<Type>& aPtr) - : mPtr(aPtr.Forget()) - { - } - - AutoPtr(Type* aPtr) - : mPtr(aPtr) - { - } - - ~AutoPtr() { - if (mPtr) { - delete mPtr; - } - } - - Type* Forget() { - Type* rv = mPtr; - mPtr = nullptr; - return rv; - } - - AutoPtr<Type>& operator=(Type* aOther) { - Assign(aOther); - return *this; - } - - AutoPtr<Type>& operator=(AutoPtr<Type>& aOther) { - Assign(aOther.Forget()); - return *this; - } - - Type* Get() const { - return mPtr; - } - - Type* operator->() const { - assert(mPtr); - return Get(); - } - - operator Type*() const { - return Get(); - } - - Type** Receive() { - return &mPtr; - } -private: - - void Assign(Type* aPtr) { - if (mPtr) { - delete mPtr; - } - mPtr = aPtr; - } - - Type* mPtr; -}; - -// Video frame microseconds are (currently) in 90kHz units, as used by RTP. -// Use this to convert to microseconds... -inline Microseconds RTPTimeToMicroseconds(int64_t rtptime) { - return (rtptime * 1000000) / 90000; -} - -inline uint32_t MicrosecondsToRTPTime(Microseconds us) { - return uint32_t(0xffffffff & (us * 90000) / 1000000); -} - -void dump(const uint8_t* data, uint32_t len, const char* filename); - -HRESULT -CreateMFT(const CLSID& clsid, - const char* aDllName, - CComPtr<IMFTransform>& aOutMFT); - -enum CodecType { - H264, - AAC, -}; - -// Returns the name of the DLL that is needed to decode H.264 or AAC on -// the given windows version we're running on. -const char* WMFDecoderDllNameFor(CodecType aCodec); - -// Returns the maximum number of threads we want WMF to use for decoding -// given the number of logical processors available. -int32_t GetNumThreads(int32_t aCoreCount); - -} // namespace wmf - -#endif // __WMFUtils_h__ diff --git a/media/gmp-clearkey/0.1/clearkey.info.in b/media/gmp-clearkey/0.1/clearkey.info.in deleted file mode 100644 index 8b3445d599..0000000000 --- a/media/gmp-clearkey/0.1/clearkey.info.in +++ /dev/null @@ -1,10 +0,0 @@ -Name: clearkey -Description: ClearKey Gecko Media Plugin -Version: 1 -#ifdef ENABLE_WMF -APIs: eme-decrypt-v9[org.w3.clearkey], decode-audio[aac:org.w3.clearkey], decode-video[h264:org.w3.clearkey] -Libraries: dxva2.dll, d3d9.dll, msmpeg2vdec.dll, msmpeg2adec.dll, MSAudDecMFT.dll, evr.dll, mfheaacdec.dll, mfh264dec.dll, mfplat.dll -#else -APIs: eme-decrypt-v9[org.w3.clearkey] -Libraries: -#endif diff --git a/media/gmp-clearkey/0.1/gmp-clearkey.cpp b/media/gmp-clearkey/0.1/gmp-clearkey.cpp deleted file mode 100644 index fae7ce9f82..0000000000 --- a/media/gmp-clearkey/0.1/gmp-clearkey.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <assert.h> -#include <stdio.h> -#include <string.h> - -#include "ClearKeyAsyncShutdown.h" -#include "ClearKeySessionManager.h" -#include "gmp-api/gmp-async-shutdown.h" -#include "gmp-api/gmp-decryption.h" -#include "gmp-api/gmp-platform.h" - -#if defined(ENABLE_WMF) -#include "WMFUtils.h" -#include "AudioDecoder.h" -#include "VideoDecoder.h" -#endif - -#if defined(WIN32) -#define GMP_EXPORT __declspec(dllexport) -#else -#define GMP_EXPORT __attribute__((visibility("default"))) -#endif - -static GMPPlatformAPI* sPlatform = nullptr; -GMPPlatformAPI* -GetPlatform() -{ - return sPlatform; -} - -extern "C" { - -GMP_EXPORT GMPErr -GMPInit(GMPPlatformAPI* aPlatformAPI) -{ - sPlatform = aPlatformAPI; - return GMPNoErr; -} - -GMP_EXPORT GMPErr -GMPGetAPI(const char* aApiName, void* aHostAPI, void** aPluginAPI) -{ - CK_LOGD("ClearKey GMPGetAPI |%s|", aApiName); - assert(!*aPluginAPI); - - if (!strcmp(aApiName, GMP_API_DECRYPTOR)) { - *aPluginAPI = new ClearKeySessionManager(); - } -#if defined(ENABLE_WMF) - else if (!strcmp(aApiName, GMP_API_AUDIO_DECODER) && - wmf::EnsureLibs()) { - *aPluginAPI = new AudioDecoder(static_cast<GMPAudioHost*>(aHostAPI)); - } else if (!strcmp(aApiName, GMP_API_VIDEO_DECODER) && - wmf::EnsureLibs()) { - *aPluginAPI = new VideoDecoder(static_cast<GMPVideoHost*>(aHostAPI)); - } -#endif - else if (!strcmp(aApiName, GMP_API_ASYNC_SHUTDOWN)) { - *aPluginAPI = new ClearKeyAsyncShutdown(static_cast<GMPAsyncShutdownHost*> (aHostAPI)); - } else { - CK_LOGE("GMPGetAPI couldn't resolve API name |%s|\n", aApiName); - } - - return *aPluginAPI ? GMPNoErr : GMPNotImplementedErr; -} - -GMP_EXPORT GMPErr -GMPShutdown(void) -{ - CK_LOGD("ClearKey GMPShutdown"); - return GMPNoErr; -} - -} diff --git a/media/gmp-clearkey/0.1/gmp-task-utils-generated.h b/media/gmp-clearkey/0.1/gmp-task-utils-generated.h deleted file mode 100644 index 597ed47210..0000000000 --- a/media/gmp-clearkey/0.1/gmp-task-utils-generated.h +++ /dev/null @@ -1,1938 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "RefCounted.h" - -// 0 arguments -- -template<typename M> class gmp_task_args_nm_0 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_0(M m) : - m_(m) {} - - void Run() { - m_(); - } - - private: - M m_; -}; - - - -// 0 arguments -- -template<typename M, typename R> class gmp_task_args_nm_0_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_0_ret(M m, R *r) : - m_(m), r_(r) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(); - } - - private: - M m_; - R* r_; -}; - - - -// 0 arguments -- -template<typename C, typename M> class gmp_task_args_m_0 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_0(C o, M m) : - o_(o), m_(m) {} - - void Run() { - ((*o_).*m_)(); - } - - private: - C o_; - M m_; -}; - - - -// 0 arguments -- -template<typename C, typename M, typename R> class gmp_task_args_m_0_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_0_ret(C o, M m, R *r) : - o_(o), m_(m), r_(r) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(); - } - - private: - C o_; - M m_; - R* r_; -}; - - - -// 1 arguments -- -template<typename M, typename A0> class gmp_task_args_nm_1 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_1(M m, A0 a0) : - m_(m), a0_(a0) {} - - void Run() { - m_(a0_); - } - - private: - M m_; - A0 a0_; -}; - - - -// 1 arguments -- -template<typename M, typename A0, typename R> class gmp_task_args_nm_1_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_1_ret(M m, A0 a0, R *r) : - m_(m), r_(r), a0_(a0) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_); - } - - private: - M m_; - R* r_; - A0 a0_; -}; - - - -// 1 arguments -- -template<typename C, typename M, typename A0> class gmp_task_args_m_1 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_1(C o, M m, A0 a0) : - o_(o), m_(m), a0_(a0) {} - - void Run() { - ((*o_).*m_)(a0_); - } - - private: - C o_; - M m_; - A0 a0_; -}; - - - -// 1 arguments -- -template<typename C, typename M, typename A0, typename R> class gmp_task_args_m_1_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_1_ret(C o, M m, A0 a0, R *r) : - o_(o), m_(m), r_(r), a0_(a0) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; -}; - - - -// 2 arguments -- -template<typename M, typename A0, typename A1> class gmp_task_args_nm_2 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_2(M m, A0 a0, A1 a1) : - m_(m), a0_(a0), a1_(a1) {} - - void Run() { - m_(a0_, a1_); - } - - private: - M m_; - A0 a0_; - A1 a1_; -}; - - - -// 2 arguments -- -template<typename M, typename A0, typename A1, typename R> class gmp_task_args_nm_2_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_2_ret(M m, A0 a0, A1 a1, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; -}; - - - -// 2 arguments -- -template<typename C, typename M, typename A0, typename A1> class gmp_task_args_m_2 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_2(C o, M m, A0 a0, A1 a1) : - o_(o), m_(m), a0_(a0), a1_(a1) {} - - void Run() { - ((*o_).*m_)(a0_, a1_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; -}; - - - -// 2 arguments -- -template<typename C, typename M, typename A0, typename A1, typename R> class gmp_task_args_m_2_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_2_ret(C o, M m, A0 a0, A1 a1, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; -}; - - - -// 3 arguments -- -template<typename M, typename A0, typename A1, typename A2> class gmp_task_args_nm_3 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_3(M m, A0 a0, A1 a1, A2 a2) : - m_(m), a0_(a0), a1_(a1), a2_(a2) {} - - void Run() { - m_(a0_, a1_, a2_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; -}; - - - -// 3 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename R> class gmp_task_args_nm_3_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_3_ret(M m, A0 a0, A1 a1, A2 a2, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; -}; - - - -// 3 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2> class gmp_task_args_m_3 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_3(C o, M m, A0 a0, A1 a1, A2 a2) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; -}; - - - -// 3 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename R> class gmp_task_args_m_3_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_3_ret(C o, M m, A0 a0, A1 a1, A2 a2, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; -}; - - - -// 4 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3> class gmp_task_args_nm_4 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_4(M m, A0 a0, A1 a1, A2 a2, A3 a3) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3) {} - - void Run() { - m_(a0_, a1_, a2_, a3_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; -}; - - - -// 4 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename R> class gmp_task_args_nm_4_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_4_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; -}; - - - -// 4 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3> class gmp_task_args_m_4 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_4(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; -}; - - - -// 4 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename R> class gmp_task_args_m_4_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_4_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; -}; - - - -// 5 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4> class gmp_task_args_nm_5 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_5(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; -}; - - - -// 5 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename R> class gmp_task_args_nm_5_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_5_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; -}; - - - -// 5 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4> class gmp_task_args_m_5 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_5(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; -}; - - - -// 5 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename R> class gmp_task_args_m_5_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_5_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; -}; - - - -// 6 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> class gmp_task_args_nm_6 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_6(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; -}; - - - -// 6 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename R> class gmp_task_args_nm_6_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_6_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; -}; - - - -// 6 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> class gmp_task_args_m_6 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_6(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; -}; - - - -// 6 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename R> class gmp_task_args_m_6_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_6_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; -}; - - - -// 7 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> class gmp_task_args_nm_7 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_7(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; -}; - - - -// 7 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename R> class gmp_task_args_nm_7_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_7_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; -}; - - - -// 7 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> class gmp_task_args_m_7 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_7(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; -}; - - - -// 7 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename R> class gmp_task_args_m_7_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_7_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; -}; - - - -// 8 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> class gmp_task_args_nm_8 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_8(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; -}; - - - -// 8 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename R> class gmp_task_args_nm_8_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_8_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; -}; - - - -// 8 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> class gmp_task_args_m_8 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_8(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; -}; - - - -// 8 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename R> class gmp_task_args_m_8_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_8_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; -}; - - - -// 9 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> class gmp_task_args_nm_9 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_9(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; -}; - - - -// 9 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename R> class gmp_task_args_nm_9_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_9_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; -}; - - - -// 9 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> class gmp_task_args_m_9 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_9(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; -}; - - - -// 9 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename R> class gmp_task_args_m_9_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_9_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; -}; - - - -// 10 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> class gmp_task_args_nm_10 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_10(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; -}; - - - -// 10 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename R> class gmp_task_args_nm_10_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_10_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; -}; - - - -// 10 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> class gmp_task_args_m_10 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_10(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; -}; - - - -// 10 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename R> class gmp_task_args_m_10_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_10_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; -}; - - - -// 11 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10> class gmp_task_args_nm_11 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_11(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; -}; - - - -// 11 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename R> class gmp_task_args_nm_11_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_11_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; -}; - - - -// 11 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10> class gmp_task_args_m_11 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_11(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; -}; - - - -// 11 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename R> class gmp_task_args_m_11_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_11_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; -}; - - - -// 12 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11> class gmp_task_args_nm_12 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_12(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; -}; - - - -// 12 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename R> class gmp_task_args_nm_12_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_12_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; -}; - - - -// 12 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11> class gmp_task_args_m_12 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_12(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; -}; - - - -// 12 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename R> class gmp_task_args_m_12_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_12_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; -}; - - - -// 13 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12> class gmp_task_args_nm_13 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_13(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; -}; - - - -// 13 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename R> class gmp_task_args_nm_13_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_13_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; -}; - - - -// 13 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12> class gmp_task_args_m_13 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_13(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; -}; - - - -// 13 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename R> class gmp_task_args_m_13_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_13_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; -}; - - - -// 14 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13> class gmp_task_args_nm_14 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_14(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; - A13 a13_; -}; - - - -// 14 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename R> class gmp_task_args_nm_14_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_14_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; - A13 a13_; -}; - - - -// 14 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13> class gmp_task_args_m_14 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_14(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; - A13 a13_; -}; - - - -// 14 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename R> class gmp_task_args_m_14_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_14_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; - A13 a13_; -}; - - - - - - -// 0 arguments -- -template<typename M> -gmp_task_args_nm_0<M>* WrapTaskNM(M m) { - return new gmp_task_args_nm_0<M> - (m); -} - -// 0 arguments -- -template<typename M, typename R> -gmp_task_args_nm_0_ret<M, R>* WrapTaskNMRet(M m, R* r) { - return new gmp_task_args_nm_0_ret<M, R> - (m, r); -} - -// 0 arguments -- -template<typename C, typename M> -gmp_task_args_m_0<C, M>* WrapTask(C o, M m) { - return new gmp_task_args_m_0<C, M> - (o, m); -} - -// 0 arguments -- -template<typename C, typename M, typename R> -gmp_task_args_m_0_ret<C, M, R>* WrapTaskRet(C o, M m, R* r) { - return new gmp_task_args_m_0_ret<C, M, R> - (o, m, r); -} - -// 1 arguments -- -template<typename M, typename A0> -gmp_task_args_nm_1<M, A0>* WrapTaskNM(M m, A0 a0) { - return new gmp_task_args_nm_1<M, A0> - (m, a0); -} - -// 1 arguments -- -template<typename M, typename A0, typename R> -gmp_task_args_nm_1_ret<M, A0, R>* WrapTaskNMRet(M m, A0 a0, R* r) { - return new gmp_task_args_nm_1_ret<M, A0, R> - (m, a0, r); -} - -// 1 arguments -- -template<typename C, typename M, typename A0> -gmp_task_args_m_1<C, M, A0>* WrapTask(C o, M m, A0 a0) { - return new gmp_task_args_m_1<C, M, A0> - (o, m, a0); -} - -// 1 arguments -- -template<typename C, typename M, typename A0, typename R> -gmp_task_args_m_1_ret<C, M, A0, R>* WrapTaskRet(C o, M m, A0 a0, R* r) { - return new gmp_task_args_m_1_ret<C, M, A0, R> - (o, m, a0, r); -} - -// 2 arguments -- -template<typename M, typename A0, typename A1> -gmp_task_args_nm_2<M, A0, A1>* WrapTaskNM(M m, A0 a0, A1 a1) { - return new gmp_task_args_nm_2<M, A0, A1> - (m, a0, a1); -} - -// 2 arguments -- -template<typename M, typename A0, typename A1, typename R> -gmp_task_args_nm_2_ret<M, A0, A1, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, R* r) { - return new gmp_task_args_nm_2_ret<M, A0, A1, R> - (m, a0, a1, r); -} - -// 2 arguments -- -template<typename C, typename M, typename A0, typename A1> -gmp_task_args_m_2<C, M, A0, A1>* WrapTask(C o, M m, A0 a0, A1 a1) { - return new gmp_task_args_m_2<C, M, A0, A1> - (o, m, a0, a1); -} - -// 2 arguments -- -template<typename C, typename M, typename A0, typename A1, typename R> -gmp_task_args_m_2_ret<C, M, A0, A1, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, R* r) { - return new gmp_task_args_m_2_ret<C, M, A0, A1, R> - (o, m, a0, a1, r); -} - -// 3 arguments -- -template<typename M, typename A0, typename A1, typename A2> -gmp_task_args_nm_3<M, A0, A1, A2>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2) { - return new gmp_task_args_nm_3<M, A0, A1, A2> - (m, a0, a1, a2); -} - -// 3 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename R> -gmp_task_args_nm_3_ret<M, A0, A1, A2, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, R* r) { - return new gmp_task_args_nm_3_ret<M, A0, A1, A2, R> - (m, a0, a1, a2, r); -} - -// 3 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2> -gmp_task_args_m_3<C, M, A0, A1, A2>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2) { - return new gmp_task_args_m_3<C, M, A0, A1, A2> - (o, m, a0, a1, a2); -} - -// 3 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename R> -gmp_task_args_m_3_ret<C, M, A0, A1, A2, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, R* r) { - return new gmp_task_args_m_3_ret<C, M, A0, A1, A2, R> - (o, m, a0, a1, a2, r); -} - -// 4 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3> -gmp_task_args_nm_4<M, A0, A1, A2, A3>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3) { - return new gmp_task_args_nm_4<M, A0, A1, A2, A3> - (m, a0, a1, a2, a3); -} - -// 4 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename R> -gmp_task_args_nm_4_ret<M, A0, A1, A2, A3, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, R* r) { - return new gmp_task_args_nm_4_ret<M, A0, A1, A2, A3, R> - (m, a0, a1, a2, a3, r); -} - -// 4 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3> -gmp_task_args_m_4<C, M, A0, A1, A2, A3>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3) { - return new gmp_task_args_m_4<C, M, A0, A1, A2, A3> - (o, m, a0, a1, a2, a3); -} - -// 4 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename R> -gmp_task_args_m_4_ret<C, M, A0, A1, A2, A3, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, R* r) { - return new gmp_task_args_m_4_ret<C, M, A0, A1, A2, A3, R> - (o, m, a0, a1, a2, a3, r); -} - -// 5 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4> -gmp_task_args_nm_5<M, A0, A1, A2, A3, A4>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return new gmp_task_args_nm_5<M, A0, A1, A2, A3, A4> - (m, a0, a1, a2, a3, a4); -} - -// 5 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename R> -gmp_task_args_nm_5_ret<M, A0, A1, A2, A3, A4, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, R* r) { - return new gmp_task_args_nm_5_ret<M, A0, A1, A2, A3, A4, R> - (m, a0, a1, a2, a3, a4, r); -} - -// 5 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4> -gmp_task_args_m_5<C, M, A0, A1, A2, A3, A4>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return new gmp_task_args_m_5<C, M, A0, A1, A2, A3, A4> - (o, m, a0, a1, a2, a3, a4); -} - -// 5 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename R> -gmp_task_args_m_5_ret<C, M, A0, A1, A2, A3, A4, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, R* r) { - return new gmp_task_args_m_5_ret<C, M, A0, A1, A2, A3, A4, R> - (o, m, a0, a1, a2, a3, a4, r); -} - -// 6 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> -gmp_task_args_nm_6<M, A0, A1, A2, A3, A4, A5>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { - return new gmp_task_args_nm_6<M, A0, A1, A2, A3, A4, A5> - (m, a0, a1, a2, a3, a4, a5); -} - -// 6 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename R> -gmp_task_args_nm_6_ret<M, A0, A1, A2, A3, A4, A5, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, R* r) { - return new gmp_task_args_nm_6_ret<M, A0, A1, A2, A3, A4, A5, R> - (m, a0, a1, a2, a3, a4, a5, r); -} - -// 6 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5> -gmp_task_args_m_6<C, M, A0, A1, A2, A3, A4, A5>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { - return new gmp_task_args_m_6<C, M, A0, A1, A2, A3, A4, A5> - (o, m, a0, a1, a2, a3, a4, a5); -} - -// 6 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename R> -gmp_task_args_m_6_ret<C, M, A0, A1, A2, A3, A4, A5, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, R* r) { - return new gmp_task_args_m_6_ret<C, M, A0, A1, A2, A3, A4, A5, R> - (o, m, a0, a1, a2, a3, a4, a5, r); -} - -// 7 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> -gmp_task_args_nm_7<M, A0, A1, A2, A3, A4, A5, A6>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { - return new gmp_task_args_nm_7<M, A0, A1, A2, A3, A4, A5, A6> - (m, a0, a1, a2, a3, a4, a5, a6); -} - -// 7 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename R> -gmp_task_args_nm_7_ret<M, A0, A1, A2, A3, A4, A5, A6, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, R* r) { - return new gmp_task_args_nm_7_ret<M, A0, A1, A2, A3, A4, A5, A6, R> - (m, a0, a1, a2, a3, a4, a5, a6, r); -} - -// 7 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> -gmp_task_args_m_7<C, M, A0, A1, A2, A3, A4, A5, A6>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { - return new gmp_task_args_m_7<C, M, A0, A1, A2, A3, A4, A5, A6> - (o, m, a0, a1, a2, a3, a4, a5, a6); -} - -// 7 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename R> -gmp_task_args_m_7_ret<C, M, A0, A1, A2, A3, A4, A5, A6, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, R* r) { - return new gmp_task_args_m_7_ret<C, M, A0, A1, A2, A3, A4, A5, A6, R> - (o, m, a0, a1, a2, a3, a4, a5, a6, r); -} - -// 8 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> -gmp_task_args_nm_8<M, A0, A1, A2, A3, A4, A5, A6, A7>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) { - return new gmp_task_args_nm_8<M, A0, A1, A2, A3, A4, A5, A6, A7> - (m, a0, a1, a2, a3, a4, a5, a6, a7); -} - -// 8 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename R> -gmp_task_args_nm_8_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, R* r) { - return new gmp_task_args_nm_8_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, R> - (m, a0, a1, a2, a3, a4, a5, a6, a7, r); -} - -// 8 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7> -gmp_task_args_m_8<C, M, A0, A1, A2, A3, A4, A5, A6, A7>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) { - return new gmp_task_args_m_8<C, M, A0, A1, A2, A3, A4, A5, A6, A7> - (o, m, a0, a1, a2, a3, a4, a5, a6, a7); -} - -// 8 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename R> -gmp_task_args_m_8_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, R* r) { - return new gmp_task_args_m_8_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, R> - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, r); -} - -// 9 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> -gmp_task_args_nm_9<M, A0, A1, A2, A3, A4, A5, A6, A7, A8>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) { - return new gmp_task_args_nm_9<M, A0, A1, A2, A3, A4, A5, A6, A7, A8> - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8); -} - -// 9 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename R> -gmp_task_args_nm_9_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, R* r) { - return new gmp_task_args_nm_9_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, R> - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, r); -} - -// 9 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8> -gmp_task_args_m_9<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) { - return new gmp_task_args_m_9<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8> - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8); -} - -// 9 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename R> -gmp_task_args_m_9_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, R* r) { - return new gmp_task_args_m_9_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, R> - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, r); -} - -// 10 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> -gmp_task_args_nm_10<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) { - return new gmp_task_args_nm_10<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9> - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); -} - -// 10 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename R> -gmp_task_args_nm_10_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R* r) { - return new gmp_task_args_nm_10_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, R> - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, r); -} - -// 10 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9> -gmp_task_args_m_10<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) { - return new gmp_task_args_m_10<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9> - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); -} - -// 10 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename R> -gmp_task_args_m_10_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R* r) { - return new gmp_task_args_m_10_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, R> - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, r); -} - -// 11 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10> -gmp_task_args_nm_11<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) { - return new gmp_task_args_nm_11<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10> - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); -} - -// 11 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename R> -gmp_task_args_nm_11_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R* r) { - return new gmp_task_args_nm_11_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, R> - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, r); -} - -// 11 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10> -gmp_task_args_m_11<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) { - return new gmp_task_args_m_11<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10> - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); -} - -// 11 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename R> -gmp_task_args_m_11_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R* r) { - return new gmp_task_args_m_11_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, R> - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, r); -} - -// 12 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11> -gmp_task_args_nm_12<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) { - return new gmp_task_args_nm_12<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11> - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); -} - -// 12 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename R> -gmp_task_args_nm_12_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R* r) { - return new gmp_task_args_nm_12_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, R> - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, r); -} - -// 12 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11> -gmp_task_args_m_12<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) { - return new gmp_task_args_m_12<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11> - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); -} - -// 12 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename R> -gmp_task_args_m_12_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R* r) { - return new gmp_task_args_m_12_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, R> - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, r); -} - -// 13 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12> -gmp_task_args_nm_13<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) { - return new gmp_task_args_nm_13<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12> - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); -} - -// 13 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename R> -gmp_task_args_nm_13_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R* r) { - return new gmp_task_args_nm_13_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, R> - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, r); -} - -// 13 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12> -gmp_task_args_m_13<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) { - return new gmp_task_args_m_13<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12> - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); -} - -// 13 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename R> -gmp_task_args_m_13_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R* r) { - return new gmp_task_args_m_13_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, R> - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, r); -} - -// 14 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13> -gmp_task_args_nm_14<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13>* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) { - return new gmp_task_args_nm_14<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13> - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); -} - -// 14 arguments -- -template<typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename R> -gmp_task_args_nm_14_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, R>* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R* r) { - return new gmp_task_args_nm_14_ret<M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, R> - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, r); -} - -// 14 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13> -gmp_task_args_m_14<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13>* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) { - return new gmp_task_args_m_14<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13> - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); -} - -// 14 arguments -- -template<typename C, typename M, typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename R> -gmp_task_args_m_14_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, R>* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R* r) { - return new gmp_task_args_m_14_ret<C, M, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, R> - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, r); -} - -class RefCountTaskWrapper : public gmp_task_args_base { -public: - RefCountTaskWrapper(GMPTask* aTask, RefCounted* aRefCounted) - : mTask(aTask) - , mRefCounted(aRefCounted) - {} - virtual void Run() override { - mTask->Run(); - } - virtual void Destroy() override { - mTask->Destroy(); - gmp_task_args_base::Destroy(); - } -private: - ~RefCountTaskWrapper() {} - - GMPTask* mTask; - RefPtr<RefCounted> mRefCounted; -}; - -template<typename Type, typename Method, typename... Args> -GMPTask* -WrapTaskRefCounted(Type* aType, Method aMethod, Args&&... args) -{ - GMPTask* t = WrapTask(aType, aMethod, std::forward<Args>(args)...); - return new RefCountTaskWrapper(t, aType); -} diff --git a/media/gmp-clearkey/0.1/gmp-task-utils.h b/media/gmp-clearkey/0.1/gmp-task-utils.h deleted file mode 100644 index 82e08373f2..0000000000 --- a/media/gmp-clearkey/0.1/gmp-task-utils.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Original author: ekr@rtfm.com - -#ifndef gmp_task_utils_h_ -#define gmp_task_utils_h_ - -#include "gmp-api/gmp-platform.h" - -class gmp_task_args_base : public GMPTask { -public: - virtual void Destroy() { delete this; } - virtual void Run() = 0; -}; - -// The generated file contains four major function templates -// (in variants for arbitrary numbers of arguments up to 10, -// which is why it is machine generated). The four templates -// are: -// -// WrapTask(o, m, ...) -- wraps a member function m of an object ptr o -// WrapTaskRet(o, m, ..., r) -- wraps a member function m of an object ptr o -// the function returns something that can -// be assigned to *r -// WrapTaskNM(f, ...) -- wraps a function f -// WrapTaskNMRet(f, ..., r) -- wraps a function f that returns something -// that can be assigned to *r -// -// All of these template functions return a GMPTask* which can be passed -// to DispatchXX(). -#include "gmp-task-utils-generated.h" - -#endif // gmp_task_utils_h_ diff --git a/media/gmp-clearkey/0.1/gtest/TestClearKeyUtils.cpp b/media/gmp-clearkey/0.1/gtest/TestClearKeyUtils.cpp deleted file mode 100644 index 021d1af68d..0000000000 --- a/media/gmp-clearkey/0.1/gtest/TestClearKeyUtils.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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/. */ - -#include "gtest/gtest.h" -#include <algorithm> -#include <stdint.h> -#include <vector> - -#include "../ClearKeyBase64.cpp" - -using namespace std; - -struct B64Test { - string b64; - vector<uint8_t> raw; - bool shouldPass; -}; - -const B64Test tests[] = { - { - "AAAAADk4AU4AAAAAAAAAAA", - { 0x0, 0x0, 0x0, 0x0, 0x39, 0x38, 0x1, 0x4e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - true - }, - { - "h2mqp1zAJjDIC34YXEXBxA==", - { 0x87, 0x69, 0xaa, 0xa7, 0x5c, 0xc0, 0x26, 0x30, 0xc8, 0xb, 0x7e, 0x18, 0x5c, 0x45, 0xc1, 0xc4 }, - true - }, - { - "flcdA35XHQN-Vx0DflcdAw", - { 0x7e, 0x57, 0x1d, 0x3, 0x7e, 0x57, 0x1d, 0x3, 0x7e, 0x57, 0x1d, 0x3, 0x7e, 0x57, 0x1d, 0x3 }, - true - }, - { - "flczM35XMzN-VzMzflczMw", - { 0x7e, 0x57, 0x33, 0x33, 0x7e, 0x57, 0x33, 0x33, 0x7e, 0x57, 0x33, 0x33, 0x7e, 0x57, 0x33, 0x33 }, - true, - }, - { - "flcdBH5XHQR-Vx0EflcdBA", - { 0x7e, 0x57, 0x1d, 0x4, 0x7e, 0x57, 0x1d, 0x4, 0x7e, 0x57, 0x1d, 0x4, 0x7e, 0x57, 0x1d, 0x4 }, - true - }, - { - "fldERH5XRER-V0REfldERA", - { 0x7e, 0x57, 0x44, 0x44, 0x7e, 0x57, 0x44, 0x44, 0x7e, 0x57, 0x44, 0x44, 0x7e, 0x57, 0x44, 0x44 }, - true - }, - { - "fuzzbiz=", - { 0x7e, 0xec, 0xf3, 0x6e, 0x2c }, - true - }, - { - "fuzzbizfuzzbizfuzzbizfuzzbizfuzzbizfuzzbizfuzzbizfuzzbiz", - { - 0x7e, 0xec, 0xf3, 0x6e, 0x2c, 0xdf, 0xbb, 0x3c, 0xdb, 0x8b, - 0x37, 0xee, 0xcf, 0x36, 0xe2, 0xcd, 0xfb, 0xb3, 0xcd, 0xb8, - 0xb3, 0x7e, 0xec, 0xf3, 0x6e, 0x2c, 0xdf, 0xbb, 0x3c, 0xdb, - 0x8b, 0x37, 0xee, 0xcf, 0x36, 0xe2, 0xcd, 0xfb, 0xb3, 0xcd, - 0xb8, 0xb3 - }, - true - }, - { "", { }, true }, - { "00", { 0xd3 }, true }, - { "000", { 0xd3, 0x4d }, true }, - - { "invalid", { 0x8a, 0x7b, 0xda, 0x96, 0x27 }, true }, - { "invalic", { 0x8a, 0x7b, 0xda, 0x96, 0x27 }, true }, - - // Failure tests - { "A", { }, false }, // 1 character is too few. - { "_", { }, false }, // 1 character is too few. -}; - -TEST(ClearKey, DecodeBase64) { - for (const B64Test& test : tests) { - vector<uint8_t> v; - bool rv = DecodeBase64(string(test.b64), v); - EXPECT_EQ(test.shouldPass, rv); - if (test.shouldPass) { - EXPECT_EQ(test.raw.size(), v.size()); - for (size_t k = 0; k < test.raw.size(); k++) { - EXPECT_EQ(test.raw[k], v[k]); - } - } - } -} diff --git a/media/gmp-clearkey/0.1/gtest/moz.build b/media/gmp-clearkey/0.1/gtest/moz.build deleted file mode 100644 index 22a61d280e..0000000000 --- a/media/gmp-clearkey/0.1/gtest/moz.build +++ /dev/null @@ -1,14 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# 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/. - -UNIFIED_SOURCES += [ - 'TestClearKeyUtils.cpp', -] - -FINAL_LIBRARY = 'xul-gtest' - -LOCAL_INCLUDES += [ - '..', -] diff --git a/media/gmp-clearkey/0.1/moz.build b/media/gmp-clearkey/0.1/moz.build deleted file mode 100644 index fb25fa8fcc..0000000000 --- a/media/gmp-clearkey/0.1/moz.build +++ /dev/null @@ -1,74 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# 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/. - -SharedLibrary('clearkey') - -FINAL_TARGET = 'dist/bin/gmp-clearkey/0.1' - -FINAL_TARGET_PP_FILES += ['clearkey.info.in'] - -UNIFIED_SOURCES += [ - 'ClearKeyAsyncShutdown.cpp', - 'ClearKeyBase64.cpp', - 'ClearKeyDecryptionManager.cpp', - 'ClearKeyPersistence.cpp', - 'ClearKeySession.cpp', - 'ClearKeySessionManager.cpp', - 'ClearKeyStorage.cpp', - 'ClearKeyUtils.cpp', - 'gmp-clearkey.cpp', -] - -SOURCES += [ - 'openaes/oaes_lib.c', -] - -if CONFIG['OS_ARCH'] == 'WINNT': - UNIFIED_SOURCES += [ - 'AnnexB.cpp', - 'AudioDecoder.cpp', - 'VideoDecoder.cpp', - 'WMFAACDecoder.cpp', - 'WMFH264Decoder.cpp', - ] - - SOURCES += [ - 'WMFUtils.cpp', - ] - - OS_LIBS += [ - 'mfuuid', - ] - - DEFINES['ENABLE_WMF'] = True - -TEST_DIRS += [ - 'gtest', -] - - -LOCAL_INCLUDES += [ - '/dom/media/gmp', -] - -DISABLE_STL_WRAPPING = True -DEFINES['MOZ_NO_MOZALLOC'] = True - -USE_LIBS += ['psshparser'] - -# Suppress warnings in third-party code. -if CONFIG['GNU_CXX']: - CFLAGS += [ - '-Wno-missing-braces', - '-Wno-pointer-to-int-cast', - '-Wno-sign-compare', - '-include', 'stdio.h', # for sprintf() prototype - '-include', 'unistd.h', # for getpid() prototype - ] -elif CONFIG['_MSC_VER']: - CFLAGS += [ - '-FI', 'stdio.h', # for sprintf() prototype - '-wd4090', # '=' : different 'const' qualifiers - ] diff --git a/media/gmp-clearkey/0.1/openaes/LICENSE b/media/gmp-clearkey/0.1/openaes/LICENSE deleted file mode 100644 index d824e13ddb..0000000000 --- a/media/gmp-clearkey/0.1/openaes/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ ---------------------------------------------------------------------------- -OpenAES Licence ---------------------------------------------------------------------------- -Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- diff --git a/media/gmp-clearkey/0.1/openaes/oaes_common.h b/media/gmp-clearkey/0.1/openaes/oaes_common.h deleted file mode 100644 index 7e2bf513f6..0000000000 --- a/media/gmp-clearkey/0.1/openaes/oaes_common.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * OpenAES License - * --------------------------------------------------------------------------- - * Copyright (c) 2013, Nabil S. Al Ramli, www.nalramli.com - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * --------------------------------------------------------------------------- - */ - -#ifndef _OAES_COMMON_H -#define _OAES_COMMON_H - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 -# ifdef OAES_SHARED -# ifdef oaes_lib_EXPORTS -# define OAES_API __declspec(dllexport) -# else -# define OAES_API __declspec(dllimport) -# endif -# else -# define OAES_API -# endif -#else -# define OAES_API -#endif // WIN32 - -#define OAES_VERSION "0.9.0" - -typedef enum -{ - OAES_RET_FIRST = 0, - OAES_RET_SUCCESS = 0, - OAES_RET_ERROR, - OAES_RET_ARG1, - OAES_RET_ARG2, - OAES_RET_ARG3, - OAES_RET_ARG4, - OAES_RET_ARG5, - OAES_RET_NOKEY, - OAES_RET_MEM, - OAES_RET_BUF, - OAES_RET_HEADER, - OAES_RET_COUNT -} OAES_RET; - -#ifdef __cplusplus -} -#endif - -#endif // _OAES_COMMON_H diff --git a/media/gmp-clearkey/0.1/openaes/oaes_config.h b/media/gmp-clearkey/0.1/openaes/oaes_config.h deleted file mode 100644 index cb9f4e7be7..0000000000 --- a/media/gmp-clearkey/0.1/openaes/oaes_config.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * OpenAES License - * --------------------------------------------------------------------------- - * Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * --------------------------------------------------------------------------- - */ - -#ifndef _OAES_CONFIG_H -#define _OAES_CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef OAES_DEBUG -#define OAES_DEBUG 0 -#endif // OAES_DEBUG - -#ifdef __cplusplus -} -#endif - -#endif // _OAES_CONFIG_H diff --git a/media/gmp-clearkey/0.1/openaes/oaes_lib.c b/media/gmp-clearkey/0.1/openaes/oaes_lib.c deleted file mode 100644 index aa13623ce8..0000000000 --- a/media/gmp-clearkey/0.1/openaes/oaes_lib.c +++ /dev/null @@ -1,1393 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * OpenAES License - * --------------------------------------------------------------------------- - * Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * --------------------------------------------------------------------------- - */ - -#include <stdlib.h> -#include <stddef.h> -#include <time.h> -#include <string.h> - -#include "mozilla/Sprintf.h" - -#ifdef WIN32 -#include <process.h> -#endif - -#include "oaes_config.h" -#include "oaes_lib.h" - -#ifdef OAES_HAVE_ISAAC -#include "rand.h" -#define OAES_RAND(x) rand(x) -#else -#define OAES_RAND(x) rand() -#endif // OAES_HAVE_ISAAC - -#define OAES_RKEY_LEN 4 -#define OAES_COL_LEN 4 -#define OAES_ROUND_BASE 7 - -// the block is padded -#define OAES_FLAG_PAD 0x01 - -#ifndef min -# define min(a,b) (((a)<(b)) ? (a) : (b)) -#endif /* min */ - -typedef struct _oaes_key -{ - size_t data_len; - uint8_t *data; - size_t exp_data_len; - uint8_t *exp_data; - size_t num_keys; - size_t key_base; -} oaes_key; - -typedef struct _oaes_ctx -{ -#ifdef OAES_HAVE_ISAAC - randctx * rctx; -#endif // OAES_HAVE_ISAAC - -#ifdef OAES_DEBUG - oaes_step_cb step_cb; -#endif // OAES_DEBUG - - oaes_key * key; - OAES_OPTION options; - uint8_t iv[OAES_BLOCK_SIZE]; -} oaes_ctx; - -// "OAES<8-bit header version><8-bit type><16-bit options><8-bit flags><56-bit reserved>" -static uint8_t oaes_header[OAES_BLOCK_SIZE] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x4f, 0x41, 0x45, 0x53, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t oaes_gf_8[] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; - -static uint8_t oaes_sub_byte_value[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - /*1*/ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - /*2*/ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - /*3*/ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - /*4*/ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - /*5*/ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - /*6*/ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - /*7*/ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - /*8*/ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - /*9*/ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - /*a*/ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - /*b*/ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - /*c*/ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - /*d*/ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - /*e*/ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - /*f*/ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, -}; - -static uint8_t oaes_inv_sub_byte_value[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, - /*1*/ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, - /*2*/ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - /*3*/ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, - /*4*/ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, - /*5*/ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - /*6*/ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, - /*7*/ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, - /*8*/ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - /*9*/ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, - /*a*/ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, - /*b*/ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - /*c*/ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, - /*d*/ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, - /*e*/ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - /*f*/ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, -}; - -static uint8_t oaes_gf_mul_2[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, - /*1*/ 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, - /*2*/ 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, - /*3*/ 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, - /*4*/ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, - /*5*/ 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, - /*6*/ 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, - /*7*/ 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, - /*8*/ 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, - /*9*/ 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, - /*a*/ 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, - /*b*/ 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, - /*c*/ 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, - /*d*/ 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, - /*e*/ 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, - /*f*/ 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5, -}; - -static uint8_t oaes_gf_mul_3[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, - /*1*/ 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, - /*2*/ 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, - /*3*/ 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41, - /*4*/ 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, - /*5*/ 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1, - /*6*/ 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, - /*7*/ 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, - /*8*/ 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a, - /*9*/ 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba, - /*a*/ 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, - /*b*/ 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda, - /*c*/ 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a, - /*d*/ 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, - /*e*/ 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a, - /*f*/ 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a, -}; - -static uint8_t oaes_gf_mul_9[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, - /*1*/ 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, - /*2*/ 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, - /*3*/ 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, - /*4*/ 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, - /*5*/ 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, - /*6*/ 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, - /*7*/ 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, - /*8*/ 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, - /*9*/ 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, - /*a*/ 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, - /*b*/ 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, - /*c*/ 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, - /*d*/ 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, - /*e*/ 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, - /*f*/ 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46, -}; - -static uint8_t oaes_gf_mul_b[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, - /*1*/ 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, - /*2*/ 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, - /*3*/ 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, - /*4*/ 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, - /*5*/ 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, - /*6*/ 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, - /*7*/ 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, - /*8*/ 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, - /*9*/ 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, - /*a*/ 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, - /*b*/ 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, - /*c*/ 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, - /*d*/ 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, - /*e*/ 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, - /*f*/ 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3, -}; - -static uint8_t oaes_gf_mul_d[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, - /*1*/ 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, - /*2*/ 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, - /*3*/ 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, - /*4*/ 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, - /*5*/ 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, - /*6*/ 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, - /*7*/ 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, - /*8*/ 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, - /*9*/ 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, - /*a*/ 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, - /*b*/ 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, - /*c*/ 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, - /*d*/ 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, - /*e*/ 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, - /*f*/ 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97, -}; - -static uint8_t oaes_gf_mul_e[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, - /*1*/ 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, - /*2*/ 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, - /*3*/ 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, - /*4*/ 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, - /*5*/ 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, - /*6*/ 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, - /*7*/ 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, - /*8*/ 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, - /*9*/ 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, - /*a*/ 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, - /*b*/ 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, - /*c*/ 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, - /*d*/ 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, - /*e*/ 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, - /*f*/ 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d, -}; - -static OAES_RET oaes_sub_byte( uint8_t * byte ) -{ - size_t _x, _y; - - if( NULL == byte ) - return OAES_RET_ARG1; - - _x = _y = *byte; - _x &= 0x0f; - _y &= 0xf0; - _y >>= 4; - *byte = oaes_sub_byte_value[_y][_x]; - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_inv_sub_byte( uint8_t * byte ) -{ - size_t _x, _y; - - if( NULL == byte ) - return OAES_RET_ARG1; - - _x = _y = *byte; - _x &= 0x0f; - _y &= 0xf0; - _y >>= 4; - *byte = oaes_inv_sub_byte_value[_y][_x]; - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_word_rot_left( uint8_t word[OAES_COL_LEN] ) -{ - uint8_t _temp[OAES_COL_LEN]; - - if( NULL == word ) - return OAES_RET_ARG1; - - memcpy( _temp, word + 1, OAES_COL_LEN - 1 ); - _temp[OAES_COL_LEN - 1] = word[0]; - memcpy( word, _temp, OAES_COL_LEN ); - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_shift_rows( uint8_t block[OAES_BLOCK_SIZE] ) -{ - uint8_t _temp[OAES_BLOCK_SIZE]; - - if( NULL == block ) - return OAES_RET_ARG1; - - _temp[0x00] = block[0x00]; - _temp[0x01] = block[0x05]; - _temp[0x02] = block[0x0a]; - _temp[0x03] = block[0x0f]; - _temp[0x04] = block[0x04]; - _temp[0x05] = block[0x09]; - _temp[0x06] = block[0x0e]; - _temp[0x07] = block[0x03]; - _temp[0x08] = block[0x08]; - _temp[0x09] = block[0x0d]; - _temp[0x0a] = block[0x02]; - _temp[0x0b] = block[0x07]; - _temp[0x0c] = block[0x0c]; - _temp[0x0d] = block[0x01]; - _temp[0x0e] = block[0x06]; - _temp[0x0f] = block[0x0b]; - memcpy( block, _temp, OAES_BLOCK_SIZE ); - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_inv_shift_rows( uint8_t block[OAES_BLOCK_SIZE] ) -{ - uint8_t _temp[OAES_BLOCK_SIZE]; - - if( NULL == block ) - return OAES_RET_ARG1; - - _temp[0x00] = block[0x00]; - _temp[0x01] = block[0x0d]; - _temp[0x02] = block[0x0a]; - _temp[0x03] = block[0x07]; - _temp[0x04] = block[0x04]; - _temp[0x05] = block[0x01]; - _temp[0x06] = block[0x0e]; - _temp[0x07] = block[0x0b]; - _temp[0x08] = block[0x08]; - _temp[0x09] = block[0x05]; - _temp[0x0a] = block[0x02]; - _temp[0x0b] = block[0x0f]; - _temp[0x0c] = block[0x0c]; - _temp[0x0d] = block[0x09]; - _temp[0x0e] = block[0x06]; - _temp[0x0f] = block[0x03]; - memcpy( block, _temp, OAES_BLOCK_SIZE ); - - return OAES_RET_SUCCESS; -} - -static uint8_t oaes_gf_mul(uint8_t left, uint8_t right) -{ - size_t _x, _y; - - _x = _y = left; - _x &= 0x0f; - _y &= 0xf0; - _y >>= 4; - - switch( right ) - { - case 0x02: - return oaes_gf_mul_2[_y][_x]; - break; - case 0x03: - return oaes_gf_mul_3[_y][_x]; - break; - case 0x09: - return oaes_gf_mul_9[_y][_x]; - break; - case 0x0b: - return oaes_gf_mul_b[_y][_x]; - break; - case 0x0d: - return oaes_gf_mul_d[_y][_x]; - break; - case 0x0e: - return oaes_gf_mul_e[_y][_x]; - break; - default: - return left; - break; - } -} - -static OAES_RET oaes_mix_cols( uint8_t word[OAES_COL_LEN] ) -{ - uint8_t _temp[OAES_COL_LEN]; - - if( NULL == word ) - return OAES_RET_ARG1; - - _temp[0] = oaes_gf_mul(word[0], 0x02) ^ oaes_gf_mul( word[1], 0x03 ) ^ - word[2] ^ word[3]; - _temp[1] = word[0] ^ oaes_gf_mul( word[1], 0x02 ) ^ - oaes_gf_mul( word[2], 0x03 ) ^ word[3]; - _temp[2] = word[0] ^ word[1] ^ - oaes_gf_mul( word[2], 0x02 ) ^ oaes_gf_mul( word[3], 0x03 ); - _temp[3] = oaes_gf_mul( word[0], 0x03 ) ^ word[1] ^ - word[2] ^ oaes_gf_mul( word[3], 0x02 ); - memcpy( word, _temp, OAES_COL_LEN ); - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_inv_mix_cols( uint8_t word[OAES_COL_LEN] ) -{ - uint8_t _temp[OAES_COL_LEN]; - - if( NULL == word ) - return OAES_RET_ARG1; - - _temp[0] = oaes_gf_mul( word[0], 0x0e ) ^ oaes_gf_mul( word[1], 0x0b ) ^ - oaes_gf_mul( word[2], 0x0d ) ^ oaes_gf_mul( word[3], 0x09 ); - _temp[1] = oaes_gf_mul( word[0], 0x09 ) ^ oaes_gf_mul( word[1], 0x0e ) ^ - oaes_gf_mul( word[2], 0x0b ) ^ oaes_gf_mul( word[3], 0x0d ); - _temp[2] = oaes_gf_mul( word[0], 0x0d ) ^ oaes_gf_mul( word[1], 0x09 ) ^ - oaes_gf_mul( word[2], 0x0e ) ^ oaes_gf_mul( word[3], 0x0b ); - _temp[3] = oaes_gf_mul( word[0], 0x0b ) ^ oaes_gf_mul( word[1], 0x0d ) ^ - oaes_gf_mul( word[2], 0x09 ) ^ oaes_gf_mul( word[3], 0x0e ); - memcpy( word, _temp, OAES_COL_LEN ); - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_sprintf( - char * buf, size_t * buf_len, const uint8_t * data, size_t data_len ) -{ - size_t _i, _buf_len_in; - char _temp[4]; - - if( NULL == buf_len ) - return OAES_RET_ARG2; - - _buf_len_in = *buf_len; - *buf_len = data_len * 3 + data_len / OAES_BLOCK_SIZE + 1; - - if( NULL == buf ) - return OAES_RET_SUCCESS; - - if( *buf_len > _buf_len_in ) - return OAES_RET_BUF; - - if( NULL == data ) - return OAES_RET_ARG3; - - strcpy( buf, "" ); - - for( _i = 0; _i < data_len; _i++ ) - { - snprintf( _temp, sizeof(_temp), "%02x ", data[_i] ); - strcat( buf, _temp ); - if( _i && 0 == ( _i + 1 ) % OAES_BLOCK_SIZE ) - strcat( buf, "\n" ); - } - - return OAES_RET_SUCCESS; -} - -/* -#ifdef OAES_HAVE_ISAAC -static void oaes_get_seed( char buf[RANDSIZ + 1] ) -{ - struct timeb timer; - struct tm *gmTimer; - char * _test = NULL; - - ftime (&timer); - gmTimer = gmtime( &timer.time ); - _test = (char *) calloc( sizeof( char ), timer.millitm ); - sprintf( buf, "%04d%02d%02d%02d%02d%02d%03d%p%d", - gmTimer->tm_year + 1900, gmTimer->tm_mon + 1, gmTimer->tm_mday, - gmTimer->tm_hour, gmTimer->tm_min, gmTimer->tm_sec, timer.millitm, - _test + timer.millitm, getpid() ); - - if( _test ) - free( _test ); -} -#else -static uint32_t oaes_get_seed() -{ - struct timeb timer; - struct tm *gmTimer; - char * _test = NULL; - uint32_t _ret = 0; - - ftime (&timer); - gmTimer = gmtime( &timer.time ); - _test = (char *) calloc( sizeof( char ), timer.millitm ); - _ret = gmTimer->tm_year + 1900 + gmTimer->tm_mon + 1 + gmTimer->tm_mday + - gmTimer->tm_hour + gmTimer->tm_min + gmTimer->tm_sec + timer.millitm + - (uint32_t) ( _test + timer.millitm ) + getpid(); - - if( _test ) - free( _test ); - - return _ret; -} -#endif // OAES_HAVE_ISAAC -*/ - -static OAES_RET oaes_key_destroy( oaes_key ** key ) -{ - if( NULL == *key ) - return OAES_RET_SUCCESS; - - if( (*key)->data ) - { - free( (*key)->data ); - (*key)->data = NULL; - } - - if( (*key)->exp_data ) - { - free( (*key)->exp_data ); - (*key)->exp_data = NULL; - } - - (*key)->data_len = 0; - (*key)->exp_data_len = 0; - (*key)->num_keys = 0; - (*key)->key_base = 0; - free( *key ); - *key = NULL; - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_key_expand( OAES_CTX * ctx ) -{ - size_t _i, _j; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - _ctx->key->key_base = _ctx->key->data_len / OAES_RKEY_LEN; - _ctx->key->num_keys = _ctx->key->key_base + OAES_ROUND_BASE; - - _ctx->key->exp_data_len = _ctx->key->num_keys * OAES_RKEY_LEN * OAES_COL_LEN; - _ctx->key->exp_data = (uint8_t *) - calloc( _ctx->key->exp_data_len, sizeof( uint8_t )); - - if( NULL == _ctx->key->exp_data ) - return OAES_RET_MEM; - - // the first _ctx->key->data_len are a direct copy - memcpy( _ctx->key->exp_data, _ctx->key->data, _ctx->key->data_len ); - - // apply ExpandKey algorithm for remainder - for( _i = _ctx->key->key_base; _i < _ctx->key->num_keys * OAES_RKEY_LEN; _i++ ) - { - uint8_t _temp[OAES_COL_LEN]; - - memcpy( _temp, - _ctx->key->exp_data + ( _i - 1 ) * OAES_RKEY_LEN, OAES_COL_LEN ); - - // transform key column - if( 0 == _i % _ctx->key->key_base ) - { - oaes_word_rot_left( _temp ); - - for( _j = 0; _j < OAES_COL_LEN; _j++ ) - oaes_sub_byte( _temp + _j ); - - _temp[0] = _temp[0] ^ oaes_gf_8[ _i / _ctx->key->key_base - 1 ]; - } - else if( _ctx->key->key_base > 6 && 4 == _i % _ctx->key->key_base ) - { - for( _j = 0; _j < OAES_COL_LEN; _j++ ) - oaes_sub_byte( _temp + _j ); - } - - for( _j = 0; _j < OAES_COL_LEN; _j++ ) - { - _ctx->key->exp_data[ _i * OAES_RKEY_LEN + _j ] = - _ctx->key->exp_data[ ( _i - _ctx->key->key_base ) * - OAES_RKEY_LEN + _j ] ^ _temp[_j]; - } - } - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_key_gen( OAES_CTX * ctx, size_t key_size ) -{ - size_t _i; - oaes_key * _key = NULL; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - OAES_RET _rc = OAES_RET_SUCCESS; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - _key = (oaes_key *) calloc( sizeof( oaes_key ), 1 ); - - if( NULL == _key ) - return OAES_RET_MEM; - - if( _ctx->key ) - oaes_key_destroy( &(_ctx->key) ); - - _key->data_len = key_size; - _key->data = (uint8_t *) calloc( key_size, sizeof( uint8_t )); - - if( NULL == _key->data ) - { - oaes_key_destroy( &_key ); - return OAES_RET_MEM; - } - - for( _i = 0; _i < key_size; _i++ ) - _key->data[_i] = (uint8_t) OAES_RAND(_ctx->rctx); - - _ctx->key = _key; - _rc = _rc || oaes_key_expand( ctx ); - - if( _rc != OAES_RET_SUCCESS ) - { - oaes_key_destroy( &(_ctx->key) ); - return _rc; - } - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_key_gen_128( OAES_CTX * ctx ) -{ - return oaes_key_gen( ctx, 16 ); -} - -OAES_RET oaes_key_gen_192( OAES_CTX * ctx ) -{ - return oaes_key_gen( ctx, 24 ); -} - -OAES_RET oaes_key_gen_256( OAES_CTX * ctx ) -{ - return oaes_key_gen( ctx, 32 ); -} - -OAES_RET oaes_key_export( OAES_CTX * ctx, - uint8_t * data, size_t * data_len ) -{ - size_t _data_len_in; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - if( NULL == data_len ) - return OAES_RET_ARG3; - - _data_len_in = *data_len; - // data + header - *data_len = _ctx->key->data_len + OAES_BLOCK_SIZE; - - if( NULL == data ) - return OAES_RET_SUCCESS; - - if( _data_len_in < *data_len ) - return OAES_RET_BUF; - - // header - memcpy( data, oaes_header, OAES_BLOCK_SIZE ); - data[5] = 0x01; - data[7] = _ctx->key->data_len; - memcpy( data + OAES_BLOCK_SIZE, _ctx->key->data, _ctx->key->data_len ); - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_key_export_data( OAES_CTX * ctx, - uint8_t * data, size_t * data_len ) -{ - size_t _data_len_in; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - if( NULL == data_len ) - return OAES_RET_ARG3; - - _data_len_in = *data_len; - *data_len = _ctx->key->data_len; - - if( NULL == data ) - return OAES_RET_SUCCESS; - - if( _data_len_in < *data_len ) - return OAES_RET_BUF; - - memcpy( data, _ctx->key->data, *data_len ); - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_key_import( OAES_CTX * ctx, - const uint8_t * data, size_t data_len ) -{ - oaes_ctx * _ctx = (oaes_ctx *) ctx; - OAES_RET _rc = OAES_RET_SUCCESS; - int _key_length; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == data ) - return OAES_RET_ARG2; - - switch( data_len ) - { - case 16 + OAES_BLOCK_SIZE: - case 24 + OAES_BLOCK_SIZE: - case 32 + OAES_BLOCK_SIZE: - break; - default: - return OAES_RET_ARG3; - } - - // header - if( 0 != memcmp( data, oaes_header, 4 ) ) - return OAES_RET_HEADER; - - // header version - switch( data[4] ) - { - case 0x01: - break; - default: - return OAES_RET_HEADER; - } - - // header type - switch( data[5] ) - { - case 0x01: - break; - default: - return OAES_RET_HEADER; - } - - // options - _key_length = data[7]; - switch( _key_length ) - { - case 16: - case 24: - case 32: - break; - default: - return OAES_RET_HEADER; - } - - if( data_len != _key_length + OAES_BLOCK_SIZE ) - return OAES_RET_ARG3; - - if( _ctx->key ) - oaes_key_destroy( &(_ctx->key) ); - - _ctx->key = (oaes_key *) calloc( sizeof( oaes_key ), 1 ); - - if( NULL == _ctx->key ) - return OAES_RET_MEM; - - _ctx->key->data_len = _key_length; - _ctx->key->data = (uint8_t *) - calloc( _key_length, sizeof( uint8_t )); - - if( NULL == _ctx->key->data ) - { - oaes_key_destroy( &(_ctx->key) ); - return OAES_RET_MEM; - } - - memcpy( _ctx->key->data, data + OAES_BLOCK_SIZE, _key_length ); - _rc = _rc || oaes_key_expand( ctx ); - - if( _rc != OAES_RET_SUCCESS ) - { - oaes_key_destroy( &(_ctx->key) ); - return _rc; - } - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_key_import_data( OAES_CTX * ctx, - const uint8_t * data, size_t data_len ) -{ - oaes_ctx * _ctx = (oaes_ctx *) ctx; - OAES_RET _rc = OAES_RET_SUCCESS; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == data ) - return OAES_RET_ARG2; - - switch( data_len ) - { - case 16: - case 24: - case 32: - break; - default: - return OAES_RET_ARG3; - } - - if( _ctx->key ) - oaes_key_destroy( &(_ctx->key) ); - - _ctx->key = (oaes_key *) calloc( sizeof( oaes_key ), 1 ); - - if( NULL == _ctx->key ) - return OAES_RET_MEM; - - _ctx->key->data_len = data_len; - _ctx->key->data = (uint8_t *) - calloc( data_len, sizeof( uint8_t )); - - if( NULL == _ctx->key->data ) - { - oaes_key_destroy( &(_ctx->key) ); - return OAES_RET_MEM; - } - - memcpy( _ctx->key->data, data, data_len ); - _rc = _rc || oaes_key_expand( ctx ); - - if( _rc != OAES_RET_SUCCESS ) - { - oaes_key_destroy( &(_ctx->key) ); - return _rc; - } - - return OAES_RET_SUCCESS; -} - -OAES_CTX * oaes_alloc() -{ - oaes_ctx * _ctx = (oaes_ctx *) calloc( sizeof( oaes_ctx ), 1 ); - - if( NULL == _ctx ) - return NULL; - -#ifdef OAES_HAVE_ISAAC - { - ub4 _i = 0; - char _seed[RANDSIZ + 1]; - - _ctx->rctx = (randctx *) calloc( sizeof( randctx ), 1 ); - - if( NULL == _ctx->rctx ) - { - free( _ctx ); - return NULL; - } - - oaes_get_seed( _seed ); - memset( _ctx->rctx->randrsl, 0, RANDSIZ ); - memcpy( _ctx->rctx->randrsl, _seed, RANDSIZ ); - randinit( _ctx->rctx, TRUE); - } -#else - //srand( oaes_get_seed() ); -#endif // OAES_HAVE_ISAAC - - _ctx->key = NULL; - oaes_set_option( _ctx, OAES_OPTION_CBC, NULL ); - -#ifdef OAES_DEBUG - _ctx->step_cb = NULL; - oaes_set_option( _ctx, OAES_OPTION_STEP_OFF, NULL ); -#endif // OAES_DEBUG - - return (OAES_CTX *) _ctx; -} - -OAES_RET oaes_free( OAES_CTX ** ctx ) -{ - oaes_ctx ** _ctx = (oaes_ctx **) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == *_ctx ) - return OAES_RET_SUCCESS; - - if( (*_ctx)->key ) - oaes_key_destroy( &((*_ctx)->key) ); - -#ifdef OAES_HAVE_ISAAC - if( (*_ctx)->rctx ) - { - free( (*_ctx)->rctx ); - (*_ctx)->rctx = NULL; - } -#endif // OAES_HAVE_ISAAC - - free( *_ctx ); - *_ctx = NULL; - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_set_option( OAES_CTX * ctx, - OAES_OPTION option, const void * value ) -{ - size_t _i; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - switch( option ) - { - case OAES_OPTION_ECB: - _ctx->options &= ~OAES_OPTION_CBC; - memset( _ctx->iv, 0, OAES_BLOCK_SIZE ); - break; - - case OAES_OPTION_CBC: - _ctx->options &= ~OAES_OPTION_ECB; - if( value ) - memcpy( _ctx->iv, value, OAES_BLOCK_SIZE ); - else - { - for( _i = 0; _i < OAES_BLOCK_SIZE; _i++ ) - _ctx->iv[_i] = (uint8_t) OAES_RAND(_ctx->rctx); - } - break; - -#ifdef OAES_DEBUG - - case OAES_OPTION_STEP_ON: - if( value ) - { - _ctx->options &= ~OAES_OPTION_STEP_OFF; - _ctx->step_cb = value; - } - else - { - _ctx->options &= ~OAES_OPTION_STEP_ON; - _ctx->options |= OAES_OPTION_STEP_OFF; - _ctx->step_cb = NULL; - return OAES_RET_ARG3; - } - break; - - case OAES_OPTION_STEP_OFF: - _ctx->options &= ~OAES_OPTION_STEP_ON; - _ctx->step_cb = NULL; - break; - -#endif // OAES_DEBUG - - default: - return OAES_RET_ARG2; - } - - _ctx->options |= option; - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_encrypt_block( - OAES_CTX * ctx, uint8_t * c, size_t c_len ) -{ - size_t _i, _j; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == c ) - return OAES_RET_ARG2; - - if( c_len != OAES_BLOCK_SIZE ) - return OAES_RET_ARG3; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "input", 1, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(State, K0) - for( _i = 0; _i < c_len; _i++ ) - c[_i] = c[_i] ^ _ctx->key->exp_data[_i]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data, "k_sch", 1, NULL ); - _ctx->step_cb( c, "k_add", 1, NULL ); - } -#endif // OAES_DEBUG - - // for round = 1 step 1 to Nr–1 - for( _i = 1; _i < _ctx->key->num_keys - 1; _i++ ) - { - // SubBytes(state) - for( _j = 0; _j < c_len; _j++ ) - oaes_sub_byte( c + _j ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "s_box", _i, NULL ); -#endif // OAES_DEBUG - - // ShiftRows(state) - oaes_shift_rows( c ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "s_row", _i, NULL ); -#endif // OAES_DEBUG - - // MixColumns(state) - oaes_mix_cols( c ); - oaes_mix_cols( c + 4 ); - oaes_mix_cols( c + 8 ); - oaes_mix_cols( c + 12 ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "m_col", _i, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) - for( _j = 0; _j < c_len; _j++ ) - c[_j] = c[_j] ^ - _ctx->key->exp_data[_i * OAES_RKEY_LEN * OAES_COL_LEN + _j]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data + _i * OAES_RKEY_LEN * OAES_COL_LEN, - "k_sch", _i, NULL ); - _ctx->step_cb( c, "k_add", _i, NULL ); - } -#endif // OAES_DEBUG - - } - - // SubBytes(state) - for( _i = 0; _i < c_len; _i++ ) - oaes_sub_byte( c + _i ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "s_box", _ctx->key->num_keys - 1, NULL ); -#endif // OAES_DEBUG - - // ShiftRows(state) - oaes_shift_rows( c ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "s_row", _ctx->key->num_keys - 1, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) - for( _i = 0; _i < c_len; _i++ ) - c[_i] = c[_i] ^ _ctx->key->exp_data[ - ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN + _i ]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data + - ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN, - "k_sch", _ctx->key->num_keys - 1, NULL ); - _ctx->step_cb( c, "output", _ctx->key->num_keys - 1, NULL ); - } -#endif // OAES_DEBUG - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_decrypt_block( - OAES_CTX * ctx, uint8_t * c, size_t c_len ) -{ - size_t _i, _j; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == c ) - return OAES_RET_ARG2; - - if( c_len != OAES_BLOCK_SIZE ) - return OAES_RET_ARG3; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "iinput", _ctx->key->num_keys - 1, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) - for( _i = 0; _i < c_len; _i++ ) - c[_i] = c[_i] ^ _ctx->key->exp_data[ - ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN + _i ]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data + - ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN, - "ik_sch", _ctx->key->num_keys - 1, NULL ); - _ctx->step_cb( c, "ik_add", _ctx->key->num_keys - 1, NULL ); - } -#endif // OAES_DEBUG - - for( _i = _ctx->key->num_keys - 2; _i > 0; _i-- ) - { - // InvShiftRows(state) - oaes_inv_shift_rows( c ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "is_row", _i, NULL ); -#endif // OAES_DEBUG - - // InvSubBytes(state) - for( _j = 0; _j < c_len; _j++ ) - oaes_inv_sub_byte( c + _j ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "is_box", _i, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) - for( _j = 0; _j < c_len; _j++ ) - c[_j] = c[_j] ^ - _ctx->key->exp_data[_i * OAES_RKEY_LEN * OAES_COL_LEN + _j]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data + _i * OAES_RKEY_LEN * OAES_COL_LEN, - "ik_sch", _i, NULL ); - _ctx->step_cb( c, "ik_add", _i, NULL ); - } -#endif // OAES_DEBUG - - // InvMixColums(state) - oaes_inv_mix_cols( c ); - oaes_inv_mix_cols( c + 4 ); - oaes_inv_mix_cols( c + 8 ); - oaes_inv_mix_cols( c + 12 ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "im_col", _i, NULL ); -#endif // OAES_DEBUG - - } - - // InvShiftRows(state) - oaes_inv_shift_rows( c ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "is_row", 1, NULL ); -#endif // OAES_DEBUG - - // InvSubBytes(state) - for( _i = 0; _i < c_len; _i++ ) - oaes_inv_sub_byte( c + _i ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "is_box", 1, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(state, w[0, Nb-1]) - for( _i = 0; _i < c_len; _i++ ) - c[_i] = c[_i] ^ _ctx->key->exp_data[_i]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data, "ik_sch", 1, NULL ); - _ctx->step_cb( c, "ioutput", 1, NULL ); - } -#endif // OAES_DEBUG - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_encrypt( OAES_CTX * ctx, - const uint8_t * m, size_t m_len, uint8_t * c, size_t * c_len ) -{ - size_t _i, _j, _c_len_in, _c_data_len; - size_t _pad_len = m_len % OAES_BLOCK_SIZE == 0 ? - 0 : OAES_BLOCK_SIZE - m_len % OAES_BLOCK_SIZE; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - OAES_RET _rc = OAES_RET_SUCCESS; - uint8_t _flags = _pad_len ? OAES_FLAG_PAD : 0; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == m ) - return OAES_RET_ARG2; - - if( NULL == c_len ) - return OAES_RET_ARG5; - - _c_len_in = *c_len; - // data + pad - _c_data_len = m_len + _pad_len; - // header + iv + data + pad - *c_len = 2 * OAES_BLOCK_SIZE + m_len + _pad_len; - - if( NULL == c ) - return OAES_RET_SUCCESS; - - if( _c_len_in < *c_len ) - return OAES_RET_BUF; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - // fill with random data first - for( _i = 0; _i < OAES_BLOCK_SIZE; _i++ ) - c[_i] = (uint8_t) OAES_RAND(_ctx->rctx); - // header - memcpy(c + 6, &_ctx->options, sizeof(_ctx->options)); - memcpy(c + 8, &_flags, sizeof(_flags)); - // iv - memcpy(c + OAES_BLOCK_SIZE, _ctx->iv, OAES_BLOCK_SIZE ); - // data - memcpy(c + 2 * OAES_BLOCK_SIZE, m, m_len ); - - for( _i = 0; _i < _c_data_len; _i += OAES_BLOCK_SIZE ) - { - uint8_t _block[OAES_BLOCK_SIZE]; - size_t _block_size = min( m_len - _i, OAES_BLOCK_SIZE ); - - memcpy( _block, c + 2 * OAES_BLOCK_SIZE + _i, _block_size ); - - // insert pad - for( _j = 0; _j < OAES_BLOCK_SIZE - _block_size; _j++ ) - _block[ _block_size + _j ] = _j + 1; - - // CBC - if( _ctx->options & OAES_OPTION_CBC ) - { - for( _j = 0; _j < OAES_BLOCK_SIZE; _j++ ) - _block[_j] = _block[_j] ^ _ctx->iv[_j]; - } - - _rc = _rc || - oaes_encrypt_block( ctx, _block, OAES_BLOCK_SIZE ); - memcpy( c + 2 * OAES_BLOCK_SIZE + _i, _block, OAES_BLOCK_SIZE ); - - if( _ctx->options & OAES_OPTION_CBC ) - memcpy( _ctx->iv, _block, OAES_BLOCK_SIZE ); - } - - return _rc; -} - -OAES_RET oaes_decrypt( OAES_CTX * ctx, - const uint8_t * c, size_t c_len, uint8_t * m, size_t * m_len ) -{ - size_t _i, _j, _m_len_in; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - OAES_RET _rc = OAES_RET_SUCCESS; - uint8_t _iv[OAES_BLOCK_SIZE]; - uint8_t _flags; - OAES_OPTION _options; - - if( NULL == ctx ) - return OAES_RET_ARG1; - - if( NULL == c ) - return OAES_RET_ARG2; - - if( c_len % OAES_BLOCK_SIZE ) - return OAES_RET_ARG3; - - if( NULL == m_len ) - return OAES_RET_ARG5; - - _m_len_in = *m_len; - *m_len = c_len - 2 * OAES_BLOCK_SIZE; - - if( NULL == m ) - return OAES_RET_SUCCESS; - - if( _m_len_in < *m_len ) - return OAES_RET_BUF; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - // options - memcpy(&_options, c + 6, sizeof(_options)); - // validate that all options are valid - if( _options & ~( - OAES_OPTION_ECB - | OAES_OPTION_CBC -#ifdef OAES_DEBUG - | OAES_OPTION_STEP_ON - | OAES_OPTION_STEP_OFF -#endif // OAES_DEBUG - ) ) - return OAES_RET_HEADER; - if( ( _options & OAES_OPTION_ECB ) && - ( _options & OAES_OPTION_CBC ) ) - return OAES_RET_HEADER; - if( _options == OAES_OPTION_NONE ) - return OAES_RET_HEADER; - - // flags - memcpy(&_flags, c + 8, sizeof(_flags)); - // validate that all flags are valid - if( _flags & ~( - OAES_FLAG_PAD - ) ) - return OAES_RET_HEADER; - - // iv - memcpy( _iv, c + OAES_BLOCK_SIZE, OAES_BLOCK_SIZE); - // data + pad - memcpy( m, c + 2 * OAES_BLOCK_SIZE, *m_len ); - - for( _i = 0; _i < *m_len; _i += OAES_BLOCK_SIZE ) - { - if( ( _options & OAES_OPTION_CBC ) && _i > 0 ) - memcpy( _iv, c + OAES_BLOCK_SIZE + _i, OAES_BLOCK_SIZE ); - - _rc = _rc || - oaes_decrypt_block( ctx, m + _i, min( *m_len - _i, OAES_BLOCK_SIZE ) ); - - // CBC - if( _options & OAES_OPTION_CBC ) - { - for( _j = 0; _j < OAES_BLOCK_SIZE; _j++ ) - m[ _i + _j ] = m[ _i + _j ] ^ _iv[_j]; - } - } - - // remove pad - if( _flags & OAES_FLAG_PAD ) - { - int _is_pad = 1; - size_t _temp = (size_t) m[*m_len - 1]; - - if( _temp <= 0x00 || _temp > 0x0f ) - return OAES_RET_HEADER; - for( _i = 0; _i < _temp; _i++ ) - if( m[*m_len - 1 - _i] != _temp - _i ) - _is_pad = 0; - if( _is_pad ) - { - memset( m + *m_len - _temp, 0, _temp ); - *m_len -= _temp; - } - else - return OAES_RET_HEADER; - } - - return OAES_RET_SUCCESS; -} diff --git a/media/gmp-clearkey/0.1/openaes/oaes_lib.h b/media/gmp-clearkey/0.1/openaes/oaes_lib.h deleted file mode 100644 index 2344480e85..0000000000 --- a/media/gmp-clearkey/0.1/openaes/oaes_lib.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * OpenAES License - * --------------------------------------------------------------------------- - * Copyright (c) 2013, Nabil S. Al Ramli, www.nalramli.com - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * --------------------------------------------------------------------------- - */ - -#ifndef _OAES_LIB_H -#define _OAES_LIB_H - -#include "oaes_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 -# ifdef OAES_SHARED -# ifdef oaes_lib_EXPORTS -# define OAES_API __declspec(dllexport) -# else -# define OAES_API __declspec(dllimport) -# endif -# else -# define OAES_API -# endif -#else -# define OAES_API -#endif // WIN32 - -#define OAES_BLOCK_SIZE 16 - -typedef void OAES_CTX; - -/* - * oaes_set_option() takes one of these values for its [option] parameter - * some options accept either an optional or a required [value] parameter - */ -// no option -#define OAES_OPTION_NONE 0 -// enable ECB mode, disable CBC mode -#define OAES_OPTION_ECB 1 -// enable CBC mode, disable ECB mode -// value is optional, may pass uint8_t iv[OAES_BLOCK_SIZE] to specify -// the value of the initialization vector, iv -#define OAES_OPTION_CBC 2 - -#ifdef OAES_DEBUG -typedef int ( * oaes_step_cb ) ( - const uint8_t state[OAES_BLOCK_SIZE], - const char * step_name, - int step_count, - void * user_data ); -// enable state stepping mode -// value is required, must pass oaes_step_cb to receive the state at each step -#define OAES_OPTION_STEP_ON 4 -// disable state stepping mode -#define OAES_OPTION_STEP_OFF 8 -#endif // OAES_DEBUG - -typedef uint16_t OAES_OPTION; - -/* - * // usage: - * - * OAES_CTX * ctx = oaes_alloc(); - * . - * . - * . - * { - * oaes_gen_key_xxx( ctx ); - * { - * oaes_key_export( ctx, _buf, &_buf_len ); - * // or - * oaes_key_export_data( ctx, _buf, &_buf_len );\ - * } - * } - * // or - * { - * oaes_key_import( ctx, _buf, _buf_len ); - * // or - * oaes_key_import_data( ctx, _buf, _buf_len ); - * } - * . - * . - * . - * oaes_encrypt( ctx, m, m_len, c, &c_len ); - * . - * . - * . - * oaes_decrypt( ctx, c, c_len, m, &m_len ); - * . - * . - * . - * oaes_free( &ctx ); - */ - -OAES_API OAES_CTX * oaes_alloc(); - -OAES_API OAES_RET oaes_free( OAES_CTX ** ctx ); - -OAES_API OAES_RET oaes_set_option( OAES_CTX * ctx, - OAES_OPTION option, const void * value ); - -OAES_API OAES_RET oaes_key_gen_128( OAES_CTX * ctx ); - -OAES_API OAES_RET oaes_key_gen_192( OAES_CTX * ctx ); - -OAES_API OAES_RET oaes_key_gen_256( OAES_CTX * ctx ); - -// export key with header information -// set data == NULL to get the required data_len -OAES_API OAES_RET oaes_key_export( OAES_CTX * ctx, - uint8_t * data, size_t * data_len ); - -// directly export the data from key -// set data == NULL to get the required data_len -OAES_API OAES_RET oaes_key_export_data( OAES_CTX * ctx, - uint8_t * data, size_t * data_len ); - -// import key with header information -OAES_API OAES_RET oaes_key_import( OAES_CTX * ctx, - const uint8_t * data, size_t data_len ); - -// directly import data into key -OAES_API OAES_RET oaes_key_import_data( OAES_CTX * ctx, - const uint8_t * data, size_t data_len ); - -// set c == NULL to get the required c_len -OAES_API OAES_RET oaes_encrypt( OAES_CTX * ctx, - const uint8_t * m, size_t m_len, uint8_t * c, size_t * c_len ); - -// set m == NULL to get the required m_len -OAES_API OAES_RET oaes_decrypt( OAES_CTX * ctx, - const uint8_t * c, size_t c_len, uint8_t * m, size_t * m_len ); - -// set buf == NULL to get the required buf_len -OAES_API OAES_RET oaes_sprintf( - char * buf, size_t * buf_len, const uint8_t * data, size_t data_len ); - -#ifdef __cplusplus -} -#endif - -#endif // _OAES_LIB_H diff --git a/media/gmp-clearkey/0.1/openaes/standard.h b/media/gmp-clearkey/0.1/openaes/standard.h deleted file mode 100644 index fbe6ef5bef..0000000000 --- a/media/gmp-clearkey/0.1/openaes/standard.h +++ /dev/null @@ -1,57 +0,0 @@ -/* ------------------------------------------------------------------------------- -Standard definitions and types, Bob Jenkins ------------------------------------------------------------------------------- -*/ -#ifndef STANDARD -# define STANDARD -# ifndef STDIO -# include <stdio.h> -# define STDIO -# endif -# ifndef STDDEF -# include <stddef.h> -# define STDDEF -# endif -typedef unsigned long long ub8; -#define UB8MAXVAL 0xffffffffffffffffLL -#define UB8BITS 64 -typedef signed long long sb8; -#define SB8MAXVAL 0x7fffffffffffffffLL -typedef unsigned long int ub4; /* unsigned 4-byte quantities */ -#define UB4MAXVAL 0xffffffff -typedef signed long int sb4; -#define UB4BITS 32 -#define SB4MAXVAL 0x7fffffff -typedef unsigned short int ub2; -#define UB2MAXVAL 0xffff -#define UB2BITS 16 -typedef signed short int sb2; -#define SB2MAXVAL 0x7fff -typedef unsigned char ub1; -#define UB1MAXVAL 0xff -#define UB1BITS 8 -typedef signed char sb1; /* signed 1-byte quantities */ -#define SB1MAXVAL 0x7f -typedef int word; /* fastest type available */ - -#define bis(target,mask) ((target) |= (mask)) -#define bic(target,mask) ((target) &= ~(mask)) -#define bit(target,mask) ((target) & (mask)) -// #ifndef min -// # define min(a,b) (((a)<(b)) ? (a) : (b)) -// #endif /* min */ -// #ifndef max -// # define max(a,b) (((a)<(b)) ? (b) : (a)) -// #endif /* max */ -#ifndef align -# define align(a) (((ub4)a+(sizeof(void *)-1))&(~(sizeof(void *)-1))) -#endif /* align */ -// #ifndef abs -// # define abs(a) (((a)>0) ? (a) : -(a)) -// #endif -#define TRUE 1 -#define FALSE 0 -#define SUCCESS 0 /* 1 on VAX */ - -#endif /* STANDARD */ diff --git a/old-configure.in b/old-configure.in index ac11e93595..aa1750ec90 100644 --- a/old-configure.in +++ b/old-configure.in @@ -2724,10 +2724,6 @@ dnl ======================================================== dnl = Enable Gecko Media Plugins dnl ======================================================== -if test -n "$MOZ_EME"; then - MOZ_GMP=1 -fi - if test -n "$MOZ_WEBRTC"; then MOZ_GMP=1 fi @@ -2794,25 +2790,6 @@ if test -n "$MOZ_APPLEMEDIA"; then fi fi # COMPILE_ENVIRONMENT -dnl ======================================================== -dnl = EME support -dnl ======================================================== - -MOZ_ARG_ENABLE_BOOL(eme, -[ --enable-eme Enable support for Encrypted Media Extensions ], - MOZ_EME=1, - MOZ_EME=) - - -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 - -AC_SUBST(MOZ_EME) - MOZ_LIBVPX_CFLAGS= MOZ_LIBVPX_LIBS= diff --git a/toolkit/content/license.html b/toolkit/content/license.html index 0de306f36e..9075fe5f28 100644 --- a/toolkit/content/license.html +++ b/toolkit/content/license.html @@ -135,9 +135,6 @@ #ifdef MOZ_WEBRTC <li><a href="about:license#nrappkit">nrappkit License</a></li> #endif -#ifdef MOZ_EME - <li><a href="about:license#openaes">OpenAES License</a></li> -#endif <li><a href="about:license#openvision">OpenVision License</a></li> <li><a href="about:license#praton">praton License</a></li> <li><a href="about:license#qcms">qcms License</a></li> @@ -3974,42 +3971,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. <hr> #endif -#ifdef MOZ_EME - <h1><a id="openaes"></a>OpenAES License</h1> - - <p>This license applies to certain files in the directory - <span class="path">media/gmp-clearkey/0.1/openaes</span>. - </p> - -<pre> -Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -</pre> - - - <hr> -#endif <h1><a id="openvision"></a>OpenVision License</h1> diff --git a/toolkit/forgetaboutsite/ForgetAboutSite.jsm b/toolkit/forgetaboutsite/ForgetAboutSite.jsm index af3572bb24..f2f4cd58e1 100644 --- a/toolkit/forgetaboutsite/ForgetAboutSite.jsm +++ b/toolkit/forgetaboutsite/ForgetAboutSite.jsm @@ -84,17 +84,6 @@ this.ForgetAboutSite = { throw new Error("Exception thrown while clearning cookies: " + ex); })); -#ifdef MOZ_EME - // EME - promises.push(Task.spawn(function*() { - let mps = Cc["@mozilla.org/gecko-media-plugin-service;1"]. - getService(Ci.mozIGeckoMediaPluginChromeService); - mps.forgetThisSite(aDomain, JSON.stringify({})); - }).catch(ex => { - throw new Error("Exception thrown while clearing Encrypted Media Extensions: " + ex); - })); -#endif - // Plugin data const phInterface = Ci.nsIPluginHost; const FLAG_CLEAR_ALL = phInterface.FLAG_CLEAR_ALL; diff --git a/toolkit/mozapps/extensions/GMPInstallManager.jsm b/toolkit/mozapps/extensions/GMPInstallManager.jsm index fe4e2de103..b7060e7908 100644 --- a/toolkit/mozapps/extensions/GMPInstallManager.jsm +++ b/toolkit/mozapps/extensions/GMPInstallManager.jsm @@ -302,9 +302,6 @@ GMPInstallManager.prototype = { } return now - lastCheck; }, - get _isEMEEnabled() { - return GMPPrefs.get(GMPPrefs.KEY_EME_ENABLED, true); - }, _isAddonUpdateEnabled: function(aAddon) { return GMPPrefs.get(GMPPrefs.KEY_PLUGIN_ENABLED, true, aAddon) && GMPPrefs.get(GMPPrefs.KEY_PLUGIN_AUTOUPDATE, true, aAddon); diff --git a/toolkit/mozapps/extensions/GMPUtils.jsm b/toolkit/mozapps/extensions/GMPUtils.jsm index 3c691610d5..f1c7e86c88 100644 --- a/toolkit/mozapps/extensions/GMPUtils.jsm +++ b/toolkit/mozapps/extensions/GMPUtils.jsm @@ -53,10 +53,6 @@ this.GMPUtils = { return true; } - if (!GMPPrefs.get(GMPPrefs.KEY_EME_ENABLED, true)) { - return true; - } - return false; }, @@ -118,7 +114,6 @@ this.GMPUtils = { * Manages preferences for GMP addons */ this.GMPPrefs = { - KEY_EME_ENABLED: "media.eme.enabled", KEY_PLUGIN_ENABLED: "media.{0}.enabled", KEY_PLUGIN_LAST_UPDATE: "media.{0}.lastUpdate", KEY_PLUGIN_VERSION: "media.{0}.version", diff --git a/toolkit/mozapps/extensions/internal/GMPProvider.jsm b/toolkit/mozapps/extensions/internal/GMPProvider.jsm index c894271018..1ecd97aa97 100644 --- a/toolkit/mozapps/extensions/internal/GMPProvider.jsm +++ b/toolkit/mozapps/extensions/internal/GMPProvider.jsm @@ -28,7 +28,7 @@ const URI_EXTENSION_STRINGS = "chrome://mozapps/locale/extensions/extensions.pr const STRING_TYPE_NAME = "type.%ID%.name"; const SEC_IN_A_DAY = 24 * 60 * 60; -// How long to wait after a user enabled EME before attempting to download CDMs. +// How long to wait before attempting to download GMPs. const GMP_CHECK_DELAY = 10 * 1000; // milliseconds const NS_GRE_DIR = "GreD"; @@ -48,16 +48,6 @@ const GMP_PLUGINS = [ licenseURL: "chrome://mozapps/content/extensions/OpenH264-license.txt", homepageURL: "http://www.openh264.org/", optionsURL: "chrome://mozapps/content/extensions/gmpPrefs.xul" - }, - { - id: WIDEVINE_ID, - name: "widevine_name", - // Describe the purpose of both CDMs in the same way. - description: "widevine_description2", - licenseURL: "https://www.google.com/policies/privacy/", - homepageURL: "https://www.widevine.com/", - optionsURL: "chrome://mozapps/content/extensions/gmpPrefs.xul", - isEME: true }]; XPCOMUtils.defineConstant(this, "GMP_PLUGINS", GMP_PLUGINS); @@ -109,11 +99,6 @@ function GMPWrapper(aPluginInfo) { Preferences.observe(GMPPrefs.getPrefKey(GMPPrefs.KEY_PLUGIN_VERSION, this._plugin.id), this.onPrefVersionChanged, this); - if (this._plugin.isEME) { - Preferences.observe(GMPPrefs.KEY_EME_ENABLED, - this.onPrefEMEGlobalEnabledChanged, this); - messageManager.addMessageListener("EMEVideo:ContentMediaKeysRequest", this); - } } GMPWrapper.prototype = { @@ -149,14 +134,7 @@ GMPWrapper.prototype = { get version() { return GMPPrefs.get(GMPPrefs.KEY_PLUGIN_VERSION, null, this._plugin.id); }, - get isActive() { return !this.appDisabled && !this.userDisabled; }, - get appDisabled() { - if (this._plugin.isEME && !GMPPrefs.get(GMPPrefs.KEY_EME_ENABLED, true)) { - // If "media.eme.enabled" is false, all EME plugins are disabled. - return true; - } - return false; - }, + get isActive() { return !this.userDisabled; }, get userDisabled() { return !GMPPrefs.get(GMPPrefs.KEY_PLUGIN_ENABLED, true, this._plugin.id); @@ -386,7 +364,7 @@ GMPWrapper.prototype = { }, onPrefEnabledChanged: function() { - if (!this._plugin.isEME || !this.appDisabled) { + if (!this._plugin.isEME) { this._handleEnabledChanged(); } }, @@ -436,11 +414,6 @@ GMPWrapper.prototype = { Preferences.ignore(GMPPrefs.getPrefKey(GMPPrefs.KEY_PLUGIN_VERSION, this._plugin.id), this.onPrefVersionChanged, this); - if (this._plugin.isEME) { - Preferences.ignore(GMPPrefs.KEY_EME_ENABLED, - this.onPrefEMEGlobalEnabledChanged, this); - messageManager.removeMessageListener("EMEVideo:ContentMediaKeysRequest", this); - } return this._updateTask; }, }; @@ -476,21 +449,6 @@ var GMPProvider = { } } } - - if (Preferences.get(GMPPrefs.KEY_EME_ENABLED, false)) { - try { - let greDir = Services.dirsvc.get(NS_GRE_DIR, - Ci.nsILocalFile); - let clearkeyPath = OS.Path.join(greDir.path, - CLEARKEY_PLUGIN_ID, - CLEARKEY_VERSION); - this._log.info("startup - adding clearkey CDM directory " + - clearkeyPath); - gmpService.addPluginDirectory(clearkeyPath); - } catch (e) { - this._log.warn("startup - adding clearkey CDM failed", e); - } - } }, shutdown: function() { @@ -586,12 +544,11 @@ var GMPProvider = { }, ensureProperCDMInstallState: function() { - if (!GMPPrefs.get(GMPPrefs.KEY_EME_ENABLED, true)) { - for (let [id, plugin] of this._plugins) { - if (plugin.isEME && plugin.wrapper.isInstalled) { - gmpService.addPluginDirectory(plugin.wrapper.gmpPath); - plugin.wrapper.uninstallPlugin(); - } + // This removes disabled EME CDM plugins + for (let [id, plugin] of this._plugins) { + if (plugin.isEME && plugin.wrapper.isInstalled) { + gmpService.addPluginDirectory(plugin.wrapper.gmpPath); + plugin.wrapper.uninstallPlugin(); } } }, diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild index bb5cac7cba..7ba79b11be 100644 --- a/toolkit/toolkit.mozbuild +++ b/toolkit/toolkit.mozbuild @@ -135,11 +135,6 @@ DIRS += [ '/tools/quitter', ] -if CONFIG['MOZ_EME']: - DIRS += [ - '/media/gmp-clearkey/0.1', - ] - if CONFIG['ENABLE_TESTS']: DIRS += [ '/testing/mochitest', |