From cf178171a4c459326eb4898533e2076479e41912 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Thu, 5 Oct 2023 16:47:30 -0400 Subject: Issue #2332 - Refactor code that feeds video stream sink when it gets added https://bugzilla.mozilla.org/show_bug.cgi?id=1305949 part 1 --- dom/media/MediaStreamGraph.cpp | 68 +++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/dom/media/MediaStreamGraph.cpp b/dom/media/MediaStreamGraph.cpp index db5fa8fa39..d0f23afaef 100644 --- a/dom/media/MediaStreamGraph.cpp +++ b/dom/media/MediaStreamGraph.cpp @@ -2869,8 +2869,8 @@ SourceMediaStream::AddDirectTrackListenerImpl(already_AddRefed listener = aListener; @@ -2879,44 +2879,30 @@ SourceMediaStream::AddDirectTrackListenerImpl(already_AddRefedmData->GetType() == MediaSegment::AUDIO; - isVideo = data->mData->GetType() == MediaSegment::VIDEO; - } - - // The track might be removed from mUpdateTrack but still exist in - // mTracks. - auto streamTrack = FindTrack(aTrackID); - bool foundTrack = !!streamTrack; - if (foundTrack) { - MediaStreamVideoSink* videoSink = listener->AsMediaStreamVideoSink(); + updateData = FindDataForTrack(aTrackID); + track = FindTrack(aTrackID); + if (track) { + isAudio = track->GetType() == MediaSegment::AUDIO; + isVideo = track->GetType() == MediaSegment::VIDEO; + } + + MediaStreamVideoSink* videoSink = listener->AsMediaStreamVideoSink(); + if (track && isVideo && videoSink) { // Re-send missed VideoSegment to new added MediaStreamVideoSink. - if (streamTrack->GetType() == MediaSegment::VIDEO && videoSink) { - VideoSegment videoSegment; - if (mTracks.GetForgottenDuration() < streamTrack->GetSegment()->GetDuration()) { - videoSegment.AppendSlice(*streamTrack->GetSegment(), - mTracks.GetForgottenDuration(), - streamTrack->GetSegment()->GetDuration()); - } else { - VideoSegment* streamTrackSegment = static_cast(streamTrack->GetSegment()); - VideoChunk* lastChunk = streamTrackSegment->GetLastChunk(); - if (lastChunk) { - StreamTime startTime = streamTrackSegment->GetDuration() - lastChunk->GetDuration(); - videoSegment.AppendSlice(*streamTrackSegment, - startTime, - streamTrackSegment->GetDuration()); - } - } - if (found) { - videoSegment.AppendSlice(*data->mData, 0, data->mData->GetDuration()); - } - videoSink->SetCurrentFrames(videoSegment); + VideoSegment* trackSegment = static_cast(track->GetSegment()); + VideoSegment videoSegment; + if (mTracks.GetForgottenDuration() < trackSegment->GetDuration()) { + videoSegment.AppendSlice(*trackSegment, + mTracks.GetForgottenDuration(), + trackSegment->GetDuration()); + } + if (updateData) { + videoSegment.AppendSlice(*updateData->mData, 0, updateData->mData->GetDuration()); } + videoSink->SetCurrentFrames(videoSegment); } - if (found && (isAudio || isVideo)) { + if (track && (isAudio || isVideo)) { for (auto entry : mDirectTrackListeners) { if (entry.mListener == listener && (entry.mTrackID == TRACK_ANY || entry.mTrackID == aTrackID)) { @@ -2932,7 +2918,7 @@ SourceMediaStream::AddDirectTrackListenerImpl(already_AddRefedmTrackID = aTrackID; } } - if (!found) { + if (!track) { STREAM_LOG(LogLevel::Warning, ("Couldn't find source track for direct track listener %p", listener.get())); listener->NotifyDirectListenerInstalled( @@ -2946,9 +2932,15 @@ SourceMediaStream::AddDirectTrackListenerImpl(already_AddRefedNotifyDirectListenerInstalled( DirectMediaStreamTrackListener::InstallationResult::SUCCESS); + if (!updateData) { + // The track exists but the mUpdateTracks entry was removed. + // This means that the track has ended. + listener->NotifyEnded(); + } } void -- cgit v1.2.3 From 8698518416d9fbb8f92e740a418a230e9d1189bd Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Thu, 5 Oct 2023 16:48:52 -0400 Subject: Issue #2332 - Use the same path for passing on missed data to video sink, as during normal operation https://bugzilla.mozilla.org/show_bug.cgi?id=1305949 part 2 --- dom/media/MediaStreamGraph.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dom/media/MediaStreamGraph.cpp b/dom/media/MediaStreamGraph.cpp index d0f23afaef..355261525c 100644 --- a/dom/media/MediaStreamGraph.cpp +++ b/dom/media/MediaStreamGraph.cpp @@ -2886,8 +2886,7 @@ SourceMediaStream::AddDirectTrackListenerImpl(already_AddRefedGetType() == MediaSegment::VIDEO; } - MediaStreamVideoSink* videoSink = listener->AsMediaStreamVideoSink(); - if (track && isVideo && videoSink) { + if (track && isVideo && listener->AsMediaStreamVideoSink()) { // Re-send missed VideoSegment to new added MediaStreamVideoSink. VideoSegment* trackSegment = static_cast(track->GetSegment()); VideoSegment videoSegment; @@ -2899,7 +2898,7 @@ SourceMediaStream::AddDirectTrackListenerImpl(already_AddRefedmData, 0, updateData->mData->GetDuration()); } - videoSink->SetCurrentFrames(videoSegment); + listener->NotifyRealtimeTrackData(Graph(), 0, videoSegment); } if (track && (isAudio || isVideo)) { -- cgit v1.2.3 From ecc90c09ef4cfdf8a45d5ec17f0069120488e4e9 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Thu, 5 Oct 2023 16:51:40 -0400 Subject: Issue #2332 - Use only one listener in MediaPipelineTransmit https://bugzilla.mozilla.org/show_bug.cgi?id=1305949 part 3 --- .../signaling/src/mediapipeline/MediaPipeline.cpp | 120 +++++++-------------- .../signaling/src/mediapipeline/MediaPipeline.h | 2 - media/webrtc/signaling/test/FakeMediaStreams.h | 3 +- 3 files changed, 40 insertions(+), 85 deletions(-) diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp index d47a103122..374467b633 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp @@ -1205,7 +1205,7 @@ void MediaPipeline::PacketReceived(TransportLayer *layer, } class MediaPipelineTransmit::PipelineListener - : public DirectMediaStreamTrackListener + : public MediaStreamVideoSink { friend class MediaPipelineTransmit; public: @@ -1293,15 +1293,17 @@ public: void NotifyDirectListenerInstalled(InstallationResult aResult) override; void NotifyDirectListenerUninstalled() override; + // Implement MediaStreamVideoSink + void SetCurrentFrames(const VideoSegment& aSegment) override; + void ClearFrames() override {} + private: void UnsetTrackIdImpl() { MutexAutoLock lock(mMutex); track_id_ = track_id_external_ = TRACK_INVALID; } - void NewData(MediaStreamGraph* graph, - StreamTime offset, - const MediaSegment& media); + void NewData(const MediaSegment& media, TrackRate aRate = 0); RefPtr conduit_; RefPtr audio_processing_; @@ -1390,34 +1392,6 @@ protected: }; #endif -class MediaPipelineTransmit::PipelineVideoSink : - public MediaStreamVideoSink -{ -public: - explicit PipelineVideoSink(const RefPtr& conduit, - MediaPipelineTransmit::PipelineListener* listener) - : conduit_(conduit) - , pipelineListener_(listener) - { - } - - virtual void SetCurrentFrames(const VideoSegment& aSegment) override; - virtual void ClearFrames() override {} - -private: - ~PipelineVideoSink() { - // release conduit on mainthread. Must use forget()! - nsresult rv = NS_DispatchToMainThread(new - ConduitDeleteEvent(conduit_.forget())); - MOZ_ASSERT(!NS_FAILED(rv),"Could not dispatch conduit shutdown to main"); - if (NS_FAILED(rv)) { - MOZ_CRASH(); - } - } - RefPtr conduit_; - MediaPipelineTransmit::PipelineListener* pipelineListener_; -}; - MediaPipelineTransmit::MediaPipelineTransmit( const std::string& pc, nsCOMPtr main_thread, @@ -1432,7 +1406,6 @@ MediaPipelineTransmit::MediaPipelineTransmit( MediaPipeline(pc, TRANSMIT, main_thread, sts_thread, track_id, level, conduit, rtp_transport, rtcp_transport, filter), listener_(new PipelineListener(conduit)), - video_sink_(new PipelineVideoSink(conduit, listener_)), domtrack_(domtrack) { if (!IsVideo()) { @@ -1490,10 +1463,6 @@ void MediaPipelineTransmit::AttachToTrack(const std::string& track_id) { domtrack_->AddDirectListener(listener_); domtrack_->AddListener(listener_); -#if !defined(MOZILLA_EXTERNAL_LINKAGE) - domtrack_->AddDirectListener(video_sink_); -#endif - #ifndef MOZILLA_INTERNAL_API // this enables the unit tests that can't fiddle with principals and the like listener_->SetEnabled(true); @@ -1542,7 +1511,6 @@ MediaPipelineTransmit::DetachMedia() if (domtrack_) { domtrack_->RemoveDirectListener(listener_); domtrack_->RemoveListener(listener_); - domtrack_->RemoveDirectListener(video_sink_); domtrack_ = nullptr; } // Let the listener be destroyed with the pipeline (or later). @@ -1747,7 +1715,14 @@ NotifyRealtimeTrackData(MediaStreamGraph* graph, this << ", offset=" << offset << ", duration=" << media.GetDuration()); - NewData(graph, offset, media); + if (media.GetType() == MediaSegment::VIDEO) { + // We have to call the upstream NotifyRealtimeTrackData and + // MediaStreamVideoSink will route them to SetCurrentFrames. + MediaStreamVideoSink::NotifyRealtimeTrackData(graph, offset, media); + return; + } + + NewData(media, graph->GraphRate()); } void MediaPipelineTransmit::PipelineListener:: @@ -1756,10 +1731,17 @@ NotifyQueuedChanges(MediaStreamGraph* graph, const MediaSegment& queued_media) { MOZ_MTLOG(ML_DEBUG, "MediaPipeline::NotifyQueuedChanges()"); - // ignore non-direct data if we're also getting direct data - if (!direct_connect_) { - NewData(graph, offset, queued_media); + if (queued_media.GetType() == MediaSegment::VIDEO) { + // We always get video from SetCurrentFrames(). + return; } + + if (direct_connect_) { + // ignore non-direct data if we're also getting direct data + return; + } + + NewData(queued_media, graph->GraphRate()); } void MediaPipelineTransmit::PipelineListener:: @@ -1778,9 +1760,7 @@ NotifyDirectListenerUninstalled() { } void MediaPipelineTransmit::PipelineListener:: -NewData(MediaStreamGraph* graph, - StreamTime offset, - const MediaSegment& media) { +NewData(const MediaSegment& media, TrackRate aRate /* = 0 */) { if (!active_) { MOZ_MTLOG(ML_DEBUG, "Discarding packets because transport not ready"); return; @@ -1798,49 +1778,27 @@ NewData(MediaStreamGraph* graph, // track type and it's destined for us // See bug 784517 if (media.GetType() == MediaSegment::AUDIO) { - AudioSegment* audio = const_cast( - static_cast(&media)); - - AudioSegment::ChunkIterator iter(*audio); - while(!iter.IsEnded()) { - TrackRate rate; -#ifdef USE_FAKE_MEDIA_STREAMS - rate = Fake_MediaStream::GraphRate(); -#else - rate = graph->GraphRate(); -#endif - audio_processing_->QueueAudioChunk(rate, *iter, enabled_); - iter.Next(); + MOZ_RELEASE_ASSERT(aRate > 0); + + AudioSegment* audio = const_cast(static_cast(&media)); + for(AudioSegment::ChunkIterator iter(*audio); !iter.IsEnded(); iter.Next()) { + audio_processing_->QueueAudioChunk(aRate, *iter, enabled_); } +#if !defined(MOZILLA_EXTERNAL_LINKAGE) } else { - // Ignore + VideoSegment* video = const_cast(static_cast(&media)); + VideoSegment::ChunkIterator iter(*video); + for(VideoSegment::ChunkIterator iter(*video); !iter.IsEnded(); iter.Next()) { + converter_->QueueVideoChunk(*iter, !enabled_); + } +#endif // MOZILLA_EXTERNAL_LINKAGE } } -void MediaPipelineTransmit::PipelineVideoSink:: +void MediaPipelineTransmit::PipelineListener:: SetCurrentFrames(const VideoSegment& aSegment) { - MOZ_ASSERT(pipelineListener_); - - if (!pipelineListener_->active_) { - MOZ_MTLOG(ML_DEBUG, "Discarding packets because transport not ready"); - return; - } - - if (conduit_->type() != MediaSessionConduit::VIDEO) { - // Ignore data of wrong kind in case we have a muxed stream - return; - } - -#if !defined(MOZILLA_EXTERNAL_LINKAGE) - VideoSegment* video = const_cast(&aSegment); - - VideoSegment::ChunkIterator iter(*video); - while(!iter.IsEnded()) { - pipelineListener_->converter_->QueueVideoChunk(*iter, !pipelineListener_->enabled_); - iter.Next(); - } -#endif + NewData(aSegment); } class TrackAddedCallback { diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h index 00333b789d..919c28f23b 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h @@ -345,7 +345,6 @@ public: // Separate classes to allow ref counting class PipelineListener; class VideoFrameFeeder; - class PipelineVideoSink; protected: ~MediaPipelineTransmit(); @@ -357,7 +356,6 @@ public: RefPtr feeder_; RefPtr converter_; #endif - RefPtr video_sink_; dom::MediaStreamTrack* domtrack_; }; diff --git a/media/webrtc/signaling/test/FakeMediaStreams.h b/media/webrtc/signaling/test/FakeMediaStreams.h index 117d269055..0325bb700b 100644 --- a/media/webrtc/signaling/test/FakeMediaStreams.h +++ b/media/webrtc/signaling/test/FakeMediaStreams.h @@ -70,6 +70,7 @@ public: gGraph = new MediaStreamGraph(); return gGraph; } + uint32_t GraphRate() { return 16000; } }; } @@ -186,8 +187,6 @@ class Fake_MediaStream { public: Fake_MediaStream () : mListeners(), mTrackListeners(), mMutex("Fake MediaStream") {} - static uint32_t GraphRate() { return 16000; } - void AddListener(Fake_MediaStreamListener *aListener) { mozilla::MutexAutoLock lock(mMutex); mListeners.insert(aListener); -- cgit v1.2.3 From 8f6d5c5ba0ea0db56e4aba45a1da4df615c9ad49 Mon Sep 17 00:00:00 2001 From: Matheus Marinho Date: Fri, 6 Oct 2023 23:04:36 -0300 Subject: Correct overzealous GMP checks --- toolkit/xre/nsEmbedFunctions.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/toolkit/xre/nsEmbedFunctions.cpp b/toolkit/xre/nsEmbedFunctions.cpp index bedd7c9914..8235963f05 100644 --- a/toolkit/xre/nsEmbedFunctions.cpp +++ b/toolkit/xre/nsEmbedFunctions.cpp @@ -451,11 +451,9 @@ XRE_InitChildProcess(int aArgc, // Content processes need the XPCOM/chromium frankenventloop uiLoopType = MessageLoop::TYPE_MOZILLA_CHILD; break; -#ifdef MOZ_GMP case GeckoProcessType_GMPlugin: uiLoopType = MessageLoop::TYPE_DEFAULT; break; -#endif default: uiLoopType = MessageLoop::TYPE_UI; break; @@ -517,11 +515,13 @@ XRE_InitChildProcess(int aArgc, #endif break; -#ifdef MOZ_GMP case GeckoProcessType_GMPlugin: +#ifdef MOZ_GMP process = new gmp::GMPProcessChild(parentPID); - break; +#else + NS_RUNTIMEABORT("rebuild with Gecko Media Plugins enabled"); #endif + break; case GeckoProcessType_GPU: process = new gfx::GPUProcessImpl(parentPID); -- cgit v1.2.3 From 69cfed48da18688dc48e9a2576fa5a8b29747e09 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Mon, 9 Oct 2023 17:00:40 -0400 Subject: Issue #2332 - Add deprecation warnings to writable RTCSessionDescription Backport of https://bugzilla.mozilla.org/show_bug.cgi?id=1313966 --- dom/media/PeerConnection.js | 60 +++++++++++++++++++++++++-------- dom/webidl/RTCSessionDescription.webidl | 9 ++--- 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/dom/media/PeerConnection.js b/dom/media/PeerConnection.js index 622b1f08be..f735e371c1 100644 --- a/dom/media/PeerConnection.js +++ b/dom/media/PeerConnection.js @@ -38,6 +38,16 @@ const PC_RECEIVER_CID = Components.ID("{d974b814-8fde-411c-8c45-b86791b81030}"); const PC_COREQUEST_CID = Components.ID("{74b2122d-65a8-4824-aa9e-3d664cb75dc2}"); const PC_DTMF_SENDER_CID = Components.ID("{3610C242-654E-11E6-8EC0-6D1BE389A607}"); +function logMsg(msg, file, line, flag, winID) { + let scriptErrorClass = Cc["@mozilla.org/scripterror;1"]; + let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError); + scriptError.initWithWindowID(msg, file, null, line, 0, flag, + "content javascript", winID); + let console = Cc["@mozilla.org/consoleservice;1"]. + getService(Ci.nsIConsoleService); + console.logMessage(scriptError); +}; + // Global list of PeerConnection objects, so they can be cleaned up when // a page is torn down. (Maps inner window ID to an array of PC objects). function GlobalPCList() { @@ -236,9 +246,7 @@ RTCIceCandidate.prototype = { } }; -function RTCSessionDescription() { - this.type = this.sdp = null; -} +function RTCSessionDescription() {} RTCSessionDescription.prototype = { classDescription: "RTCSessionDescription", classID: PC_SESSION_CID, @@ -246,11 +254,41 @@ RTCSessionDescription.prototype = { QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIDOMGlobalPropertyInitializer]), - init: function(win) { this._win = win; }, + init: function(win) { + this._win = win; + this._winID = this._win.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID; + }, - __init: function(dict) { - this.type = dict.type; - this.sdp = dict.sdp; + __init: function({ type, sdp }) { + Object.assign(this, { _type: type, _sdp: sdp }); + }, + + get type() { return this._type; }, + set type(type) { + this.warn(); + this._type = type; + }, + + get sdp() { return this._sdp; }, + set sdp(sdp) { + this.warn(); + this._sdp = sdp; + }, + + warn: function() { + if (!this._warned) { + // Warn once per RTCSessionDescription about deprecated writable usage. + this.logWarning("RTCSessionDescription's members are readonly! " + + "Writing to them is deprecated and will break soon!"); + this._warned = true; + } + }, + + logWarning: function(msg) { + let err = this._win.Error(); + logMsg(msg, err.fileName, err.lineNumber, Ci.nsIScriptError.warningFlag, + this._winID); } }; @@ -645,13 +683,7 @@ RTCPeerConnection.prototype = { }, logMsg: function(msg, file, line, flag) { - let scriptErrorClass = Cc["@mozilla.org/scripterror;1"]; - let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError); - scriptError.initWithWindowID(msg, file, null, line, 0, flag, - "content javascript", this._winID); - let console = Cc["@mozilla.org/consoleservice;1"]. - getService(Ci.nsIConsoleService); - console.logMessage(scriptError); + return logMsg(msg, file, line, flag, this._winID); }, getEH: function(type) { diff --git a/dom/webidl/RTCSessionDescription.webidl b/dom/webidl/RTCSessionDescription.webidl index 07bfb36f02..4dafe01e1b 100644 --- a/dom/webidl/RTCSessionDescription.webidl +++ b/dom/webidl/RTCSessionDescription.webidl @@ -15,16 +15,17 @@ enum RTCSdpType { }; dictionary RTCSessionDescriptionInit { - RTCSdpType? type = null; - DOMString? sdp = ""; + required RTCSdpType type; + DOMString sdp = ""; }; [Pref="media.peerconnection.enabled", JSImplementation="@mozilla.org/dom/rtcsessiondescription;1", Constructor(optional RTCSessionDescriptionInit descriptionInitDict)] interface RTCSessionDescription { - attribute RTCSdpType? type; - attribute DOMString? sdp; + // These should be readonly, but writing causes deprecation warnings for a bit + attribute RTCSdpType type; + attribute DOMString sdp; jsonifier; }; -- cgit v1.2.3 From 09e6d13d6b2fd2851ea8076efb72f219cd65c2cd Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Mon, 9 Oct 2023 17:02:11 -0400 Subject: Issue #2332 - Update RTCIceCandidate to spec Backport of https://bugzilla.mozilla.org/show_bug.cgi?id=1263312 - part 1 --- dom/media/PeerConnection.js | 8 ++------ dom/webidl/RTCIceCandidate.webidl | 8 ++++---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/dom/media/PeerConnection.js b/dom/media/PeerConnection.js index f735e371c1..991cf5798f 100644 --- a/dom/media/PeerConnection.js +++ b/dom/media/PeerConnection.js @@ -227,9 +227,7 @@ GlobalPCList.prototype = { }; var _globalPCList = new GlobalPCList(); -function RTCIceCandidate() { - this.candidate = this.sdpMid = this.sdpMLineIndex = null; -} +function RTCIceCandidate() {} RTCIceCandidate.prototype = { classDescription: "RTCIceCandidate", classID: PC_ICE_CID, @@ -240,9 +238,7 @@ RTCIceCandidate.prototype = { init: function(win) { this._win = win; }, __init: function(dict) { - this.candidate = dict.candidate; - this.sdpMid = dict.sdpMid; - this.sdpMLineIndex = ("sdpMLineIndex" in dict)? dict.sdpMLineIndex : null; + Object.assign(this, dict); } }; diff --git a/dom/webidl/RTCIceCandidate.webidl b/dom/webidl/RTCIceCandidate.webidl index 67d479aef2..35b404bb7d 100644 --- a/dom/webidl/RTCIceCandidate.webidl +++ b/dom/webidl/RTCIceCandidate.webidl @@ -8,16 +8,16 @@ */ dictionary RTCIceCandidateInit { - DOMString? candidate = null; + required DOMString candidate; DOMString? sdpMid = null; - unsigned short sdpMLineIndex; + unsigned short? sdpMLineIndex = null; }; [Pref="media.peerconnection.enabled", JSImplementation="@mozilla.org/dom/rtcicecandidate;1", - Constructor(optional RTCIceCandidateInit candidateInitDict)] + Constructor(RTCIceCandidateInit candidateInitDict)] interface RTCIceCandidate { - attribute DOMString? candidate; + attribute DOMString candidate; attribute DOMString? sdpMid; attribute unsigned short? sdpMLineIndex; -- cgit v1.2.3 From 81cf4413e21bcda21aa6664d53c2ab74dd749b37 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Mon, 9 Oct 2023 17:04:07 -0400 Subject: Issue #2332 - Have addIceCandidate take a dictionary Backport of https://bugzilla.mozilla.org/show_bug.cgi?id=1263312 part 2 --- dom/media/PeerConnection.js | 11 +++++--- .../test_peerConnection_addIceCandidate.html | 29 ++++++++++++---------- dom/webidl/RTCPeerConnection.webidl | 2 +- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/dom/media/PeerConnection.js b/dom/media/PeerConnection.js index 991cf5798f..712c2b0d13 100644 --- a/dom/media/PeerConnection.js +++ b/dom/media/PeerConnection.js @@ -985,12 +985,15 @@ RTCPeerConnection.prototype = { containsTrickle(topSection) || sections.every(containsTrickle); }, - addIceCandidate: function(c, onSuccess, onError) { return this._legacyCatchAndCloseGuard(onSuccess, onError, () => { - if (!c.candidate && !c.sdpMLineIndex) { - throw new this._win.DOMException("Invalid candidate passed to addIceCandidate!", - "InvalidParameterError"); + if (!c) { + // TODO: Implement processing for end-of-candidates (bug 1318167) + return Promise.resolve(); + } + if (c.sdpMid === null && c.sdpMLineIndex === null) { + throw new this._win.DOMException("Invalid candidate (both sdpMid and sdpMLineIndex are null).", + "TypeError"); } return this._chain(() => new this._win.Promise((resolve, reject) => { this._onAddIceCandidateSuccess = resolve; diff --git a/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html b/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html index 93cbdd0832..a46af2d2f0 100644 --- a/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html +++ b/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html @@ -54,15 +54,15 @@ } ); }, - function PC_REMOTE_ADD_CANDIDATE_MISSING_INDEX(test) { - // Note: it is probably not a good idea to automatically fill a missing - // MLineIndex with a default value of zero, see bug 1157034 + function PC_REMOTE_ADD_MISSING_MID_AND_MISSING_INDEX(test) { var broken = new RTCIceCandidate( {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host"}); return test.pcRemote._pc.addIceCandidate(broken) .then( - // FIXME this needs to be updated once bug 1157034 is fixed - todo(false, "Missing index in got automatically set to a valid value bz://1157034") + generateErrorCallback("addIceCandidate should have failed."), + err => { + is(err.name, "TypeError", "Error is TypeError"); + } ); }, function PC_REMOTE_ADD_VALID_CANDIDATE(test) { @@ -70,7 +70,7 @@ {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host", sdpMLineIndex: 0}); return test.pcRemote._pc.addIceCandidate(candidate) - .then(ok(true, "Successfully added valid ICE candidate")); + .then(() => ok(true, "Successfully added valid ICE candidate")); }, // bug 1095793 function PC_REMOTE_ADD_MISMATCHED_MID_AND_LEVEL_CANDIDATE(test) { @@ -79,12 +79,15 @@ sdpMLineIndex: 0, sdpMid: "sdparta_1"}); return test.pcRemote._pc.addIceCandidate(bogus) - .then( - generateErrorCallback("addIceCandidate should have failed."), - err => { - is(err.name, "InvalidCandidateError", "Error is InvalidCandidateError"); - } - ); + .then(generateErrorCallback("addIceCandidate should have failed."), + err => is(err.name, "InvalidCandidateError", "Error is InvalidCandidateError")); + }, + function PC_REMOTE_ADD_MID_AND_MISSING_INDEX(test) { + var candidate = new RTCIceCandidate( + {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host", + sdpMid: "sdparta_0"}); + return test.pcRemote._pc.addIceCandidate(candidate) + .then(() => ok(true, "Successfully added valid ICE candidate")); }, function PC_REMOTE_ADD_MATCHING_MID_AND_LEVEL_CANDIDATE(test) { var candidate = new mozRTCIceCandidate( @@ -92,7 +95,7 @@ sdpMLineIndex: 0, sdpMid: "sdparta_0"}); return test.pcRemote._pc.addIceCandidate(candidate) - .then(ok(true, "Successfully added valid ICE candidate with matching mid and level")); + .then(() => ok(true, "Successfully added valid ICE candidate with matching mid and level")); } ]); test.run(); diff --git a/dom/webidl/RTCPeerConnection.webidl b/dom/webidl/RTCPeerConnection.webidl index b852d32070..272d9c6c4e 100644 --- a/dom/webidl/RTCPeerConnection.webidl +++ b/dom/webidl/RTCPeerConnection.webidl @@ -91,7 +91,7 @@ interface RTCPeerConnection : EventTarget { readonly attribute RTCSessionDescription? localDescription; readonly attribute RTCSessionDescription? remoteDescription; readonly attribute RTCSignalingState signalingState; - Promise addIceCandidate (RTCIceCandidate candidate); + Promise addIceCandidate ((RTCIceCandidateInit or RTCIceCandidate)? candidate); readonly attribute boolean? canTrickleIceCandidates; readonly attribute RTCIceGatheringState iceGatheringState; readonly attribute RTCIceConnectionState iceConnectionState; -- cgit v1.2.3 From c8218f73b7a1f2dcc8b2a83707dcfd9d38e741d4 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Mon, 9 Oct 2023 17:06:12 -0400 Subject: Issue #2332 - Have set(Local|Remote)Description take dictionaries Backport of https://bugzilla.mozilla.org/show_bug.cgi?id=1263312 part 3 --- dom/webidl/RTCPeerConnection.webidl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/dom/webidl/RTCPeerConnection.webidl b/dom/webidl/RTCPeerConnection.webidl index 272d9c6c4e..7e9016e0aa 100644 --- a/dom/webidl/RTCPeerConnection.webidl +++ b/dom/webidl/RTCPeerConnection.webidl @@ -7,7 +7,7 @@ * http://w3c.github.io/webrtc-pc/#interface-definition */ -callback RTCSessionDescriptionCallback = void (RTCSessionDescription sdp); +callback RTCSessionDescriptionCallback = void (RTCSessionDescriptionInit description); callback RTCPeerConnectionErrorCallback = void (DOMError error); callback RTCStatsCallback = void (RTCStatsReport report); @@ -84,10 +84,10 @@ interface RTCPeerConnection : EventTarget { optional DOMString username); [Pref="media.peerconnection.identity.enabled"] Promise getIdentityAssertion(); - Promise createOffer (optional RTCOfferOptions options); - Promise createAnswer (optional RTCAnswerOptions options); - Promise setLocalDescription (RTCSessionDescription description); - Promise setRemoteDescription (RTCSessionDescription description); + Promise createOffer (optional RTCOfferOptions options); + Promise createAnswer (optional RTCAnswerOptions options); + Promise setLocalDescription (RTCSessionDescriptionInit description); + Promise setRemoteDescription (RTCSessionDescriptionInit description); readonly attribute RTCSessionDescription? localDescription; readonly attribute RTCSessionDescription? remoteDescription; readonly attribute RTCSignalingState signalingState; @@ -155,10 +155,10 @@ partial interface RTCPeerConnection { optional RTCOfferOptions options); Promise createAnswer (RTCSessionDescriptionCallback successCallback, RTCPeerConnectionErrorCallback failureCallback); - Promise setLocalDescription (RTCSessionDescription description, + Promise setLocalDescription (RTCSessionDescriptionInit description, VoidFunction successCallback, RTCPeerConnectionErrorCallback failureCallback); - Promise setRemoteDescription (RTCSessionDescription description, + Promise setRemoteDescription (RTCSessionDescriptionInit description, VoidFunction successCallback, RTCPeerConnectionErrorCallback failureCallback); Promise addIceCandidate (RTCIceCandidate candidate, -- cgit v1.2.3 From 9bee3a8b7250fe33f50eca53737f8bec71d69d84 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Mon, 9 Oct 2023 17:07:05 -0400 Subject: Issue #2332 - Have createOffer/Answer resolve with dictionaries Backport of https://bugzilla.mozilla.org/show_bug.cgi?id=1263312 part 4 --- dom/media/PeerConnection.js | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/dom/media/PeerConnection.js b/dom/media/PeerConnection.js index 712c2b0d13..e4612f8316 100644 --- a/dom/media/PeerConnection.js +++ b/dom/media/PeerConnection.js @@ -739,8 +739,7 @@ RTCPeerConnection.prototype = { this._impl.createOffer(options); })); p = this._addIdentityAssertion(p, origin); - return p.then( - sdp => new this._win.RTCSessionDescription({ type: "offer", sdp: sdp })); + return p.then(sdp => Cu.cloneInto({ type: "offer", sdp: sdp }, this._win)); }); }); }, @@ -774,9 +773,7 @@ RTCPeerConnection.prototype = { this._impl.createAnswer(); })); p = this._addIdentityAssertion(p, origin); - return p.then(sdp => { - return new this._win.RTCSessionDescription({ type: "answer", sdp: sdp }); - }); + return p.then(sdp => Cu.cloneInto({ type: "answer", sdp: sdp }, this._win)); }); }); }, @@ -1137,8 +1134,7 @@ RTCPeerConnection.prototype = { return null; } - return new this._win.RTCSessionDescription({ type: this._localType, - sdp: sdp }); + return new this._win.RTCSessionDescription({ type: this._localType, sdp }); }, get remoteDescription() { @@ -1147,8 +1143,7 @@ RTCPeerConnection.prototype = { if (sdp.length == 0) { return null; } - return new this._win.RTCSessionDescription({ type: this._remoteType, - sdp: sdp }); + return new this._win.RTCSessionDescription({ type: this._remoteType, sdp }); }, get peerIdentity() { return this._peerIdentity; }, -- cgit v1.2.3 From 38dfadad45fe43d08de05706dc3332f41e94aee5 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Mon, 9 Oct 2023 17:08:07 -0400 Subject: Issue #2332 - Update most tests to skip RTCIceCandidate construction Backport of https://bugzilla.mozilla.org/show_bug.cgi?id=1263312 part 5 --- dom/media/tests/mochitest/templates.js | 2 +- .../mochitest/test_peerConnection_addIceCandidate.html | 14 +++++++------- .../mochitest/test_peerConnection_closeDuringIce.html | 4 ++-- .../tests/mochitest/test_peerConnection_iceFailure.html | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/dom/media/tests/mochitest/templates.js b/dom/media/tests/mochitest/templates.js index 3a8e0dd496..7a149c146e 100644 --- a/dom/media/tests/mochitest/templates.js +++ b/dom/media/tests/mochitest/templates.js @@ -118,7 +118,7 @@ var commandsPeerConnectionInitial = [ test.setupSignalingClient(); test.registerSignalingCallback("ice_candidate", function (message) { var pc = test.pcRemote ? test.pcRemote : test.pcLocal; - pc.storeOrAddIceCandidate(new RTCIceCandidate(message.ice_candidate)); + pc.storeOrAddIceCandidate(message.ice_candidate); }); test.registerSignalingCallback("end_of_trickle_ice", function (message) { test.signalingMessagesFinished(); diff --git a/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html b/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html index a46af2d2f0..ba0039a513 100644 --- a/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html +++ b/dom/media/tests/mochitest/test_peerConnection_addIceCandidate.html @@ -19,9 +19,9 @@ test.chain.insertAfter("PC_LOCAL_SET_LOCAL_DESCRIPTION", [ function PC_LOCAL_ADD_CANDIDATE_EARLY(test) { - var candidate = new RTCIceCandidate( - {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host", - sdpMLineIndex: 0}); + var candidate = { + candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host", + sdpMLineIndex: 0}; return test.pcLocal._pc.addIceCandidate(candidate).then( generateErrorCallback("addIceCandidate should have failed."), err => { @@ -66,9 +66,9 @@ ); }, function PC_REMOTE_ADD_VALID_CANDIDATE(test) { - var candidate = new RTCIceCandidate( - {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host", - sdpMLineIndex: 0}); + var candidate = { + candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host", + sdpMLineIndex: 0}; return test.pcRemote._pc.addIceCandidate(candidate) .then(() => ok(true, "Successfully added valid ICE candidate")); }, @@ -90,7 +90,7 @@ .then(() => ok(true, "Successfully added valid ICE candidate")); }, function PC_REMOTE_ADD_MATCHING_MID_AND_LEVEL_CANDIDATE(test) { - var candidate = new mozRTCIceCandidate( + var candidate = new RTCIceCandidate( {candidate:"candidate:1 1 UDP 2130706431 192.168.2.1 50005 typ host", sdpMLineIndex: 0, sdpMid: "sdparta_0"}); diff --git a/dom/media/tests/mochitest/test_peerConnection_closeDuringIce.html b/dom/media/tests/mochitest/test_peerConnection_closeDuringIce.html index eb8228d03c..37b2011664 100644 --- a/dom/media/tests/mochitest/test_peerConnection_closeDuringIce.html +++ b/dom/media/tests/mochitest/test_peerConnection_closeDuringIce.html @@ -21,12 +21,12 @@ function PC_REMOTE_SETUP_NULL_ICE_HANDLER(test) { test.pcRemote.setupIceCandidateHandler(test, function() {}, function () {}); } function PC_REMOTE_ADD_FAKE_ICE_CANDIDATE(test) { - var cand = new RTCIceCandidate({"candidate":"candidate:0 1 UDP 2130379007 192.0.2.1 12345 typ host","sdpMid":"","sdpMLineIndex":0}); + var cand = {"candidate":"candidate:0 1 UDP 2130379007 192.0.2.1 12345 typ host","sdpMid":"","sdpMLineIndex":0}; test.pcRemote.storeOrAddIceCandidate(cand); info(test.pcRemote + " Stored fake candidate: " + JSON.stringify(cand)); } function PC_LOCAL_ADD_FAKE_ICE_CANDIDATE(test) { - var cand = new RTCIceCandidate({"candidate":"candidate:0 1 UDP 2130379007 192.0.2.2 56789 typ host","sdpMid":"","sdpMLineIndex":0}); + var cand = {"candidate":"candidate:0 1 UDP 2130379007 192.0.2.2 56789 typ host","sdpMid":"","sdpMLineIndex":0}; test.pcLocal.storeOrAddIceCandidate(cand); info(test.pcLocal + " Stored fake candidate: " + JSON.stringify(cand)); } diff --git a/dom/media/tests/mochitest/test_peerConnection_iceFailure.html b/dom/media/tests/mochitest/test_peerConnection_iceFailure.html index cbdfd018a0..3f6728573f 100644 --- a/dom/media/tests/mochitest/test_peerConnection_iceFailure.html +++ b/dom/media/tests/mochitest/test_peerConnection_iceFailure.html @@ -20,12 +20,12 @@ function PC_REMOTE_SETUP_NULL_ICE_HANDLER(test) { test.pcRemote.setupIceCandidateHandler(test, function() {}, function () {}); } function PC_REMOTE_ADD_FAKE_ICE_CANDIDATE(test) { - var cand = new RTCIceCandidate({"candidate":"candidate:0 1 UDP 2130379007 192.0.2.1 12345 typ host","sdpMid":"","sdpMLineIndex":0}); + var cand = {"candidate":"candidate:0 1 UDP 2130379007 192.0.2.1 12345 typ host","sdpMid":"","sdpMLineIndex":0}; test.pcRemote.storeOrAddIceCandidate(cand); info(test.pcRemote + " Stored fake candidate: " + JSON.stringify(cand)); } function PC_LOCAL_ADD_FAKE_ICE_CANDIDATE(test) { - var cand = new RTCIceCandidate({"candidate":"candidate:0 1 UDP 2130379007 192.0.2.2 56789 typ host","sdpMid":"","sdpMLineIndex":0}); + var cand = {"candidate":"candidate:0 1 UDP 2130379007 192.0.2.2 56789 typ host","sdpMid":"","sdpMLineIndex":0}; test.pcLocal.storeOrAddIceCandidate(cand); info(test.pcLocal + " Stored fake candidate: " + JSON.stringify(cand)); } -- cgit v1.2.3 From 95a8edc5fc34800f4823a216fad64de5b966d0a0 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Mon, 9 Oct 2023 17:09:04 -0400 Subject: Issue #2332 - Update most tests to skip RTCSessionDescription construction Backport of https://bugzilla.mozilla.org/show_bug.cgi?id=1263312 part 6 --- dom/media/tests/mochitest/identity/test_fingerprints.html | 3 +-- dom/media/tests/mochitest/pc.js | 12 ++++++------ .../tests/mochitest/test_peerConnection_errorCallbacks.html | 6 ++---- .../mochitest/test_peerConnection_localReofferRollback.html | 7 +++---- .../tests/mochitest/test_peerConnection_localRollback.html | 7 +++---- .../mochitest/test_peerConnection_remoteReofferRollback.html | 6 ++---- .../tests/mochitest/test_peerConnection_remoteRollback.html | 6 ++---- ...test_peerConnection_restartIceLocalAndRemoteRollback.html | 6 ++---- .../test_peerConnection_restartIceLocalRollback.html | 8 +++----- 9 files changed, 24 insertions(+), 37 deletions(-) diff --git a/dom/media/tests/mochitest/identity/test_fingerprints.html b/dom/media/tests/mochitest/identity/test_fingerprints.html index 0fd065af26..bf26c2fdd5 100644 --- a/dom/media/tests/mochitest/identity/test_fingerprints.html +++ b/dom/media/tests/mochitest/identity/test_fingerprints.html @@ -86,8 +86,7 @@ function testMultipleFingerprints() { fingerprintSdp(fingerprints.slice(1)) + offer.sdp.slice(match.index); - var desc = new RTCSessionDescription({ type: 'offer', sdp: sdp }); - return pcStrict.setRemoteDescription(desc); + return pcStrict.setRemoteDescription({ type: 'offer', sdp }); }) .then(() => { ok(true, 'Modified fingerprints were accepted'); diff --git a/dom/media/tests/mochitest/pc.js b/dom/media/tests/mochitest/pc.js index 2e9c7c63f1..4363841da7 100644 --- a/dom/media/tests/mochitest/pc.js +++ b/dom/media/tests/mochitest/pc.js @@ -334,7 +334,7 @@ PeerConnectionTest.prototype.createOffer = function(peer) { * * @param {PeerConnectionWrapper} peer The peer connection wrapper to run the command on - * @param {RTCSessionDescription} desc + * @param {RTCSessionDescriptionInit} desc * Session description for the local description request */ PeerConnectionTest.prototype.setLocalDescription = @@ -403,7 +403,7 @@ PeerConnectionTest.prototype.setOfferOptions = function(options) { * * @param {PeerConnectionWrapper} peer The peer connection wrapper to run the command on - * @param {RTCSessionDescription} desc + * @param {RTCSessionDescriptionInit} desc * Session description for the remote description request */ PeerConnectionTest.prototype.setRemoteDescription = @@ -1064,7 +1064,7 @@ PeerConnectionWrapper.prototype = { * Sets the local description and automatically handles the failure case. * * @param {object} desc - * RTCSessionDescription for the local description request + * RTCSessionDescriptionInit for the local description request */ setLocalDescription : function(desc) { this.observedNegotiationNeeded = undefined; @@ -1078,7 +1078,7 @@ PeerConnectionWrapper.prototype = { * causes the test case to fail if the call succeeds. * * @param {object} desc - * RTCSessionDescription for the local description request + * RTCSessionDescriptionInit for the local description request * @returns {Promise} * A promise that resolves to the expected error */ @@ -1095,7 +1095,7 @@ PeerConnectionWrapper.prototype = { * Sets the remote description and automatically handles the failure case. * * @param {object} desc - * RTCSessionDescription for the remote description request + * RTCSessionDescriptionInit for the remote description request */ setRemoteDescription : function(desc) { this.observedNegotiationNeeded = undefined; @@ -1115,7 +1115,7 @@ PeerConnectionWrapper.prototype = { * causes the test case to fail if the call succeeds. * * @param {object} desc - * RTCSessionDescription for the remote description request + * RTCSessionDescriptionInit for the remote description request * @returns {Promise} * a promise that resolve to the returned error */ diff --git a/dom/media/tests/mochitest/test_peerConnection_errorCallbacks.html b/dom/media/tests/mochitest/test_peerConnection_errorCallbacks.html index 6d152a4fa6..9ae3b8d50f 100644 --- a/dom/media/tests/mochitest/test_peerConnection_errorCallbacks.html +++ b/dom/media/tests/mochitest/test_peerConnection_errorCallbacks.html @@ -27,8 +27,7 @@ function testSetLocalDescriptionError() { var pc = new RTCPeerConnection(); info ("Testing setLocalDescription error"); - return pc.setLocalDescription(new RTCSessionDescription({ sdp: "Picklechips!", - type: "offer" })) + return pc.setLocalDescription({ sdp: "Picklechips!", type: "offer" }) .then(generateErrorCallback("setLocalDescription with nonsense SDP should fail"), validateReason); }; @@ -36,8 +35,7 @@ function testSetRemoteDescriptionError() { var pc = new RTCPeerConnection(); info ("Testing setRemoteDescription error"); - return pc.setRemoteDescription(new RTCSessionDescription({ sdp: "Who?", - type: "offer" })) + return pc.setRemoteDescription({ sdp: "Who?", type: "offer" }) .then(generateErrorCallback("setRemoteDescription with nonsense SDP should fail"), validateReason); }; diff --git a/dom/media/tests/mochitest/test_peerConnection_localReofferRollback.html b/dom/media/tests/mochitest/test_peerConnection_localReofferRollback.html index 0b0b35fe80..ed149747ca 100644 --- a/dom/media/tests/mochitest/test_peerConnection_localReofferRollback.html +++ b/dom/media/tests/mochitest/test_peerConnection_localReofferRollback.html @@ -37,10 +37,9 @@ }, function PC_REMOTE_ROLLBACK(test) { - return test.setLocalDescription( - test.pcRemote, - new RTCSessionDescription({ type: "rollback", sdp: ""}), - STABLE); + return test.setLocalDescription(test.pcRemote, + { type: "rollback", sdp: "" }, + STABLE); }, // Rolling back should shut down gathering diff --git a/dom/media/tests/mochitest/test_peerConnection_localRollback.html b/dom/media/tests/mochitest/test_peerConnection_localRollback.html index 2a35920baa..45ceba844e 100644 --- a/dom/media/tests/mochitest/test_peerConnection_localRollback.html +++ b/dom/media/tests/mochitest/test_peerConnection_localRollback.html @@ -23,10 +23,9 @@ }, function PC_REMOTE_ROLLBACK(test) { - return test.setLocalDescription( - test.pcRemote, - new RTCSessionDescription({ type: "rollback", sdp: ""}), - STABLE); + return test.setLocalDescription(test.pcRemote, + { type: "rollback", sdp: "" }, + STABLE); }, // Rolling back should shut down gathering diff --git a/dom/media/tests/mochitest/test_peerConnection_remoteReofferRollback.html b/dom/media/tests/mochitest/test_peerConnection_remoteReofferRollback.html index 6b518e1d29..7580358b86 100644 --- a/dom/media/tests/mochitest/test_peerConnection_remoteReofferRollback.html +++ b/dom/media/tests/mochitest/test_peerConnection_remoteReofferRollback.html @@ -35,10 +35,8 @@ }, function PC_REMOTE_ROLLBACK(test) { - return test.setRemoteDescription( - test.pcRemote, - new RTCSessionDescription({ type: "rollback" }), - STABLE) + return test.setRemoteDescription(test.pcRemote, { type: "rollback" }, + STABLE) .then(() => test.pcRemote.rollbackRemoteTracksIfNotNegotiated()); }, diff --git a/dom/media/tests/mochitest/test_peerConnection_remoteRollback.html b/dom/media/tests/mochitest/test_peerConnection_remoteRollback.html index 099628ab88..35a51d03c0 100644 --- a/dom/media/tests/mochitest/test_peerConnection_remoteRollback.html +++ b/dom/media/tests/mochitest/test_peerConnection_remoteRollback.html @@ -20,10 +20,8 @@ function PC_REMOTE_ROLLBACK(test) { // We still haven't negotiated the tracks test.pcRemote.expectNegotiationNeeded(); - return test.setRemoteDescription( - test.pcRemote, - new RTCSessionDescription({ type: "rollback" }), - STABLE) + return test.setRemoteDescription(test.pcRemote, { type: "rollback" }, + STABLE) .then(() => test.pcRemote.rollbackRemoteTracksIfNotNegotiated()); }, diff --git a/dom/media/tests/mochitest/test_peerConnection_restartIceLocalAndRemoteRollback.html b/dom/media/tests/mochitest/test_peerConnection_restartIceLocalAndRemoteRollback.html index e926171644..d2280cee87 100644 --- a/dom/media/tests/mochitest/test_peerConnection_restartIceLocalAndRemoteRollback.html +++ b/dom/media/tests/mochitest/test_peerConnection_restartIceLocalAndRemoteRollback.html @@ -51,10 +51,8 @@ }, function PC_REMOTE_ROLLBACK(test) { - return test.setRemoteDescription( - test.pcRemote, - new RTCSessionDescription({ type: "rollback" }), - STABLE); + return test.setRemoteDescription(test.pcRemote, { type: "rollback" }, + STABLE); }, function PC_LOCAL_ROLLBACK(test) { diff --git a/dom/media/tests/mochitest/test_peerConnection_restartIceLocalRollback.html b/dom/media/tests/mochitest/test_peerConnection_restartIceLocalRollback.html index c1ac186de1..fd9fee9c0c 100644 --- a/dom/media/tests/mochitest/test_peerConnection_restartIceLocalRollback.html +++ b/dom/media/tests/mochitest/test_peerConnection_restartIceLocalRollback.html @@ -42,11 +42,9 @@ test.pcLocal.iceCheckingIceRollbackExpected = true; }, function PC_LOCAL_ROLLBACK(test) { - return test.setLocalDescription( - test.pcLocal, - new RTCSessionDescription({ type: "rollback", - sdp: ""}), - STABLE); + return test.setLocalDescription(test.pcLocal, + { type: "rollback", sdp: ""}, + STABLE); }, // Rolling back should shut down gathering function PC_LOCAL_WAIT_FOR_END_OF_TRICKLE(test) { -- cgit v1.2.3 From 0ea78ba5fad57abc0f3669dfa9badb9337d49bfa Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Mon, 9 Oct 2023 22:13:50 -0400 Subject: Issue #2332 - Fix CamerasChild helper to return by value instead of out-of-scope reference Backport of https://bugzilla.mozilla.org/show_bug.cgi?id=1318132 --- dom/media/systemservices/CamerasChild.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/media/systemservices/CamerasChild.cpp b/dom/media/systemservices/CamerasChild.cpp index abbcc9e223..341c6e17a7 100644 --- a/dom/media/systemservices/CamerasChild.cpp +++ b/dom/media/systemservices/CamerasChild.cpp @@ -223,7 +223,7 @@ public: Dispatch(); } - const T& ReturnValue() const { + T ReturnValue() const { if (mSuccess) { return mSuccessValue; } else { -- cgit v1.2.3 From 4df8e7664af00cc7d12edbd1b75be95f1a10cc8a Mon Sep 17 00:00:00 2001 From: Moonchild Date: Sat, 14 Oct 2023 14:16:26 +0200 Subject: Issue #2340 - Return an array (actually frozen sequence) for {border|content}BoxSize Resolves #2340 --- dom/base/ResizeObserver.cpp | 24 ++++++++++++++++++++++++ dom/base/ResizeObserver.h | 10 +++------- dom/webidl/ResizeObserver.webidl | 8 ++++++-- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/dom/base/ResizeObserver.cpp b/dom/base/ResizeObserver.cpp index 51fd603217..ca25c06e43 100644 --- a/dom/base/ResizeObserver.cpp +++ b/dom/base/ResizeObserver.cpp @@ -303,6 +303,30 @@ ResizeObserverEntry::Constructor(const GlobalObject& aGlobal, return observerEntry.forget(); } +void ResizeObserverEntry::GetBorderBoxSize( + nsTArray>& aRetVal) const { + // In the resize-observer-1 spec, there will only be a single + // ResizeObserverSize returned in the FrozenArray. + // + // Note: the usage of FrozenArray is to support elements that have multiple + // fragments, which occur in multi-column scenarios. See: + // https://drafts.csswg.org/resize-observer/#resize-observer-entry-interface + aRetVal.Clear(); + aRetVal.AppendElement(mBorderBoxSize); +} + +void ResizeObserverEntry::GetContentBoxSize( + nsTArray>& aRetVal) const { + // In the resize-observer-1 spec, there will only be a single + // ResizeObserverSize returned in the FrozenArray. + // + // Note: the usage of FrozenArray is to support elements that have multiple + // fragments, which occur in multi-column scenarios. + // https://drafts.csswg.org/resize-observer/#resize-observer-entry-interface + aRetVal.Clear(); + aRetVal.AppendElement(mContentBoxSize); +} + void ResizeObserverEntry::SetBorderBoxSize(const nsSize& aSize) { nsIFrame* frame = mTarget->GetPrimaryFrame(); diff --git a/dom/base/ResizeObserver.h b/dom/base/ResizeObserver.h index 56675693ce..ca87a080b4 100644 --- a/dom/base/ResizeObserver.h +++ b/dom/base/ResizeObserver.h @@ -163,14 +163,10 @@ public: /** * Returns target's logical border-box size and content-box size as - * ResizeObserverSize. + * a ResizeObserverSize array. */ - ResizeObserverSize* BorderBoxSize() const { - return mBorderBoxSize; - } - ResizeObserverSize* ContentBoxSize() const { - return mContentBoxSize; - } + void GetBorderBoxSize(nsTArray>& aRetVal) const; + void GetContentBoxSize(nsTArray>& aRetVal) const; // Set borderBoxSize. void SetBorderBoxSize(const nsSize& aSize); diff --git a/dom/webidl/ResizeObserver.webidl b/dom/webidl/ResizeObserver.webidl index d764af7cbd..c1286d66a7 100644 --- a/dom/webidl/ResizeObserver.webidl +++ b/dom/webidl/ResizeObserver.webidl @@ -34,8 +34,12 @@ callback ResizeObserverCallback = void (sequence entries, R interface ResizeObserverEntry { readonly attribute Element target; readonly attribute DOMRectReadOnly? contentRect; - readonly attribute ResizeObserverSize borderBoxSize; - readonly attribute ResizeObserverSize contentBoxSize; + // We are using a [Pure, Cached, Frozen] sequence since `FrozenArray` is not implemented in webidl. + // This is functionally similar enough. As of #2340 Mozilla has not implemented this yet, either. + [Frozen, Cached, Pure] + readonly attribute sequence borderBoxSize; + [Frozen, Cached, Pure] + readonly attribute sequence contentBoxSize; }; [Pref="layout.css.resizeobserver.enabled"] -- cgit v1.2.3 From 3b39358c842b88d3570b6817fc4f3fce8ee97a70 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Sat, 14 Oct 2023 15:16:41 +0200 Subject: Clean up dom\webidl Fix CRLF line endings in some files, and remove EME interface leftovers. --- dom/webidl/HiddenPluginEvent.webidl | 24 +++---- dom/webidl/MediaEncryptedEvent.webidl | 23 ------- dom/webidl/MediaKeyError.webidl | 19 ------ dom/webidl/MediaKeyMessageEvent.webidl | 30 --------- dom/webidl/MediaKeySession.webidl | 47 ------------- dom/webidl/MediaKeyStatusMap.webidl | 30 --------- dom/webidl/MediaKeySystemAccess.webidl | 41 ----------- dom/webidl/MediaKeys.webidl | 30 --------- dom/webidl/MediaKeysRequestStatus.webidl | 23 ------- dom/webidl/MediaQueryListEvent.webidl | 36 +++++----- dom/webidl/ResizeObserver.webidl | 112 +++++++++++++++---------------- dom/webidl/WidevineCDMManifest.webidl | 15 ----- 12 files changed, 86 insertions(+), 344 deletions(-) delete mode 100644 dom/webidl/MediaEncryptedEvent.webidl delete mode 100644 dom/webidl/MediaKeyError.webidl delete mode 100644 dom/webidl/MediaKeyMessageEvent.webidl delete mode 100644 dom/webidl/MediaKeySession.webidl delete mode 100644 dom/webidl/MediaKeyStatusMap.webidl delete mode 100644 dom/webidl/MediaKeySystemAccess.webidl delete mode 100644 dom/webidl/MediaKeys.webidl delete mode 100644 dom/webidl/MediaKeysRequestStatus.webidl delete mode 100644 dom/webidl/WidevineCDMManifest.webidl diff --git a/dom/webidl/HiddenPluginEvent.webidl b/dom/webidl/HiddenPluginEvent.webidl index 1ba09acb69..53096f9c81 100644 --- a/dom/webidl/HiddenPluginEvent.webidl +++ b/dom/webidl/HiddenPluginEvent.webidl @@ -1,12 +1,12 @@ -interface PluginTag; - -[Constructor(DOMString type, optional HiddenPluginEventInit eventInit), ChromeOnly] -interface HiddenPluginEvent : Event -{ - readonly attribute PluginTag? tag; -}; - -dictionary HiddenPluginEventInit : EventInit -{ - PluginTag? tag = null; -}; +interface PluginTag; + +[Constructor(DOMString type, optional HiddenPluginEventInit eventInit), ChromeOnly] +interface HiddenPluginEvent : Event +{ + readonly attribute PluginTag? tag; +}; + +dictionary HiddenPluginEventInit : EventInit +{ + PluginTag? tag = null; +}; 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 closed; - - readonly attribute MediaKeyStatusMap keyStatuses; - - attribute EventHandler onkeystatuseschange; - - attribute EventHandler onmessage; - - [NewObject] - Promise generateRequest(DOMString initDataType, BufferSource initData); - - [NewObject] - Promise load(DOMString sessionId); - - // session operations - [NewObject] - Promise update(BufferSource response); - - [NewObject] - Promise close(); - - [NewObject] - Promise remove(); -}; diff --git a/dom/webidl/MediaKeyStatusMap.webidl b/dom/webidl/MediaKeyStatusMap.webidl deleted file mode 100644 index 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; - 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 initDataTypes = []; - sequence audioCapabilities = []; - sequence videoCapabilities = []; - MediaKeysRequirement distinctiveIdentifier = "optional"; - MediaKeysRequirement persistentState = "optional"; - sequence sessionTypes; -}; - -[Pref="media.eme.apiVisible"] -interface MediaKeySystemAccess { - readonly attribute DOMString keySystem; - [NewObject] - MediaKeySystemConfiguration getConfiguration(); - [NewObject] - Promise 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 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/MediaQueryListEvent.webidl b/dom/webidl/MediaQueryListEvent.webidl index f3a66fb57f..5e53e9734f 100644 --- a/dom/webidl/MediaQueryListEvent.webidl +++ b/dom/webidl/MediaQueryListEvent.webidl @@ -1,18 +1,18 @@ -/* -*- 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/. - * - * https://drafts.csswg.org/cssom-view/#mediaquerylistevent - */ - -[Constructor(DOMString type, optional MediaQueryListEventInit eventInitDict)] -interface MediaQueryListEvent : Event { - readonly attribute DOMString media; - readonly attribute boolean matches; -}; - -dictionary MediaQueryListEventInit : EventInit { - DOMString media = ""; - boolean matches = false; -}; +/* -*- 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/. + * + * https://drafts.csswg.org/cssom-view/#mediaquerylistevent + */ + +[Constructor(DOMString type, optional MediaQueryListEventInit eventInitDict)] +interface MediaQueryListEvent : Event { + readonly attribute DOMString media; + readonly attribute boolean matches; +}; + +dictionary MediaQueryListEventInit : EventInit { + DOMString media = ""; + boolean matches = false; +}; diff --git a/dom/webidl/ResizeObserver.webidl b/dom/webidl/ResizeObserver.webidl index c1286d66a7..183bf42304 100644 --- a/dom/webidl/ResizeObserver.webidl +++ b/dom/webidl/ResizeObserver.webidl @@ -1,56 +1,56 @@ -/* -*- 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://wicg.github.io/ResizeObserver/ - */ - -enum ResizeObserverBoxOptions { - "border-box", - "content-box" -}; - -dictionary ResizeObserverOptions { - ResizeObserverBoxOptions box = "content-box"; -}; - -[Constructor(ResizeObserverCallback callback), - Exposed=Window, - Pref="layout.css.resizeobserver.enabled"] -interface ResizeObserver { - [Throws] - void observe(Element? target, optional ResizeObserverOptions options); - [Throws] - void unobserve(Element? target); - void disconnect(); -}; - -callback ResizeObserverCallback = void (sequence entries, ResizeObserver observer); - -[Constructor(Element? target), - Pref="layout.css.resizeobserver.enabled"] -interface ResizeObserverEntry { - readonly attribute Element target; - readonly attribute DOMRectReadOnly? contentRect; - // We are using a [Pure, Cached, Frozen] sequence since `FrozenArray` is not implemented in webidl. - // This is functionally similar enough. As of #2340 Mozilla has not implemented this yet, either. - [Frozen, Cached, Pure] - readonly attribute sequence borderBoxSize; - [Frozen, Cached, Pure] - readonly attribute sequence contentBoxSize; -}; - -[Pref="layout.css.resizeobserver.enabled"] -interface ResizeObserverSize { - readonly attribute unrestricted double inlineSize; - readonly attribute unrestricted double blockSize; -}; - -[ChromeOnly, - Pref="layout.css.resizeobserver.enabled"] -interface ResizeObservation { - readonly attribute Element target; - boolean isActive(); -}; +/* -*- 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://wicg.github.io/ResizeObserver/ + */ + +enum ResizeObserverBoxOptions { + "border-box", + "content-box" +}; + +dictionary ResizeObserverOptions { + ResizeObserverBoxOptions box = "content-box"; +}; + +[Constructor(ResizeObserverCallback callback), + Exposed=Window, + Pref="layout.css.resizeobserver.enabled"] +interface ResizeObserver { + [Throws] + void observe(Element? target, optional ResizeObserverOptions options); + [Throws] + void unobserve(Element? target); + void disconnect(); +}; + +callback ResizeObserverCallback = void (sequence entries, ResizeObserver observer); + +[Constructor(Element? target), + Pref="layout.css.resizeobserver.enabled"] +interface ResizeObserverEntry { + readonly attribute Element target; + readonly attribute DOMRectReadOnly? contentRect; + // We are using a [Pure, Cached, Frozen] sequence since `FrozenArray` is not implemented in webidl. + // This is functionally similar enough. As of #2340 Mozilla has not implemented this yet, either. + [Frozen, Cached, Pure] + readonly attribute sequence borderBoxSize; + [Frozen, Cached, Pure] + readonly attribute sequence contentBoxSize; +}; + +[Pref="layout.css.resizeobserver.enabled"] +interface ResizeObserverSize { + readonly attribute unrestricted double inlineSize; + readonly attribute unrestricted double blockSize; +}; + +[ChromeOnly, + Pref="layout.css.resizeobserver.enabled"] +interface ResizeObservation { + readonly attribute Element target; + boolean isActive(); +}; 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; -}; -- cgit v1.2.3 From d5020b69bd84b937de89b2aef5787bfdb4e37dac Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 16 Oct 2023 01:10:26 -0500 Subject: Issue #1442 Follow-up: Stop pretending proxies have a JSNative call/construct hook. https://bugzilla.mozilla.org/show_bug.cgi?id=1471924 Part 1 Also remove an erroneous debug assert and guard against future issues. This fixes crashes on vk.com but still does not behave correctly. --- dom/workers/WorkerPrivate.cpp | 2 -- js/src/builtin/Stream.cpp | 2 +- js/src/jit/BaselineIC.cpp | 3 --- js/src/jscntxtinlines.h | 17 ++--------------- js/src/jsobj.cpp | 32 ++++++++++---------------------- js/src/proxy/Proxy.cpp | 18 ------------------ js/src/vm/Interpreter.cpp | 21 +++++++++++++++++---- 7 files changed, 30 insertions(+), 65 deletions(-) diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 3b3de7e3b5..51ab67f708 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -6226,8 +6226,6 @@ WorkerPrivate::RunExpiredTimeouts(JSContext* aCx) // Guard against recursion. mRunningExpiredTimeouts = true; - MOZ_DIAGNOSTIC_ASSERT(data->mCurrentTimerNestingLevel == 0); - // Run expired timeouts. for (uint32_t index = 0; index < expiredTimeouts.Length(); index++) { TimeoutInfo*& info = expiredTimeouts[index]; diff --git a/js/src/builtin/Stream.cpp b/js/src/builtin/Stream.cpp index c8d8e3e324..26457709d8 100644 --- a/js/src/builtin/Stream.cpp +++ b/js/src/builtin/Stream.cpp @@ -2790,7 +2790,7 @@ ReadableStreamControllerCallPullIfNeeded(JSContext* cx, HandleNativeObject contr } else { pullPromise = PromiseInvokeOrNoop(cx, underlyingSource, cx->names().pull, controllerVal); } - if (!pullPromise) + if (!pullPromise || !pullPromise->is()) return false; RootedObject onPullFulfilled(cx, NewHandler(cx, ControllerPullHandler, controller)); diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index b657359d3e..a6adc122c7 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -5593,9 +5593,6 @@ TryAttachCallStub(JSContext* cx, ICCall_Fallback* stub, HandleScript script, jsb RootedObject obj(cx, &callee.toObject()); if (!obj->is()) { // Try to attach a stub for a call/construct hook on the object. - // Ignore proxies, which are special cased by callHook/constructHook. - if (obj->is()) - return true; if (JSNative hook = constructing ? obj->constructHook() : obj->callHook()) { if (op != JSOP_FUNAPPLY && !isSpread && !createSingleton) { RootedObject templateObject(cx); diff --git a/js/src/jscntxtinlines.h b/js/src/jscntxtinlines.h index c89ef86ec2..d5bd0dc46e 100644 --- a/js/src/jscntxtinlines.h +++ b/js/src/jscntxtinlines.h @@ -278,22 +278,9 @@ CallJSNativeConstructor(JSContext* cx, Native native, const CallArgs& args) * constructor to return the callee, the assertion can be removed or * (another) conjunct can be added to the antecedent. * - * Exceptions: - * - * - Proxies are exceptions to both rules: they can return primitives and - * they allow content to return the callee. - * - * - CallOrConstructBoundFunction is an exception as well because we might - * have used bind on a proxy function. - * - * - new Iterator(x) is user-hookable; it returns x.__iterator__() which - * could be any object. - * - * - (new Object(Object)) returns the callee. + * Exception: (new Object(Object)) returns the callee. */ - MOZ_ASSERT_IF(native != js::proxy_Construct && - native != js::IteratorConstructor && - (!callee->is() || callee->as().native() != obj_construct), + MOZ_ASSERT_IF((!callee->is() || callee->as().native() != obj_construct), args.rval().isObject() && callee != &args.rval().toObject()); return true; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 730805e038..46f89e547e 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -2066,6 +2066,10 @@ JSObject::isCallable() const { if (is()) return true; + if (is()) { + const js::ProxyObject& p = as(); + return p.handler()->isCallable(const_cast(this)); + } return callHook() != nullptr; } @@ -2076,39 +2080,23 @@ JSObject::isConstructor() const const JSFunction& fun = as(); return fun.isConstructor(); } + if (is()) { + const js::ProxyObject& p = as(); + return p.handler()->isConstructor(const_cast(this)); + } return constructHook() != nullptr; } JSNative JSObject::callHook() const { - const js::Class* clasp = getClass(); - - if (JSNative call = clasp->getCall()) - return call; - - if (is()) { - const js::ProxyObject& p = as(); - if (p.handler()->isCallable(const_cast(this))) - return js::proxy_Call; - } - return nullptr; + return getClass()->getCall(); } JSNative JSObject::constructHook() const { - const js::Class* clasp = getClass(); - - if (JSNative construct = clasp->getConstruct()) - return construct; - - if (is()) { - const js::ProxyObject& p = as(); - if (p.handler()->isConstructor(const_cast(this))) - return js::proxy_Construct; - } - return nullptr; + return getClass()->getConstruct(); } bool diff --git a/js/src/proxy/Proxy.cpp b/js/src/proxy/Proxy.cpp index 8f6a262106..984e1f411d 100644 --- a/js/src/proxy/Proxy.cpp +++ b/js/src/proxy/Proxy.cpp @@ -665,24 +665,6 @@ js::proxy_HasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v, b return Proxy::hasInstance(cx, proxy, v, bp); } -bool -js::proxy_Call(JSContext* cx, unsigned argc, Value* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - RootedObject proxy(cx, &args.callee()); - MOZ_ASSERT(proxy->is()); - return Proxy::call(cx, proxy, args); -} - -bool -js::proxy_Construct(JSContext* cx, unsigned argc, Value* vp) -{ - CallArgs args = CallArgsFromVp(argc, vp); - RootedObject proxy(cx, &args.callee()); - MOZ_ASSERT(proxy->is()); - return Proxy::construct(cx, proxy, args); -} - bool js::proxy_GetElements(JSContext* cx, HandleObject proxy, uint32_t begin, uint32_t end, ElementAdder* adder) diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index f97ba99272..ad52234a31 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -457,10 +457,18 @@ js::InternalCallOrConstruct(JSContext* cx, const CallArgs& args, MaybeConstruct /* Invoke non-functions. */ if (MOZ_UNLIKELY(!args.callee().is())) { - MOZ_ASSERT_IF(construct, !args.callee().constructHook()); - JSNative call = args.callee().callHook(); - if (!call) + MOZ_ASSERT_IF(construct, !args.callee().isConstructor()); + + if (!args.callee().isCallable()) return ReportIsNotFunction(cx, args.calleev(), skipForCallee, construct); + + if (args.callee().is()) { + RootedObject proxy(cx, &args.callee()); + return Proxy::call(cx, proxy, args); + } + + JSNative call = args.callee().callHook(); + MOZ_ASSERT(call, "isCallable without a callHook?"); return CallJSNative(cx, call, args); } @@ -579,6 +587,11 @@ InternalConstruct(JSContext* cx, const AnyConstructArgs& args) return true; } + if (callee.is()) { + RootedObject proxy(cx, &callee); + return Proxy::construct(cx, proxy, args); + } + JSNative construct = callee.constructHook(); MOZ_ASSERT(construct != nullptr, "IsConstructor without a construct hook?"); @@ -4846,7 +4859,7 @@ js::SpreadCallOperation(JSContext* cx, HandleScript script, jsbytecode* pc, Hand constructing ? CONSTRUCT : NO_CONSTRUCT); } - if (MOZ_UNLIKELY(!callee.toObject().is()) && !callee.toObject().callHook()) { + if (!callee.toObject().isCallable()) { return ReportIsNotFunction(cx, callee, 2 + constructing, constructing ? CONSTRUCT : NO_CONSTRUCT); } -- cgit v1.2.3 From 6430adfb2d937f4a37bcc0e18aeaae411672582c Mon Sep 17 00:00:00 2001 From: Moonchild Date: Mon, 16 Oct 2023 08:39:28 +0200 Subject: Restore EME WebIDL for proper cleanup later. --- dom/webidl/MediaEncryptedEvent.webidl | 23 ++++++++++++++++ dom/webidl/MediaKeyError.webidl | 19 +++++++++++++ dom/webidl/MediaKeyMessageEvent.webidl | 30 ++++++++++++++++++++ dom/webidl/MediaKeySession.webidl | 47 ++++++++++++++++++++++++++++++++ dom/webidl/MediaKeyStatusMap.webidl | 30 ++++++++++++++++++++ dom/webidl/MediaKeySystemAccess.webidl | 41 ++++++++++++++++++++++++++++ dom/webidl/MediaKeys.webidl | 30 ++++++++++++++++++++ dom/webidl/MediaKeysRequestStatus.webidl | 23 ++++++++++++++++ dom/webidl/WidevineCDMManifest.webidl | 15 ++++++++++ 9 files changed, 258 insertions(+) create mode 100644 dom/webidl/MediaEncryptedEvent.webidl create mode 100644 dom/webidl/MediaKeyError.webidl create mode 100644 dom/webidl/MediaKeyMessageEvent.webidl create mode 100644 dom/webidl/MediaKeySession.webidl create mode 100644 dom/webidl/MediaKeyStatusMap.webidl create mode 100644 dom/webidl/MediaKeySystemAccess.webidl create mode 100644 dom/webidl/MediaKeys.webidl create mode 100644 dom/webidl/MediaKeysRequestStatus.webidl create mode 100644 dom/webidl/WidevineCDMManifest.webidl diff --git a/dom/webidl/MediaEncryptedEvent.webidl b/dom/webidl/MediaEncryptedEvent.webidl new file mode 100644 index 0000000000..28d7a17b79 --- /dev/null +++ b/dom/webidl/MediaEncryptedEvent.webidl @@ -0,0 +1,23 @@ +/* -*- 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 new file mode 100644 index 0000000000..d0dde20320 --- /dev/null +++ b/dom/webidl/MediaKeyError.webidl @@ -0,0 +1,19 @@ +/* -*- 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 new file mode 100644 index 0000000000..057924bb73 --- /dev/null +++ b/dom/webidl/MediaKeyMessageEvent.webidl @@ -0,0 +1,30 @@ +/* -*- 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 new file mode 100644 index 0000000000..8ca5745c44 --- /dev/null +++ b/dom/webidl/MediaKeySession.webidl @@ -0,0 +1,47 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. + * + * The origin of this IDL file is + * https://dvcs.w3.org/hg/html-media/raw-file/default/encrypted-media/encrypted-media.html + * + * Copyright © 2014 W3C® (MIT, ERCIM, Keio, Beihang), All Rights Reserved. + * W3C liability, trademark and document use rules apply. + */ + +[Pref="media.eme.apiVisible"] +interface MediaKeySession : EventTarget { + // error state + readonly attribute MediaKeyError? error; + + // session properties + readonly attribute DOMString keySystem; + readonly attribute DOMString sessionId; + + readonly attribute unrestricted double expiration; + + readonly attribute Promise closed; + + readonly attribute MediaKeyStatusMap keyStatuses; + + attribute EventHandler onkeystatuseschange; + + attribute EventHandler onmessage; + + [NewObject] + Promise generateRequest(DOMString initDataType, BufferSource initData); + + [NewObject] + Promise load(DOMString sessionId); + + // session operations + [NewObject] + Promise update(BufferSource response); + + [NewObject] + Promise close(); + + [NewObject] + Promise remove(); +}; diff --git a/dom/webidl/MediaKeyStatusMap.webidl b/dom/webidl/MediaKeyStatusMap.webidl new file mode 100644 index 0000000000..1f34b5dc7c --- /dev/null +++ b/dom/webidl/MediaKeyStatusMap.webidl @@ -0,0 +1,30 @@ +/* -*- 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; + 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 new file mode 100644 index 0000000000..01552e4490 --- /dev/null +++ b/dom/webidl/MediaKeySystemAccess.webidl @@ -0,0 +1,41 @@ +/* -*- 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 initDataTypes = []; + sequence audioCapabilities = []; + sequence videoCapabilities = []; + MediaKeysRequirement distinctiveIdentifier = "optional"; + MediaKeysRequirement persistentState = "optional"; + sequence sessionTypes; +}; + +[Pref="media.eme.apiVisible"] +interface MediaKeySystemAccess { + readonly attribute DOMString keySystem; + [NewObject] + MediaKeySystemConfiguration getConfiguration(); + [NewObject] + Promise createMediaKeys(); +}; diff --git a/dom/webidl/MediaKeys.webidl b/dom/webidl/MediaKeys.webidl new file mode 100644 index 0000000000..cb84cdab6d --- /dev/null +++ b/dom/webidl/MediaKeys.webidl @@ -0,0 +1,30 @@ +/* -*- 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 setServerCertificate((ArrayBufferView or ArrayBuffer) serverCertificate); +}; diff --git a/dom/webidl/MediaKeysRequestStatus.webidl b/dom/webidl/MediaKeysRequestStatus.webidl new file mode 100644 index 0000000000..737372f664 --- /dev/null +++ b/dom/webidl/MediaKeysRequestStatus.webidl @@ -0,0 +1,23 @@ +/* -*- 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/WidevineCDMManifest.webidl b/dom/webidl/WidevineCDMManifest.webidl new file mode 100644 index 0000000000..83e14e0b0b --- /dev/null +++ b/dom/webidl/WidevineCDMManifest.webidl @@ -0,0 +1,15 @@ +/* -*- 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; +}; -- cgit v1.2.3 From 2b1281f2c91acdcba4d3499d537633607daa7966 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Mon, 16 Oct 2023 10:13:10 -0400 Subject: Backport of Mozilla tooltip bugs: Bug 148624 - only show tooltip when document has focus Partial Bug 1857513 - Use window activeness rather than document.hasFocus() to display chrome-only tooltips --- layout/xul/nsXULTooltipListener.cpp | 81 +++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/layout/xul/nsXULTooltipListener.cpp b/layout/xul/nsXULTooltipListener.cpp index eefeec3599..484919f1f3 100644 --- a/layout/xul/nsXULTooltipListener.cpp +++ b/layout/xul/nsXULTooltipListener.cpp @@ -376,49 +376,52 @@ nsXULTooltipListener::ShowTooltip() return NS_ERROR_FAILURE; // the target node doesn't need a tooltip // set the node in the document that triggered the tooltip and show it - nsCOMPtr xulDoc = - do_QueryInterface(tooltipNode->GetComposedDoc()); - if (xulDoc) { - // Make sure the target node is still attached to some document. - // It might have been deleted. - if (sourceNode->IsInComposedDoc()) { - if (!mIsSourceTree) { - mLastTreeRow = -1; - mLastTreeCol = nullptr; - } + // Make sure the document still has focus. + nsIDocument* doc = tooltipNode->GetComposedDoc(); + if (!doc || !nsContentUtils::IsChromeDoc(doc) || + doc->GetDocumentState().HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE)) { + return NS_OK; + } - mCurrentTooltip = do_GetWeakReference(tooltipNode); - LaunchTooltip(); - mTargetNode = nullptr; + // Make sure the target node is still attached to some document. + // It might have been deleted. + if (sourceNode->IsInComposedDoc()) { + if (!mIsSourceTree) { + mLastTreeRow = -1; + mLastTreeCol = nullptr; + } - nsCOMPtr currentTooltip = do_QueryReferent(mCurrentTooltip); - if (!currentTooltip) - return NS_OK; + mCurrentTooltip = do_GetWeakReference(tooltipNode); + LaunchTooltip(); + mTargetNode = nullptr; - // listen for popuphidden on the tooltip node, so that we can - // be sure DestroyPopup is called even if someone else closes the tooltip - currentTooltip->AddSystemEventListener(NS_LITERAL_STRING("popuphiding"), - this, false, false); - - // listen for mousedown, mouseup, keydown, and DOMMouseScroll events at document level - nsIDocument* doc = sourceNode->GetComposedDoc(); - if (doc) { - // Probably, we should listen to untrusted events for hiding tooltips - // on content since tooltips might disturb something of web - // applications. If we don't specify the aWantsUntrusted of - // AddSystemEventListener(), the event target sets it to TRUE if the - // target is in content. - doc->AddSystemEventListener(NS_LITERAL_STRING("DOMMouseScroll"), - this, true); - doc->AddSystemEventListener(NS_LITERAL_STRING("mousedown"), - this, true); - doc->AddSystemEventListener(NS_LITERAL_STRING("mouseup"), - this, true); - doc->AddSystemEventListener(NS_LITERAL_STRING("keydown"), - this, true); - } - mSourceNode = nullptr; + nsCOMPtr currentTooltip = do_QueryReferent(mCurrentTooltip); + if (!currentTooltip) + return NS_OK; + + // listen for popuphidden on the tooltip node, so that we can + // be sure DestroyPopup is called even if someone else closes the tooltip + currentTooltip->AddSystemEventListener(NS_LITERAL_STRING("popuphiding"), + this, false, false); + + // listen for mousedown, mouseup, keydown, and DOMMouseScroll events at document level + doc = sourceNode->GetComposedDoc(); + if (doc) { + // Probably, we should listen to untrusted events for hiding tooltips + // on content since tooltips might disturb something of web + // applications. If we don't specify the aWantsUntrusted of + // AddSystemEventListener(), the event target sets it to TRUE if the + // target is in content. + doc->AddSystemEventListener(NS_LITERAL_STRING("DOMMouseScroll"), + this, true); + doc->AddSystemEventListener(NS_LITERAL_STRING("mousedown"), + this, true); + doc->AddSystemEventListener(NS_LITERAL_STRING("mouseup"), + this, true); + doc->AddSystemEventListener(NS_LITERAL_STRING("keydown"), + this, true); } + mSourceNode = nullptr; } return NS_OK; -- cgit v1.2.3 From 60b4d804bd8f29582df32db7e862e1e91b221e69 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 17 Oct 2023 16:26:18 +0200 Subject: Issue #1721 - Follow-up: Properly protect GPC header Make it a singleton so it cannot be overwritten. --- netwerk/protocol/http/nsHttpHeaderArray.h | 1 + 1 file changed, 1 insertion(+) diff --git a/netwerk/protocol/http/nsHttpHeaderArray.h b/netwerk/protocol/http/nsHttpHeaderArray.h index b65b36fcdd..0a93e94ff6 100644 --- a/netwerk/protocol/http/nsHttpHeaderArray.h +++ b/netwerk/protocol/http/nsHttpHeaderArray.h @@ -234,6 +234,7 @@ nsHttpHeaderArray::IsSingletonHeader(nsHttpAtom header) header == nsHttp::From || header == nsHttp::Location || header == nsHttp::Max_Forwards || + header == nsHttp::GlobalPrivacyControl || // Ignore-multiple-headers are singletons in the sense that they // shouldn't be merged. IsIgnoreMultipleHeader(header); -- cgit v1.2.3 From 08406731e57a357418190043eaa83e5d27c11dd0 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 17 Oct 2023 12:56:22 +0200 Subject: Issue #2346 - Remove MOZ_EME conditional code --- dom/base/Navigator.cpp | 141 ----------- dom/base/Navigator.h | 12 - dom/base/nsDocument.cpp | 34 --- dom/base/nsDocument.h | 4 - dom/canvas/CanvasRenderingContext2D.cpp | 7 - dom/html/HTMLMediaElement.cpp | 322 +------------------------- dom/html/HTMLMediaElement.h | 37 --- dom/media/AbstractMediaDecoder.h | 3 - dom/media/MediaDecoder.cpp | 24 -- dom/media/MediaDecoder.h | 19 -- dom/media/MediaDecoderOwner.h | 8 - dom/media/MediaDecoderReader.h | 7 - dom/media/MediaDecoderReaderWrapper.h | 4 - dom/media/MediaDecoderStateMachine.cpp | 37 --- dom/media/MediaDecoderStateMachine.h | 7 - dom/media/MediaFormatReader.cpp | 61 +---- dom/media/MediaFormatReader.h | 16 -- dom/media/MediaPrefs.h | 3 - dom/media/fmp4/MP4Decoder.cpp | 3 - dom/media/gmp/GMPChild.cpp | 9 - dom/media/gmp/GMPDecryptorParent.cpp | 8 +- dom/media/gmp/GMPDecryptorProxy.h | 8 - dom/media/gmp/GMPParent.cpp | 56 ----- dom/media/gmp/moz.build | 15 -- dom/media/gtest/MockMediaDecoderOwner.h | 4 - dom/media/mediasource/TrackBuffersManager.cpp | 36 --- dom/media/moz.build | 3 - dom/media/platforms/PDMFactory.cpp | 14 -- dom/media/platforms/PDMFactory.h | 13 -- dom/media/platforms/PlatformDecoderModule.h | 3 - dom/media/platforms/moz.build | 3 - dom/media/webaudio/AudioContext.cpp | 7 - dom/webidl/HTMLMediaElement.webidl | 18 -- dom/webidl/Navigator.webidl | 9 - layout/base/nsLayoutUtils.cpp | 6 - toolkit/forgetaboutsite/ForgetAboutSite.jsm | 11 - 36 files changed, 3 insertions(+), 969 deletions(-) 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(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 -static nsCString -ToCString(const Sequence& 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 -static nsCString -ToCString(const Optional>& 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& aConfigs) -{ - nsCString str; - str.AppendPrintf("Navigator::RequestMediaKeySystemAccess(keySystem='%s' options=", - NS_ConvertUTF16toUTF8(aKeySystem).get()); - str.Append(ToCString(aConfigs)); - str.AppendLiteral(")"); - return str; -} - -already_AddRefed -Navigator::RequestMediaKeySystemAccess(const nsAString& aKeySystem, - const Sequence& aConfigs, - ErrorResult& aRv) -{ - EME_LOG("%s", RequestKeySystemAccessLogString(aKeySystem, aConfigs).get()); - - nsCOMPtr go = do_QueryInterface(mWindow); - RefPtr 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 GetWindowFromGlobal(JSObject* aGlobal); -#ifdef MOZ_EME - already_AddRefed - RequestMediaKeySystemAccess(const nsAString& aKeySystem, - const Sequence& aConfig, - ErrorResult& aRv); -private: - RefPtr 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 domMediaElem(do_QueryInterface(aSupports)); - if (domMediaElem) { - nsCOMPtr content(do_QueryInterface(domMediaElem)); - MOZ_ASSERT(content, "aSupports is not a content"); - HTMLMediaElement* mediaElem = static_cast(content.get()); - bool* contains = static_cast(aContainsEME); - if (mediaElem->GetMediaKeys()) { - *contains = true; - } - } -} - -bool -nsDocument::ContainsEMEContent() -{ - bool containsEME = false; - EnumerateActivityObservers(CheckIfContainsEMEContent, - static_cast(&containsEME)); - return containsEME; -} -#endif // MOZ_EME - static void CheckIfContainsMSEContent(nsISupports* aSupports, void* aContainsMSE) { @@ -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* 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 -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 global = - do_QueryInterface(OwnerDoc()->GetInnerWindow()); - if (!global) { - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - RefPtr 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& 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 event; - if (IsCORSSameOrigin()) { - event = MediaEncryptedEvent::Constructor(this, aInitDataType, aInitData); - } else { - event = MediaEncryptedEvent::Constructor(this); - } - - RefPtr asyncDispatcher = - new AsyncEventDispatcher(this, event); - asyncDispatcher->PostDOMEvent(); -} - -bool -HTMLMediaElement::IsEventAttributeName(nsIAtom* aName) -{ - return aName == nsGkAtoms::onencrypted || - nsGenericHTMLElement::IsEventAttributeName(aName); -} - -already_AddRefed -HTMLMediaElement::GetTopLevelPrincipal() -{ - RefPtr principal; - nsCOMPtr window = OwnerDoc()->GetInnerWindow(); - if (!window) { - return nullptr; - } - // XXXkhuey better hope we always have an outer ... - nsCOMPtr 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 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& aInitData, - const nsAString& aInitDataType) override; - - bool IsEventAttributeName(nsIAtom* aName) override; - - // Returns the principal of the "top level" document; the origin displayed - // in the URL bar of the browser window. - already_AddRefed GetTopLevelPrincipal(); - - bool ContainsRestrictedContent(); -#endif // MOZ_EME - void CannotDecryptWaitingForKey(); bool MozAutoplayEnabled() const @@ -1474,11 +1447,6 @@ protected: // Timer used for updating progress events. nsCOMPtr mProgressTimer; -#ifdef MOZ_EME - // Encrypted Media Extension media keys. - RefPtr 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 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 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::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::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, 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 RequestCDMProxy() const; - - void SetCDMProxy(CDMProxy* aProxy); -#endif - static bool IsOggEnabled(); static bool IsOpusEnabled(); static bool IsWaveEnabled(); @@ -596,11 +582,6 @@ private: RefPtr mResourceCallback; -#ifdef MOZ_EME - MozPromiseHolder mCDMProxyPromiseHolder; - RefPtr 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& 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..218bddc4ac 100644 --- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -1238,11 +1238,7 @@ DecodeMetadataState::OnMetadataRead(MetadataHolder* aMetadata) // 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; @@ -1266,9 +1262,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(Move(mPendingSeek), EventVisibility::Suppressed); } @@ -1581,10 +1574,6 @@ ShutdownState::Enter() // dispose of the timer. master->mVideoDecodeSuspendTimer.Reset(); -#ifdef MOZ_EME - master->mCDMProxyPromise.DisconnectIfExists(); -#endif - if (master->IsPlaying()) { master->StopPlayback(); } @@ -2137,13 +2126,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); @@ -3118,25 +3100,6 @@ void MediaDecoderStateMachine::OnMediaSinkAudioError(nsresult aResult) DecodeError(MediaResult(NS_ERROR_DOM_MEDIA_MEDIASINK_ERR, __func__)); } -#ifdef MOZ_EME -void -MediaDecoderStateMachine::OnCDMProxyReady(RefPtr 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..6391c85740 100644 --- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -767,13 +767,6 @@ private: // Playback will not start when audio is offloading. bool mAudioOffloading; -#ifdef MOZ_EME - void OnCDMProxyReady(RefPtr aProxy); - void OnCDMProxyNotReady(); - RefPtr mCDMProxy; - MozPromiseRequestHolder mCDMProxyPromise; -#endif - private: // The buffered range. Mirrored from the decoder thread. Mirror mBuffered; diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index a658298e2d..2bdd2621ac 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,54 +583,11 @@ MediaFormatReader::InitInternal() return NS_OK; } -#ifdef MOZ_EME -class DispatchKeyNeededEvent : public Runnable { -public: - DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder, - nsTArray& 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 mDecoder; - nsTArray mInitData; - nsString mInitDataType; -}; - -void -MediaFormatReader::SetCDMProxy(CDMProxy* aProxy) -{ - RefPtr proxy = aProxy; - RefPtr self = this; - nsCOMPtr 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 + /* EME stub */ return false; -#endif } RefPtr @@ -746,13 +694,6 @@ MediaFormatReader::OnDemuxerInitDone(nsresult) UniquePtr 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..4e084f4158 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); @@ -587,14 +579,6 @@ private: RefPtr mVideoFrameContainer; layers::ImageContainer* GetImageContainer(); -#ifdef MOZ_EME - RefPtr mCDMProxy; -#endif - -#ifdef MOZ_GMP - RefPtr 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 @@ -101,9 +101,6 @@ private: #ifdef MOZ_GMP 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); 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/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/GMPDecryptorParent.cpp b/dom/media/gmp/GMPDecryptorParent.cpp index 56474e9736..410868c33b 100644 --- a/dom/media/gmp/GMPDecryptorParent.cpp +++ b/dom/media/gmp/GMPDecryptorParent.cpp @@ -45,13 +45,7 @@ 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 + /* EME stub */ return true; } 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 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 @@ -758,48 +742,8 @@ GMPParent::ReadChromiumManifestFile(nsIFile* aFile) RefPtr 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/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/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& 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 sStreamSourceID(0u); -#ifdef MOZ_EME -class DispatchKeyNeededEvent : public Runnable { -public: - DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder, - nsTArray& 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 mDecoder; - nsTArray mInitData; - nsString mInitDataType; -}; -#endif // MOZ_EME - TrackBuffersManager::TrackBuffersManager(MediaSourceDecoder* aParentDecoder, const nsACString& aType) : mInputBuffer(new MediaByteBuffer) @@ -1101,14 +1073,6 @@ TrackBuffersManager::OnDemuxerInitDone(nsresult) UniquePtr 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..389b151994 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" @@ -444,13 +439,4 @@ PDMFactory::GetDecoder(const TrackInfo& aTrackInfo, return pdm.forget(); } -#ifdef MOZ_EME -void -PDMFactory::SetCDMProxy(CDMProxy* aProxy) -{ - RefPtr 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..e288efadd0 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; 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/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/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 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/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 - requestMediaKeySystemAccess(DOMString keySystem, - sequence supportedConfigurations); -}; -#endif - [NoInterfaceObject, Exposed=(Window,Worker)] interface NavigatorConcurrentHardware { readonly attribute unsigned long long hardwareConcurrency; 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/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; -- cgit v1.2.3 From e80bbcfe915e1f6c64a8b44a2e501f8fedfcf659 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 17 Oct 2023 12:59:49 +0200 Subject: Issue #2346 - Remove unused EME components This removes: dom/media/eme code GMP CDM proxies GMP WideVine adapter code EME media platform code GMP clearkey module --- dom/media/eme/CDMCaps.cpp | 169 -- dom/media/eme/CDMCaps.h | 112 -- dom/media/eme/CDMProxy.h | 278 --- dom/media/eme/DecryptorProxyCallback.h | 54 - dom/media/eme/DetailedPromise.cpp | 57 - dom/media/eme/DetailedPromise.h | 57 - dom/media/eme/EMEUtils.cpp | 86 - dom/media/eme/EMEUtils.h | 104 -- dom/media/eme/MediaEncryptedEvent.cpp | 128 -- dom/media/eme/MediaEncryptedEvent.h | 66 - dom/media/eme/MediaKeyError.cpp | 38 - dom/media/eme/MediaKeyError.h | 37 - dom/media/eme/MediaKeyMessageEvent.cpp | 122 -- dom/media/eme/MediaKeyMessageEvent.h | 66 - dom/media/eme/MediaKeySession.cpp | 670 ------- dom/media/eme/MediaKeySession.h | 136 -- dom/media/eme/MediaKeyStatusMap.cpp | 120 -- dom/media/eme/MediaKeyStatusMap.h | 96 - dom/media/eme/MediaKeySystemAccess.cpp | 1041 ----------- dom/media/eme/MediaKeySystemAccess.h | 80 - dom/media/eme/MediaKeySystemAccessManager.cpp | 339 ---- dom/media/eme/MediaKeySystemAccessManager.h | 83 - dom/media/eme/MediaKeys.cpp | 579 ------ dom/media/eme/MediaKeys.h | 167 -- dom/media/eme/moz.build | 41 - dom/media/gmp/GMPCDMCallbackProxy.cpp | 250 --- dom/media/gmp/GMPCDMCallbackProxy.h | 71 - dom/media/gmp/GMPCDMProxy.cpp | 798 -------- dom/media/gmp/GMPCDMProxy.h | 265 --- dom/media/gmp/widevine-adapter/WidevineAdapter.cpp | 168 -- dom/media/gmp/widevine-adapter/WidevineAdapter.h | 59 - .../gmp/widevine-adapter/WidevineDecryptor.cpp | 554 ------ dom/media/gmp/widevine-adapter/WidevineDecryptor.h | 132 -- dom/media/gmp/widevine-adapter/WidevineFileIO.cpp | 97 - dom/media/gmp/widevine-adapter/WidevineFileIO.h | 46 - dom/media/gmp/widevine-adapter/WidevineUtils.cpp | 95 - dom/media/gmp/widevine-adapter/WidevineUtils.h | 73 - .../gmp/widevine-adapter/WidevineVideoDecoder.cpp | 400 ---- .../gmp/widevine-adapter/WidevineVideoDecoder.h | 80 - .../gmp/widevine-adapter/WidevineVideoFrame.cpp | 126 -- .../gmp/widevine-adapter/WidevineVideoFrame.h | 50 - .../widevine-adapter/content_decryption_module.h | 1278 ------------- .../content_decryption_module_export.h | 22 - .../content_decryption_module_ext.h | 64 - dom/media/gmp/widevine-adapter/moz.build | 24 - .../platforms/agnostic/eme/EMEAudioDecoder.cpp | 43 - dom/media/platforms/agnostic/eme/EMEAudioDecoder.h | 36 - .../platforms/agnostic/eme/EMEDecoderModule.cpp | 306 ---- .../platforms/agnostic/eme/EMEDecoderModule.h | 51 - .../platforms/agnostic/eme/EMEVideoDecoder.cpp | 67 - dom/media/platforms/agnostic/eme/EMEVideoDecoder.h | 44 - .../agnostic/eme/SamplesWaitingForKey.cpp | 85 - .../platforms/agnostic/eme/SamplesWaitingForKey.h | 57 - dom/media/platforms/agnostic/eme/moz.build | 22 - media/gmp-clearkey/0.1/AnnexB.cpp | 79 - media/gmp-clearkey/0.1/AnnexB.h | 32 - media/gmp-clearkey/0.1/ArrayUtils.h | 23 - media/gmp-clearkey/0.1/AudioDecoder.cpp | 312 ---- media/gmp-clearkey/0.1/AudioDecoder.h | 73 - media/gmp-clearkey/0.1/BigEndian.h | 68 - media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.cpp | 45 - media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.h | 37 - media/gmp-clearkey/0.1/ClearKeyBase64.cpp | 99 - media/gmp-clearkey/0.1/ClearKeyBase64.h | 28 - .../gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp | 241 --- media/gmp-clearkey/0.1/ClearKeyDecryptionManager.h | 101 - media/gmp-clearkey/0.1/ClearKeyPersistence.cpp | 260 --- media/gmp-clearkey/0.1/ClearKeyPersistence.h | 53 - media/gmp-clearkey/0.1/ClearKeySession.cpp | 94 - media/gmp-clearkey/0.1/ClearKeySession.h | 58 - media/gmp-clearkey/0.1/ClearKeySessionManager.cpp | 418 ----- media/gmp-clearkey/0.1/ClearKeySessionManager.h | 100 - media/gmp-clearkey/0.1/ClearKeyStorage.cpp | 194 -- media/gmp-clearkey/0.1/ClearKeyStorage.h | 48 - media/gmp-clearkey/0.1/ClearKeyUtils.cpp | 541 ------ media/gmp-clearkey/0.1/ClearKeyUtils.h | 114 -- media/gmp-clearkey/0.1/RefCounted.h | 116 -- media/gmp-clearkey/0.1/VideoDecoder.cpp | 455 ----- media/gmp-clearkey/0.1/VideoDecoder.h | 110 -- media/gmp-clearkey/0.1/WMFAACDecoder.cpp | 366 ---- media/gmp-clearkey/0.1/WMFAACDecoder.h | 74 - media/gmp-clearkey/0.1/WMFH264Decoder.cpp | 365 ---- media/gmp-clearkey/0.1/WMFH264Decoder.h | 78 - media/gmp-clearkey/0.1/WMFSymbols.h | 20 - media/gmp-clearkey/0.1/WMFUtils.cpp | 276 --- media/gmp-clearkey/0.1/WMFUtils.h | 269 --- media/gmp-clearkey/0.1/clearkey.info.in | 10 - media/gmp-clearkey/0.1/gmp-clearkey.cpp | 89 - media/gmp-clearkey/0.1/gmp-task-utils-generated.h | 1938 -------------------- media/gmp-clearkey/0.1/gmp-task-utils.h | 47 - media/gmp-clearkey/0.1/gtest/TestClearKeyUtils.cpp | 92 - media/gmp-clearkey/0.1/gtest/moz.build | 14 - media/gmp-clearkey/0.1/moz.build | 74 - media/gmp-clearkey/0.1/openaes/LICENSE | 27 - media/gmp-clearkey/0.1/openaes/oaes_common.h | 77 - media/gmp-clearkey/0.1/openaes/oaes_config.h | 46 - media/gmp-clearkey/0.1/openaes/oaes_lib.c | 1393 -------------- media/gmp-clearkey/0.1/openaes/oaes_lib.h | 168 -- media/gmp-clearkey/0.1/openaes/standard.h | 57 - 99 files changed, 19268 deletions(-) delete mode 100644 dom/media/eme/CDMCaps.cpp delete mode 100644 dom/media/eme/CDMCaps.h delete mode 100644 dom/media/eme/CDMProxy.h delete mode 100644 dom/media/eme/DecryptorProxyCallback.h delete mode 100644 dom/media/eme/DetailedPromise.cpp delete mode 100644 dom/media/eme/DetailedPromise.h delete mode 100644 dom/media/eme/EMEUtils.cpp delete mode 100644 dom/media/eme/EMEUtils.h delete mode 100644 dom/media/eme/MediaEncryptedEvent.cpp delete mode 100644 dom/media/eme/MediaEncryptedEvent.h delete mode 100644 dom/media/eme/MediaKeyError.cpp delete mode 100644 dom/media/eme/MediaKeyError.h delete mode 100644 dom/media/eme/MediaKeyMessageEvent.cpp delete mode 100644 dom/media/eme/MediaKeyMessageEvent.h delete mode 100644 dom/media/eme/MediaKeySession.cpp delete mode 100644 dom/media/eme/MediaKeySession.h delete mode 100644 dom/media/eme/MediaKeyStatusMap.cpp delete mode 100644 dom/media/eme/MediaKeyStatusMap.h delete mode 100644 dom/media/eme/MediaKeySystemAccess.cpp delete mode 100644 dom/media/eme/MediaKeySystemAccess.h delete mode 100644 dom/media/eme/MediaKeySystemAccessManager.cpp delete mode 100644 dom/media/eme/MediaKeySystemAccessManager.h delete mode 100644 dom/media/eme/MediaKeys.cpp delete mode 100644 dom/media/eme/MediaKeys.h delete mode 100644 dom/media/eme/moz.build delete mode 100644 dom/media/gmp/GMPCDMCallbackProxy.cpp delete mode 100644 dom/media/gmp/GMPCDMCallbackProxy.h delete mode 100644 dom/media/gmp/GMPCDMProxy.cpp delete mode 100644 dom/media/gmp/GMPCDMProxy.h delete mode 100644 dom/media/gmp/widevine-adapter/WidevineAdapter.cpp delete mode 100644 dom/media/gmp/widevine-adapter/WidevineAdapter.h delete mode 100644 dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp delete mode 100644 dom/media/gmp/widevine-adapter/WidevineDecryptor.h delete mode 100644 dom/media/gmp/widevine-adapter/WidevineFileIO.cpp delete mode 100644 dom/media/gmp/widevine-adapter/WidevineFileIO.h delete mode 100644 dom/media/gmp/widevine-adapter/WidevineUtils.cpp delete mode 100644 dom/media/gmp/widevine-adapter/WidevineUtils.h delete mode 100644 dom/media/gmp/widevine-adapter/WidevineVideoDecoder.cpp delete mode 100644 dom/media/gmp/widevine-adapter/WidevineVideoDecoder.h delete mode 100644 dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp delete mode 100644 dom/media/gmp/widevine-adapter/WidevineVideoFrame.h delete mode 100644 dom/media/gmp/widevine-adapter/content_decryption_module.h delete mode 100644 dom/media/gmp/widevine-adapter/content_decryption_module_export.h delete mode 100644 dom/media/gmp/widevine-adapter/content_decryption_module_ext.h delete mode 100644 dom/media/gmp/widevine-adapter/moz.build delete mode 100644 dom/media/platforms/agnostic/eme/EMEAudioDecoder.cpp delete mode 100644 dom/media/platforms/agnostic/eme/EMEAudioDecoder.h delete mode 100644 dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp delete mode 100644 dom/media/platforms/agnostic/eme/EMEDecoderModule.h delete mode 100644 dom/media/platforms/agnostic/eme/EMEVideoDecoder.cpp delete mode 100644 dom/media/platforms/agnostic/eme/EMEVideoDecoder.h delete mode 100644 dom/media/platforms/agnostic/eme/SamplesWaitingForKey.cpp delete mode 100644 dom/media/platforms/agnostic/eme/SamplesWaitingForKey.h delete mode 100644 dom/media/platforms/agnostic/eme/moz.build delete mode 100644 media/gmp-clearkey/0.1/AnnexB.cpp delete mode 100644 media/gmp-clearkey/0.1/AnnexB.h delete mode 100644 media/gmp-clearkey/0.1/ArrayUtils.h delete mode 100644 media/gmp-clearkey/0.1/AudioDecoder.cpp delete mode 100644 media/gmp-clearkey/0.1/AudioDecoder.h delete mode 100644 media/gmp-clearkey/0.1/BigEndian.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeyBase64.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeyBase64.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeyDecryptionManager.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeyPersistence.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeyPersistence.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeySession.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeySession.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeySessionManager.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeySessionManager.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeyStorage.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeyStorage.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeyUtils.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeyUtils.h delete mode 100644 media/gmp-clearkey/0.1/RefCounted.h delete mode 100644 media/gmp-clearkey/0.1/VideoDecoder.cpp delete mode 100644 media/gmp-clearkey/0.1/VideoDecoder.h delete mode 100644 media/gmp-clearkey/0.1/WMFAACDecoder.cpp delete mode 100644 media/gmp-clearkey/0.1/WMFAACDecoder.h delete mode 100644 media/gmp-clearkey/0.1/WMFH264Decoder.cpp delete mode 100644 media/gmp-clearkey/0.1/WMFH264Decoder.h delete mode 100644 media/gmp-clearkey/0.1/WMFSymbols.h delete mode 100644 media/gmp-clearkey/0.1/WMFUtils.cpp delete mode 100644 media/gmp-clearkey/0.1/WMFUtils.h delete mode 100644 media/gmp-clearkey/0.1/clearkey.info.in delete mode 100644 media/gmp-clearkey/0.1/gmp-clearkey.cpp delete mode 100644 media/gmp-clearkey/0.1/gmp-task-utils-generated.h delete mode 100644 media/gmp-clearkey/0.1/gmp-task-utils.h delete mode 100644 media/gmp-clearkey/0.1/gtest/TestClearKeyUtils.cpp delete mode 100644 media/gmp-clearkey/0.1/gtest/moz.build delete mode 100644 media/gmp-clearkey/0.1/moz.build delete mode 100644 media/gmp-clearkey/0.1/openaes/LICENSE delete mode 100644 media/gmp-clearkey/0.1/openaes/oaes_common.h delete mode 100644 media/gmp-clearkey/0.1/openaes/oaes_config.h delete mode 100644 media/gmp-clearkey/0.1/openaes/oaes_lib.c delete mode 100644 media/gmp-clearkey/0.1/openaes/oaes_lib.h delete mode 100644 media/gmp-clearkey/0.1/openaes/standard.h 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& 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& aOutKeyStatuses) -{ - for (const KeyStatus& keyStatus : mData.mKeyStatuses) { - if (keyStatus.mSessionId.Equals(aSessionId)) { - aOutKeyStatuses.AppendElement(keyStatus); - } - } -} - -void -CDMCaps::AutoLock::GetSessionIdsForKeyId(const CencKeyId& aKeyId, - nsTArray& 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 statuses; - GetKeyStatusesForSession(aSessionId, statuses); - for (const KeyStatus& status : statuses) { - changed |= SetKeyStatus(status.mId, - aSessionId, - dom::Optional()); - } - 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& aStatus); - - void GetKeyStatusesForSession(const nsAString& aSessionId, - nsTArray& aOutKeyStatuses); - - void GetSessionIdsForKeyId(const CencKeyId& aKeyId, - nsTArray& 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 mListener; - }; - - Monitor mMonitor; - - nsTArray mKeyStatuses; - - nsTArray 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 mSample; -}; - -class CDMKeyInfo { -public: - explicit CDMKeyInfo(const nsTArray& aKeyId) - : mKeyId(aKeyId) - , mStatus() - {} - - CDMKeyInfo(const nsTArray& aKeyId, - const dom::Optional& aStatus) - : mKeyId(aKeyId) - , mStatus(aStatus.Value()) - {} - - // The copy-ctor and copy-assignment operator for Optional 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 mKeyId; - dom::Optional 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 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& 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& 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& 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& 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 Decrypt(MediaRawData* aSample) = 0; - - // Owner thread only. - virtual void OnDecrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray& 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& aKeyId, - nsTArray& 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 MainThreadOnlyRawPtr { - public: - explicit MainThreadOnlyRawPtr(Type* aPtr) - : mPtr(aPtr) - { - MOZ_ASSERT(NS_IsMainThread()); - } - - bool IsNull() const { - MOZ_ASSERT(NS_IsMainThread()); - return !mPtr; - } - - void Clear() { - MOZ_ASSERT(NS_IsMainThread()); - mPtr = nullptr; - } - - Type* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { - MOZ_ASSERT(NS_IsMainThread()); - return mPtr; - } - private: - Type* mPtr; - }; - - // Our reference back to the MediaKeys object. - // WARNING: This is a non-owning reference that is cleared by MediaKeys - // destructor. only use on main thread, and always nullcheck before using! - MainThreadOnlyRawPtr mKeys; - - const 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 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& 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& aDecryptedData) = 0; - - virtual void BatchedKeyStatusChanged(const nsCString& aSessionId, - const nsTArray& 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::Create(nsIGlobalObject* aGlobal, - ErrorResult& aRv, - const nsACString& aName) -{ - RefPtr 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 - Create(nsIGlobalObject* aGlobal, - ErrorResult& aRv, - const nsACString& aName); - - template - void MaybeResolve(const T& aArg) - { - EME_LOG("%s promise resolved", mName.get()); - Promise::MaybeResolve(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& 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& 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& aOutData); - -// Overload for ArrayBuffer -void CopyArrayBufferViewOrArrayBufferData(const dom::ArrayBuffer& aBufferOrView, - nsTArray& 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& 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 aGivenProto) -{ - return MediaEncryptedEventBinding::Wrap(aCx, this, aGivenProto); -} - -already_AddRefed -MediaEncryptedEvent::Constructor(EventTarget* aOwner) -{ - RefPtr e = new MediaEncryptedEvent(aOwner); - e->InitEvent(NS_LITERAL_STRING("encrypted"), false, false); - e->SetTrusted(true); - return e.forget(); -} - -already_AddRefed -MediaEncryptedEvent::Constructor(EventTarget* aOwner, - const nsAString& aInitDataType, - const nsTArray& aInitData) -{ - RefPtr e = new MediaEncryptedEvent(aOwner); - e->InitEvent(NS_LITERAL_STRING("encrypted"), false, false); - e->mInitDataType = aInitDataType; - e->mRawInitData = aInitData; - e->SetTrusted(true); - return e.forget(); -} - -already_AddRefed -MediaEncryptedEvent::Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyNeededEventInit& aEventInitDict, - ErrorResult& aRv) -{ - nsCOMPtr owner = do_QueryInterface(aGlobal.GetAsSupports()); - RefPtr 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 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 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 mInitData; - -public: - - JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle aGivenProto) override; - - static already_AddRefed - Constructor(EventTarget* aOwner); - - static already_AddRefed - Constructor(EventTarget* aOwner, - const nsAString& aInitDataType, - const nsTArray& aInitData); - - static already_AddRefed - Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyNeededEventInit& aEventInitDict, - ErrorResult& aRv); - - void GetInitDataType(nsString& aRetVal) const; - - void GetInitData(JSContext* cx, - JS::MutableHandle aData, - ErrorResult& aRv); -private: - nsTArray mRawInitData; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_MediaKeyNeededEvent_h__ diff --git a/dom/media/eme/MediaKeyError.cpp b/dom/media/eme/MediaKeyError.cpp deleted file mode 100644 index 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 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 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 aGivenProto) -{ - return MediaKeyMessageEventBinding::Wrap(aCx, this, aGivenProto); -} - -already_AddRefed -MediaKeyMessageEvent::Constructor(EventTarget* aOwner, - MediaKeyMessageType aMessageType, - const nsTArray& aMessage) -{ - RefPtr e = new MediaKeyMessageEvent(aOwner); - e->InitEvent(NS_LITERAL_STRING("message"), false, false); - e->mMessageType = aMessageType; - e->mRawMessage = aMessage; - e->SetTrusted(true); - return e.forget(); -} - -already_AddRefed -MediaKeyMessageEvent::Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyMessageEventInit& aEventInitDict, - ErrorResult& aRv) -{ - nsCOMPtr owner = do_QueryInterface(aGlobal.GetAsSupports()); - RefPtr e = new MediaKeyMessageEvent(owner); - bool trusted = e->Init(owner); - e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable); - nsTArray 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 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 mMessage; - -public: - virtual MediaKeyMessageEvent* AsMediaKeyMessageEvent(); - - JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle aGivenProto) override; - - static already_AddRefed - Constructor(EventTarget* aOwner, - MediaKeyMessageType aMessageType, - const nsTArray& aMessage); - - static already_AddRefed - Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyMessageEventInit& aEventInitDict, - ErrorResult& aRv); - - MediaKeyMessageType MessageType() const { return mMessageType; } - - void GetMessage(JSContext* cx, - JS::MutableHandle aMessage, - ErrorResult& aRv); - -private: - nsTArray mRawMessage; -}; - - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_MediaKeyMessageEvent_h__ diff --git a/dom/media/eme/MediaKeySession.cpp b/dom/media/eme/MediaKeySession.cpp deleted file mode 100644 index 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 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 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::type; - for (const CDMCaps::KeyStatus& status : keyStatuses) { - message.Append(nsPrintfCString(" (%s,%s)", ToBase64(status.mId).get(), - MediaKeyStatusValues::strings[static_cast(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& 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> 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(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 -MediaKeySession::GenerateRequest(const nsAString& aInitDataType, - const ArrayBufferViewOrArrayBuffer& aInitData, - ErrorResult& aRv) -{ - RefPtr 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 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 -MediaKeySession::Load(const nsAString& aSessionId, ErrorResult& aRv) -{ - RefPtr 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 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 -MediaKeySession::Update(const ArrayBufferViewOrArrayBuffer& aResponse, ErrorResult& aRv) -{ - RefPtr 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 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 -MediaKeySession::Close(ErrorResult& aRv) -{ - RefPtr 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 -MediaKeySession::Remove(ErrorResult& aRv) -{ - RefPtr 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& 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 event( - MediaKeyMessageEvent::Constructor(this, aMessageType, aMessage)); - RefPtr 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 event(new MediaKeyError(this, aSystemCode)); - RefPtr asyncDispatcher = - new AsyncEventDispatcher(this, event); - asyncDispatcher->PostDOMEvent(); -} - -void -MediaKeySession::DispatchKeyStatusesChange() -{ - if (IsClosed()) { - return; - } - - UpdateKeyStatusMap(); - - RefPtr asyncDispatcher = - new AsyncEventDispatcher(this, NS_LITERAL_STRING("keystatuseschange"), false); - asyncDispatcher->PostDOMEvent(); -} - -uint32_t -MediaKeySession::Token() const -{ - return mToken; -} - -already_AddRefed -MediaKeySession::MakePromise(ErrorResult& aRv, const nsACString& aName) -{ - nsCOMPtr 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 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 GenerateRequest(const nsAString& aInitDataType, - const ArrayBufferViewOrArrayBuffer& aInitData, - ErrorResult& aRv); - - already_AddRefed Load(const nsAString& aSessionId, - ErrorResult& aRv); - - already_AddRefed Update(const ArrayBufferViewOrArrayBuffer& response, - ErrorResult& aRv); - - already_AddRefed Close(ErrorResult& aRv); - - already_AddRefed Remove(ErrorResult& aRv); - - void DispatchKeyMessage(MediaKeyMessageType aMessageType, - const nsTArray& aMessage); - - void DispatchKeyError(uint32_t system_code); - - void DispatchKeyStatusesChange(); - - void OnClosed(); - - bool IsClosed() const; - - 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 MakePromise(ErrorResult& aRv, - const nsACString& aName); - - RefPtr mClosed; - - RefPtr mMediaKeyError; - RefPtr mKeys; - const nsString mKeySystem; - nsString mSessionId; - const MediaKeySessionType mSessionType; - const uint32_t mToken; - bool mIsClosed; - bool mUninitialized; - RefPtr 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 aGivenProto) -{ - return MediaKeyStatusMapBinding::Wrap(aCx, this, aGivenProto); -} - -nsPIDOMWindowInner* -MediaKeyStatusMap::GetParentObject() const -{ - return mParent; -} - -void -MediaKeyStatusMap::Get(JSContext* aCx, - const ArrayBufferViewOrArrayBuffer& aKey, - JS::MutableHandle 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 -MediaKeyStatusMap::GetKeyAtIndex(uint32_t aIndex) const -{ - MOZ_ASSERT(aIndex < GetIterableLength()); - return TypedArrayCreator(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& 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 aGivenProto) override; - - void Get(JSContext* aCx, - const ArrayBufferViewOrArrayBuffer& aKey, - JS::MutableHandle aOutValue, - ErrorResult& aOutRv) const; - bool Has(const ArrayBufferViewOrArrayBuffer& aKey) const; - uint32_t Size() const; - - uint32_t GetIterableLength() const; - TypedArrayCreator GetKeyAtIndex(uint32_t aIndex) const; - MediaKeyStatus GetValueAtIndex(uint32_t aIndex) const; - - void Update(const nsTArray& keys); - -private: - - nsCOMPtr mParent; - - struct KeyStatus { - KeyStatus(const nsTArray& 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& other = aOther.mKeyId; - const nsTArray& self = mKeyId; - size_t length = std::min(other.Length(), self.Length()); - int cmp = memcmp(self.Elements(), other.Elements(), length); - if (cmp != 0) { - return cmp < 0; - } - return self.Length() <= other.Length(); - } - nsTArray mKeyId; - MediaKeyStatus mStatus; - }; - - nsTArray 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 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 -MediaKeySystemAccess::CreateMediaKeys(ErrorResult& aRv) -{ - RefPtr 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 mCodecsDecoded; - nsTArray mCodecsDecrypted; -}; - -enum class KeySystemFeatureSupport -{ - Prohibited = 1, - Requestable = 2, - Required = 3, -}; - -struct KeySystemConfig -{ - nsString mKeySystem; - nsTArray mInitDataTypes; - KeySystemFeatureSupport mPersistentState = KeySystemFeatureSupport::Prohibited; - KeySystemFeatureSupport mDistinctiveIdentifier = KeySystemFeatureSupport::Prohibited; - nsTArray mSessionTypes; - nsTArray mVideoRobustness; - nsTArray mAudioRobustness; - KeySystemContainerSupport mMP4; - KeySystemContainerSupport mWebM; -}; - -static nsTArray -GetSupportedKeySystems() -{ - nsTArray 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& 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(MediaKeySessionType::Temporary)].value; - if (aSessionType.EqualsASCII(temporary)) { - aOutType = MediaKeySessionType::Temporary; - return true; - } - const char* persistentLicense = - strings[static_cast(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& 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 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 -GetSupportedCapabilities(const CodecType aCodecType, - const nsTArray& 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 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(); - } - // If content type is an invalid or unrecognized MIME type, continue - // to the next iteration. - nsAutoString container; - nsTArray 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 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(); - } - - // 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 -UnboxSessionTypes(const Optional>& aSessionTypes) -{ - Sequence sessionTypes; - if (aSessionTypes.WasPassed()) { - sessionTypes = aSessionTypes.Value(); - } else { - using MediaKeySessionTypeValues::strings; - const char* temporary = strings[static_cast(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 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 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 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 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& 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 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 aGivenProto) override; - - void GetKeySystem(nsString& aRetVal) const; - - void GetConfiguration(MediaKeySystemConfiguration& aConfig); - - already_AddRefed CreateMediaKeys(ErrorResult& aRv); - - static MediaKeySystemStatus GetKeySystemStatus(const nsAString& aKeySystem, - nsACString& aOutExceptionMessage); - - static bool IsSupported(const nsAString& aKeySystem, - const Sequence& aConfigs, - DecoderDoctorDiagnostics* aDiagnostics); - - static void NotifyObservers(nsPIDOMWindowInner* aWindow, - const nsAString& aKeySystem, - MediaKeySystemStatus aStatus); - - static bool GetSupportedConfig(const nsAString& aKeySystem, - const Sequence& aConfigs, - MediaKeySystemConfiguration& aOutConfig, - DecoderDoctorDiagnostics* aDiagnostics); - - static bool KeySystemSupportsInitDataType(const nsAString& aKeySystem, - const nsAString& aInitDataType); - -private: - nsCOMPtr 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& aConfigs) -{ - Request(aPromise, aKeySystem, aConfigs, RequestType::Initial); -} - -void -MediaKeySystemAccessManager::Request(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence& 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 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& 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& aConfigs) -{ - EME_LOG("MediaKeySystemAccessManager::AwaitInstall %s", NS_ConvertUTF16toUTF8(aKeySystem).get()); - - if (!EnsureObserversAdded()) { - NS_WARNING("Failed to add pref observer"); - return false; - } - - nsCOMPtr timer(do_CreateInstance("@mozilla.org/timer;1")); - if (!timer || NS_FAILED(timer->Init(this, 60 * 1000, nsITimer::TYPE_ONE_SHOT))) { - NS_WARNING("Failed to create timer to await CDM install."); - return false; - } - - mRequests.AppendElement(PendingRequest(aPromise, aKeySystem, 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 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 timer(do_QueryInterface(aSubject)); - for (size_t i = 0; i < mRequests.Length(); i++) { - if (mRequests[i].mTimer == timer) { - EME_LOG("MediaKeySystemAccessManager::AwaitInstall resuming request"); - PendingRequest request = mRequests[i]; - mRequests.RemoveElementAt(i); - RetryRequest(request); - break; - } - } - } - return NS_OK; -} - -bool -MediaKeySystemAccessManager::EnsureObserversAdded() -{ - if (mAddedObservers) { - return true; - } - - nsCOMPtr obsService = mozilla::services::GetObserverService(); - if (NS_WARN_IF(!obsService)) { - return false; - } - mAddedObservers = NS_SUCCEEDED(obsService->AddObserver(this, "gmp-changed", false)); - return mAddedObservers; -} - -void -MediaKeySystemAccessManager::Shutdown() -{ - EME_LOG("MediaKeySystemAccessManager::Shutdown"); - nsTArray requests(Move(mRequests)); - for (PendingRequest& request : requests) { - // Cancel all requests; we're shutting down. - request.CancelTimer(); - request.RejectPromise(NS_LITERAL_CSTRING("Promise still outstanding at MediaKeySystemAccessManager shutdown")); - } - if (mAddedObservers) { - nsCOMPtr 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& aConfig); - - void Shutdown(); - - struct PendingRequest { - PendingRequest(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence& aConfig, - nsITimer* aTimer); - PendingRequest(const PendingRequest& aOther); - ~PendingRequest(); - void CancelTimer(); - void RejectPromise(const nsCString& aReason); - - RefPtr mPromise; - const nsString mKeySystem; - const Sequence mConfigs; - nsCOMPtr mTimer; - }; - -private: - - enum RequestType { - Initial, - Subsequent - }; - - void Request(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence& aConfig, - RequestType aType); - - ~MediaKeySystemAccessManager(); - - bool EnsureObserversAdded(); - - bool AwaitInstall(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence& aConfig); - - void RetryRequest(PendingRequest& aRequest); - - nsTArray mRequests; - - nsCOMPtr mWindow; - bool mAddedObservers; -}; - -} // namespace dom -} // namespace mozilla - -#endif diff --git a/dom/media/eme/MediaKeys.cpp b/dom/media/eme/MediaKeys.cpp deleted file mode 100644 index 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& session = iter.Data(); - keySessions.Put(session->GetSessionId(), session); - } - for (auto iter = keySessions.Iter(); !iter.Done(); iter.Next()) { - RefPtr& 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 kungFuDeathGrip = this; - - for (auto iter = mPromises.Iter(); !iter.Done(); iter.Next()) { - RefPtr& 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 aGivenProto) -{ - return MediaKeysBinding::Wrap(aCx, this, aGivenProto); -} - -void -MediaKeys::GetKeySystem(nsString& aOutKeySystem) const -{ - aOutKeySystem.Assign(mKeySystem); -} - -already_AddRefed -MediaKeys::SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aCert, ErrorResult& aRv) -{ - RefPtr 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 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 -MediaKeys::MakePromise(ErrorResult& aRv, const nsACString& aName) -{ - nsCOMPtr 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 -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 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 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 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 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 - 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 mMediaKeys; -}; - -already_AddRefed -MediaKeys::CreateCDMProxy() -{ - RefPtr proxy; - { - proxy = new GMPCDMProxy(this, - mKeySystem, - new MediaKeysGMPCrashHelper(this), - mConfig.mDistinctiveIdentifier == MediaKeysRequirement::Required, - mConfig.mPersistentState == MediaKeysRequirement::Required); - } - return proxy.forget(); -} - -already_AddRefed -MediaKeys::Init(ErrorResult& aRv) -{ - RefPtr 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 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 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 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 promise(RetrievePromise(aId)); - if (!promise) { - return; - } - mNodeId = aNodeId; - RefPtr 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(aSessionType)].value; - for (const nsString& s : aConfig.mSessionTypes.Value()) { - if (s.EqualsASCII(sessionType)) { - return true; - } - } - return false; -} - -already_AddRefed -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 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 promise(RetrievePromise(aId)); - if (!promise) { - return; - } - EME_LOG("MediaKeys[%p]::OnSessionLoaded() resolve promise id=%d", this, aId); - - promise->MaybeResolve(aSuccess); -} - -void -MediaKeys::OnSessionClosed(MediaKeySession* aSession) -{ - nsAutoString id; - aSession->GetSessionId(id); - mKeySessions.Remove(id); -} - -already_AddRefed -MediaKeys::GetSession(const nsAString& aSessionId) -{ - RefPtr session; - mKeySessions.Get(aSessionId, getter_AddRefs(session)); - return session.forget(); -} - -already_AddRefed -MediaKeys::GetPendingSession(uint32_t aToken) -{ - RefPtr 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 KeySessionHashMap; -typedef nsRefPtrHashtable PromiseHashMap; -typedef nsRefPtrHashtable PendingKeySessionsHashMap; -typedef nsDataHashtable 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(); - -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 Init(ErrorResult& aRv); - - nsPIDOMWindowInner* GetParentObject() const; - - JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - nsresult Bind(HTMLMediaElement* aElement); - void Unbind(); - - // Javascript: readonly attribute DOMString keySystem; - void GetKeySystem(nsString& retval) const; - - // JavaScript: MediaKeys.createSession() - already_AddRefed CreateSession(JSContext* aCx, - MediaKeySessionType aSessionType, - ErrorResult& aRv); - - // JavaScript: MediaKeys.SetServerCertificate() - already_AddRefed - SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aServerCertificate, - ErrorResult& aRv); - - already_AddRefed GetSession(const nsAString& aSessionId); - - // Removes and returns MediaKeySession from the set of sessions awaiting - // their sessionId to be assigned. - already_AddRefed GetPendingSession(uint32_t aToken); - - // Called once a Init() operation succeeds. - void OnCDMCreated(PromiseId aId, - const nsACString& aNodeId, const 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 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 CreateCDMProxy(); - - // Removes promise from mPromises, and returns it. - already_AddRefed RetrievePromise(PromiseId aId); - - // Owning ref to proxy. The proxy has a weak reference back to the MediaKeys, - // and the MediaKeys destructor clears the proxy's reference to the MediaKeys. - RefPtr mProxy; - - RefPtr mElement; - - nsCOMPtr mParent; - const nsString mKeySystem; - nsCString mNodeId; - KeySessionHashMap mKeySessions; - PromiseHashMap mPromises; - PendingKeySessionsHashMap mPendingSessions; - PromiseId mCreatePromiseId; - - RefPtr mPrincipal; - RefPtr 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/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 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 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 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 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& aMessage) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr proxy = mProxy; - auto sid = NS_ConvertUTF8toUTF16(aSessionId); - nsTArray 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 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 proxy = mProxy; - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, sid] () - { - proxy->OnKeyStatusesChange(sid); - }) - ); - } - - RefPtr 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 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& aKeyInfos) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - BatchedKeyStatusChangedInternal(aSessionId, aKeyInfos); -} - -void -GMPCDMCallbackProxy::BatchedKeyStatusChangedInternal(const nsCString& aSessionId, - const nsTArray& 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 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& aDecryptedData) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - mProxy->OnDecrypted(aId, aResult, aDecryptedData); -} - -void -GMPCDMCallbackProxy::Terminated() -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr 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& 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& aDecryptedData) override; - - void BatchedKeyStatusChanged(const nsCString& aSessionId, - const nsTArray& aKeyInfos) override; - - void Terminated() override; - - ~GMPCDMCallbackProxy() {} - -private: - friend class GMPCDMProxy; - explicit GMPCDMCallbackProxy(CDMProxy* aProxy); - - void BatchedKeyStatusChangedInternal(const nsCString& aSessionId, - const nsTArray& 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 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 data(new InitData()); - data->mPromiseId = aPromiseId; - data->mOrigin = aOrigin; - data->mTopLevelOrigin = aTopLevelOrigin; - data->mGMPName = aGMPName; - data->mInPrivateBrowsing = aInPrivateBrowsing; - data->mCrashHelper = mCrashHelper; - nsCOMPtr task( - NewRunnableMethod>(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&& 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 task( - NewRunnableMethod(this, - &GMPCDMProxy::OnCDMCreated, - mCreatePromiseId)); - NS_DispatchToMainThread(task); -} - -class gmp_InitDoneCallback : public GetGMPDecryptorCallback -{ -public: - gmp_InitDoneCallback(GMPCDMProxy* aGMPCDMProxy, - nsAutoPtr&& aData) - : mGMPCDMProxy(aGMPCDMProxy), - mData(Move(aData)) - { - } - - void Done(GMPDecryptorProxy* aCDM) - { - mGMPCDMProxy->gmp_InitDone(aCDM, Move(mData)); - } - -private: - RefPtr mGMPCDMProxy; - nsAutoPtr mData; -}; - -class gmp_InitGetGMPDecryptorCallback : public GetNodeIdCallback -{ -public: - gmp_InitGetGMPDecryptorCallback(GMPCDMProxy* aGMPCDMProxy, - nsAutoPtr&& aData) - : mGMPCDMProxy(aGMPCDMProxy), - mData(aData) - { - } - - void Done(nsresult aResult, const nsACString& aNodeId) - { - mGMPCDMProxy->gmp_InitGetGMPDecryptor(aResult, aNodeId, Move(mData)); - } - -private: - RefPtr mGMPCDMProxy; - nsAutoPtr mData; -}; - -void -GMPCDMProxy::gmp_Init(nsAutoPtr&& aData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - - nsCOMPtr 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 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&& 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 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 tags; - tags.AppendElement(NS_ConvertUTF16toUTF8(mKeySystem)); - - // Note: must capture helper refptr here, before the Move() - // when we create the GetGMPDecryptorCallback below. - RefPtr crashHelper = Move(aData->mCrashHelper); - UniquePtr 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& aInitData) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mOwnerThread); - - nsAutoPtr data(new CreateSessionData()); - data->mSessionType = aSessionType; - data->mCreateSessionToken = aCreateSessionToken; - data->mPromiseId = aPromiseId; - data->mInitDataType = NS_ConvertUTF16toUTF8(aInitDataType); - data->mInitData = Move(aInitData); - - nsCOMPtr task( - NewRunnableMethod>(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 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 data(new SessionOpData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - nsCOMPtr task( - NewRunnableMethod>(this, &GMPCDMProxy::gmp_LoadSession, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -GMPCDMProxy::gmp_LoadSession(nsAutoPtr 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& aCert) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mOwnerThread); - - nsAutoPtr data(new SetServerCertificateData()); - data->mPromiseId = aPromiseId; - data->mCert = Move(aCert); - nsCOMPtr task( - NewRunnableMethod>(this, &GMPCDMProxy::gmp_SetServerCertificate, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -GMPCDMProxy::gmp_SetServerCertificate(nsAutoPtr 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& aResponse) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mOwnerThread); - NS_ENSURE_TRUE_VOID(!mKeys.IsNull()); - - nsAutoPtr data(new UpdateSessionData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - data->mResponse = Move(aResponse); - nsCOMPtr task( - NewRunnableMethod>(this, &GMPCDMProxy::gmp_UpdateSession, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -GMPCDMProxy::gmp_UpdateSession(nsAutoPtr 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 data(new SessionOpData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - nsCOMPtr task( - NewRunnableMethod>(this, &GMPCDMProxy::gmp_CloseSession, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -GMPCDMProxy::gmp_CloseSession(nsAutoPtr 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 data(new SessionOpData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - nsCOMPtr task( - NewRunnableMethod>(this, &GMPCDMProxy::gmp_RemoveSession, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -GMPCDMProxy::gmp_RemoveSession(nsAutoPtr 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 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 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 task; - task = NewRunnableMethod(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 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& aMessage) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - RefPtr 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 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 session(mKeys->GetSession(aSessionId)); - if (session) { - session->SetExpiration(static_cast(aExpiryTime)); - } -} - -void -GMPCDMProxy::OnSessionClosed(const nsAString& aSessionId) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - RefPtr session(mKeys->GetSession(aSessionId)); - if (session) { - session->OnClosed(); - } -} - -void -GMPCDMProxy::OnDecrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray& aDecryptedData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - gmp_Decrypted(aId, aResult, aDecryptedData); -} - -static void -LogToConsole(const nsAString& aMsg) -{ - nsCOMPtr console( - do_GetService("@mozilla.org/consoleservice;1")); - if (!console) { - NS_WARNING("Failed to log message to console."); - return; - } - nsAutoString msg(aMsg); - console->LogStringMessage(msg.get()); -} - -void -GMPCDMProxy::OnSessionError(const nsAString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsAString& aMsg) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - RefPtr 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::Decrypt(MediaRawData* aSample) -{ - RefPtr job(new DecryptJob(aSample)); - RefPtr promise(job->Ensure()); - - nsCOMPtr task( - NewRunnableMethod>(this, &GMPCDMProxy::gmp_Decrypt, job)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); - return promise; -} - -void -GMPCDMProxy::gmp_Decrypt(RefPtr aJob) -{ - MOZ_ASSERT(IsOnOwnerThread()); - - if (!mCDM) { - aJob->PostResult(AbortedErr); - return; - } - - aJob->mId = ++mDecryptionJobCount; - nsTArray 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& 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 empty; - PostResult(aResult, empty); -} - -void -GMPCDMProxy::DecryptJob::PostResult(DecryptStatus aResult, - const nsTArray& aDecryptedData) -{ - if (aDecryptedData.Length() != mSample->Size()) { - NS_WARNING("CDM returned incorrect number of decrypted bytes"); - } - if (aResult == Ok) { - nsAutoPtr writer(mSample->CreateWriter()); - PodCopy(writer->Data(), - aDecryptedData.Elements(), - std::min(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& aKeyId, - nsTArray& 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 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& aInitData) override; - - void LoadSession(PromiseId aPromiseId, - const nsAString& aSessionId) override; - - void SetServerCertificate(PromiseId aPromiseId, - nsTArray& aCert) override; - - void UpdateSession(const nsAString& aSessionId, - PromiseId aPromiseId, - nsTArray& 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& 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 Decrypt(MediaRawData* aSample) override; - - void OnDecrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray& 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& aKeyId, - nsTArray& 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 mCrashHelper; - bool mInPrivateBrowsing; - }; - - // GMP thread only. - void gmp_Init(nsAutoPtr&& aData); - void gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr&& aData); - void gmp_InitGetGMPDecryptor(nsresult aResult, - const nsACString& aNodeId, - nsAutoPtr&& 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 mInitData; - }; - // GMP thread only. - void gmp_CreateSession(nsAutoPtr aData); - - struct SessionOpData { - PromiseId mPromiseId; - nsCString mSessionId; - }; - // GMP thread only. - void gmp_LoadSession(nsAutoPtr aData); - - struct SetServerCertificateData { - PromiseId mPromiseId; - nsTArray mCert; - }; - // GMP thread only. - void gmp_SetServerCertificate(nsAutoPtr aData); - - struct UpdateSessionData { - PromiseId mPromiseId; - nsCString mSessionId; - nsTArray mResponse; - }; - // GMP thread only. - void gmp_UpdateSession(nsAutoPtr aData); - - // GMP thread only. - void gmp_CloseSession(nsAutoPtr aData); - - // GMP thread only. - void gmp_RemoveSession(nsAutoPtr aData); - - class DecryptJob { - public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DecryptJob) - - explicit DecryptJob(MediaRawData* aSample) - : mId(0) - , mSample(aSample) - { - } - - void PostResult(DecryptStatus aResult, - const nsTArray& aDecryptedData); - void PostResult(DecryptStatus aResult); - - RefPtr Ensure() { - return mPromise.Ensure(__func__); - } - - uint32_t mId; - RefPtr mSample; - private: - ~DecryptJob() {} - MozPromiseHolder mPromise; - }; - // GMP thread only. - void gmp_Decrypt(RefPtr aJob); - - // GMP thread only. - void gmp_Decrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray& 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 mProxy; - PromiseId mId; - nsresult mCode; - nsCString mReason; - }; - - ~GMPCDMProxy(); - - GMPCrashHelper* mCrashHelper; - - GMPDecryptorProxy* mCDM; - - nsAutoPtr mCallback; - - // Decryption jobs sent to CDM, awaiting result. - // GMP thread only. - nsTArray> mDecryptionJobs; - - // Number of buffers we've decrypted. Used to uniquely identify - // decryption jobs sent to CDM. Note we can't just use the length of - // mDecryptionJobs as that shrinks as jobs are completed and removed - // from it. - // GMP thread only. - uint32_t mDecryptionJobCount; - - // 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/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(aUserData); - MOZ_ASSERT(decryptor); - return static_cast(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( - 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( - 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( - 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 wrapper(new CDMWrapper(cdm, decryptor)); - decryptor->SetCDM(wrapper, aDecryptorId); - *aPluginAPI = decryptor; - - } else if (!strcmp(aAPIName, GMP_API_VIDEO_DECODER)) { - RefPtr 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(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 -#include -#include "base/time.h" - -using namespace cdm; -using namespace std; - -namespace mozilla { - -static map> sDecryptors; - -/* static */ -RefPtr -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 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 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 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 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 mDecryptor; - RefPtr 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(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 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(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 - -namespace mozilla { - -class WidevineDecryptor : public GMPDecryptor - , public cdm::Host_9 -{ -public: - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WidevineDecryptor) - - WidevineDecryptor(); - - void SetCDM(RefPtr aCDM, uint32_t aDecryptorId); - - static RefPtr 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 GetCDMWrapper() const { return mCDM; } -private: - ~WidevineDecryptor(); - RefPtr mCDM; - cdm::ContentDecryptionModule_9* CDM() { return mCDM->GetCDM(); } - - GMPDecryptorCallback* mCallback; - std::map 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(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 -#include "content_decryption_module.h" -#include "gmp-api/gmp-storage.h" -#include - -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 -#include - -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 &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 mDecryptor; -}; - -void InitInputBuffer(const GMPEncryptedBufferMetadata* aCrypto, - int64_t aTimestamp, - const uint8_t* aData, - size_t aDataSize, - cdm::InputBuffer &aInputBuffer, - nsTArray &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 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 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 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(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 -#include - -namespace mozilla { - -class WidevineVideoDecoder : public GMPVideoDecoder { -public: - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WidevineVideoDecoder) - - WidevineVideoDecoder(GMPVideoHost* aVideoHost, - RefPtr 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 mCDMWrapper; - RefPtr mExtraData; - RefPtr mAnnexB; - GMPVideoDecoderCallback* mCallback; - std::map mFrameDurations; - bool mSentInput; - GMPVideoCodecType mCodecType; - // Frames waiting on allocation - std::deque 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 - -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 -#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 -#endif - -#include "content_decryption_module_export.h" - -#if defined(_MSC_VER) -typedef unsigned int uint32_t; -#else -#include -#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/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& 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& aTags) override; - nsCString GetNodeId() override; - - RefPtr 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 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 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 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 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 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& 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& 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 mDecoder; - MediaDataDecoderCallback* mCallback; - RefPtr mTaskQueue; - RefPtr mProxy; - nsClassHashtable, DecryptPromiseRequestHolder> mDecrypts; - RefPtr mSamplesWaitingForKey; - bool mIsShutdown; -}; - -class EMEMediaDataDecoderProxy : public MediaDataDecoderProxy { -public: - EMEMediaDataDecoderProxy(already_AddRefed 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 mSamplesWaitingForKey; - RefPtr mProxy; -}; - -void -EMEMediaDataDecoderProxy::Input(MediaRawData* aSample) -{ - if (mSamplesWaitingForKey->WaitIfKeyNotUsable(aSample)) { - return; - } - - nsAutoPtr 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 -CreateDecoderWrapper(MediaDataDecoderCallback* aCallback, CDMProxy* aProxy, TaskQueue* aTaskQueue) -{ - RefPtr s(gmp::GeckoMediaPluginService::GetGeckoMediaPluginService()); - if (!s) { - return nullptr; - } - RefPtr thread(s->GetAbstractGMPThread()); - if (!thread) { - return nullptr; - } - RefPtr decoder( - new EMEMediaDataDecoderProxy(thread.forget(), aCallback, aProxy, aTaskQueue)); - return decoder.forget(); -} - -already_AddRefed -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 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 decoder(mPDM->CreateDecoder(aParams)); - if (!decoder) { - return nullptr; - } - - RefPtr emeDecoder(new EMEDecryptor(decoder, - aParams.mCallback, - mProxy, - AbstractThread::GetCurrent()->AsTaskQueue())); - return emeDecoder.forget(); -} - -already_AddRefed -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 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 decoder(mPDM->CreateDecoder(aParams)); - if (!decoder) { - return nullptr; - } - - RefPtr 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 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 - CreateVideoDecoder(const CreateDecoderParams& aParams) override; - - // Decode thread. - already_AddRefed - CreateAudioDecoder(const CreateDecoderParams& aParams) override; - - ConversionRequired - DecoderNeedsConversion(const TrackInfo& aConfig) const override; - - bool - SupportsMimeType(const nsACString& aMimeType, - DecoderDoctorDiagnostics* aDiagnostics) const override; - -private: - RefPtr mProxy; - // Will be null if CDM has decoding capability. - RefPtr mPDM; - // We run the PDM on its own task queue. - RefPtr 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& 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 -EMEVideoDecoder::CreateFrame(MediaRawData* aSample) -{ - GMPUniquePtr frame = GMPVideoDecoder::CreateFrame(aSample); - if (frame && aSample->mCrypto.mValid) { - static_cast(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& aTags) override; - nsCString GetNodeId() override; - uint32_t DecryptorId() const override { return mDecryptorId; } - GMPUniquePtr CreateFrame(MediaRawData* aSample) override; - - RefPtr 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 task; - task = NewRunnableMethod>(mDecoder, - &MediaDataDecoder::Input, - RefPtr(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 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 mDecoder; - MediaDataDecoderCallback* mDecoderCallback; - RefPtr mTaskQueue; - RefPtr mProxy; - nsTArray> 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/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 - -using mozilla::BigEndian; - -static const uint8_t kAnnexBDelimiter[] = { 0, 0, 0, 1 }; - -/* static */ void -AnnexB::ConvertFrameInPlace(std::vector& 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::const_iterator& aIter, - size_t aCount, - std::vector& 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& aBuffer, - std::vector& 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 -#include - -class AnnexB -{ -public: - static void ConvertFrameInPlace(std::vector& aBuffer); - - static void ConvertConfig(const std::vector& aBuffer, - std::vector& 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 -#include - -#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 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 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 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 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 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 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 - -namespace mozilla { - -class BigEndian { -public: - - static uint32_t readUint32(const void* aPtr) { - const uint8_t* p = reinterpret_cast(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(aPtr); - return uint32_t(p[0]) << 8 | - uint32_t(p[1]); - } - - static uint64_t readUint64(const void* aPtr) { - const uint8_t* p = reinterpret_cast(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(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 - -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& 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::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 -#include -#include - -// Decodes a base64 encoded string. Returns true on success. -bool -DecodeBase64(const std::string& aEncoded, std::vector& 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 -#include - -#include "ClearKeyDecryptionManager.h" -#include "psshparser/PsshParser.h" -#include "gmp-api/gmp-decryption.h" -#include "mozilla/CheckedInt.h" -#include - -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& 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 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 data = reinterpret_cast(aBuffer); - const uintptr_t endBuffer = - reinterpret_cast(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 dataAfterCipher = data + cipherBytes; - if (!dataAfterCipher.isValid() || dataAfterCipher.value() > endBuffer) { - // Trying to read past the end of the buffer! - return GMPCryptoErr; - } - - memcpy(iter, reinterpret_cast(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 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 - -#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 mKeyId; - std::vector mIV; - std::vector mClearBytes; - std::vector 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& aBuffer, - const CryptoMetaData& aMetadata); - - void Shutdown(); - -private: - bool IsExpectingKeyForKeyId(const KeyId& aKeyId) const; - - std::map 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 -#include -#include -#include -#include -#include - -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 sPersistentSessionIds; - -static vector 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 mTarget; - uint32_t mCreateSessionToken; - uint32_t mPromiseId; - const string mInitDataType; - vector 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 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 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 -#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 -#include - -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 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 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& 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 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 -#include -#include - -#include "ClearKeyDecryptionManager.h" -#include "ClearKeySessionManager.h" -#include "ClearKeyUtils.h" -#include "ClearKeyStorage.h" -#include "ClearKeyPersistence.h" -#include "gmp-task-utils.h" -#include - -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& sessionKeys = session->GetKeyIds(); - vector 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 key_infos; - vector 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 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 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 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& aOutKeyData) -{ - const std::vector& 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 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 -#include -#include -#include - -#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& aOutKeyData); - - RefPtr mDecryptionManager; - - GMPDecryptorCallback* mCallback; - GMPThread* mThread; - - std::set mKeyIds; - std::map 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 -#include "ArrayUtils.h" - -#include - -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& 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& 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 mData; -}; - -void -StoreData(const std::string& aRecordName, - const std::vector& 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 -#include -#include - -class GMPTask; - -// Responsible for ensuring that both aOnSuccess and aOnFailure are destroyed. -void StoreData(const std::string& aRecordName, - const std::vector& 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 -#include -#include -#include -#include - -#include "ClearKeyUtils.h" -#include "ClearKeyBase64.h" -#include "ArrayUtils.h" -#include -#include -#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& aIV) { - using mozilla::BigEndian; - - assert(aIV.size() == 16); - BigEndian::writeUint64(&aIV[8], BigEndian::readUint64(&aIV[8]) + 1); -} - -/* static */ void -ClearKeyUtils::DecryptAES(const vector& aKey, - vector& aData, vector& 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 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 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(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& 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& 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& 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& aOutKeyIds) -{ - // Consume start of array. - EXPECT_SYMBOL(aCtx, '['); - - while (true) { - string label; - vector 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& 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 -#include -#include -#include -#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 KeyId; -typedef std::vector 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& aKey, - std::vector& aData, std::vector& aIV); - - static bool ParseKeyIdsInitData(const uint8_t* aInitData, - uint32_t aInitDataSize, - std::vector& aOutKeyIds); - - static void MakeKeyRequest(const std::vector& aKeyIds, - std::string& aOutRequest, - GMPSessionType aSessionType); - - static bool ParseJWK(const uint8_t* aKeyData, uint32_t aKeyDataSize, - std::vector& aOutKeys, - GMPSessionType aSessionType); - static const char* SessionTypeToString(GMPSessionType aSessionType); - - static bool IsValidSessionId(const char* aBuff, uint32_t aLength); -}; - -template -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 -inline void -Assign(std::vector& 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 -#include -#include "ClearKeyUtils.h" - -#if defined(_MSC_VER) -#include -typedef std::atomic 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 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 -#include - -#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 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& 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 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(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(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 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 twoDBuffer; - hr = mediaBuffer->QueryInterface(static_cast(&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 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(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 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 - -#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 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 mDecoder; - - std::vector mExtraData; - std::vector mAnnexB; - - int32_t mNumInputTasks; - bool mSentExtraData; - - std::atomic 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 -#include -#include - -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 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 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 sample = nullptr; - hr = MFCreateSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - CComPtr buffer = nullptr; - int32_t bufferSize = std::max(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 sample = nullptr; - hr = MFCreateSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - CComPtr 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 sample = nullptr; - hr = CreateOutputSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - output.pSample = sample; - - DWORD status = 0; - hr = mDecoder->ProcessOutput(0, 1, &output, &status); - CComPtr 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 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 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 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 -#include - -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 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 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 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 sample; - hr = MFCreateSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - CComPtr buffer; - int32_t bufferSize = std::max(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 sample; - hr = MFCreateSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - CComPtr 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 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 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 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 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 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 - -#include -#include - -#define INITGUID -#include - -#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& 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(GetProcAddress(module, "DllGetClassObject")); - if (!GetClassObjPtr) { - LOG("Failed to get DllGetClassObject\n"); - return E_FAIL; - } - - CComPtr classFactory; - HRESULT hr = GetClassObjPtr(clsid, - __uuidof(IClassFactory), - reinterpret_cast(static_cast(&classFactory))); - if (FAILED(hr)) { - LOG("Failed to get H264 IClassFactory\n"); - return E_FAIL; - } - - hr = classFactory->CreateInstance(NULL, - __uuidof(IMFTransform), - reinterpret_cast(static_cast(&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 -#include - -#include -#include -#include -#include -#include -#include -#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 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 AutoPtr { -public: - AutoPtr() - : mPtr(nullptr) - { - } - - AutoPtr(AutoPtr& aPtr) - : mPtr(aPtr.Forget()) - { - } - - AutoPtr(Type* aPtr) - : mPtr(aPtr) - { - } - - ~AutoPtr() { - if (mPtr) { - delete mPtr; - } - } - - Type* Forget() { - Type* rv = mPtr; - mPtr = nullptr; - return rv; - } - - AutoPtr& operator=(Type* aOther) { - Assign(aOther); - return *this; - } - - AutoPtr& operator=(AutoPtr& 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& 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 -#include -#include - -#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(aHostAPI)); - } else if (!strcmp(aApiName, GMP_API_VIDEO_DECODER) && - wmf::EnsureLibs()) { - *aPluginAPI = new VideoDecoder(static_cast(aHostAPI)); - } -#endif - else if (!strcmp(aApiName, GMP_API_ASYNC_SHUTDOWN)) { - *aPluginAPI = new ClearKeyAsyncShutdown(static_cast (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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 -gmp_task_args_nm_0* WrapTaskNM(M m) { - return new gmp_task_args_nm_0 - (m); -} - -// 0 arguments -- -template -gmp_task_args_nm_0_ret* WrapTaskNMRet(M m, R* r) { - return new gmp_task_args_nm_0_ret - (m, r); -} - -// 0 arguments -- -template -gmp_task_args_m_0* WrapTask(C o, M m) { - return new gmp_task_args_m_0 - (o, m); -} - -// 0 arguments -- -template -gmp_task_args_m_0_ret* WrapTaskRet(C o, M m, R* r) { - return new gmp_task_args_m_0_ret - (o, m, r); -} - -// 1 arguments -- -template -gmp_task_args_nm_1* WrapTaskNM(M m, A0 a0) { - return new gmp_task_args_nm_1 - (m, a0); -} - -// 1 arguments -- -template -gmp_task_args_nm_1_ret* WrapTaskNMRet(M m, A0 a0, R* r) { - return new gmp_task_args_nm_1_ret - (m, a0, r); -} - -// 1 arguments -- -template -gmp_task_args_m_1* WrapTask(C o, M m, A0 a0) { - return new gmp_task_args_m_1 - (o, m, a0); -} - -// 1 arguments -- -template -gmp_task_args_m_1_ret* WrapTaskRet(C o, M m, A0 a0, R* r) { - return new gmp_task_args_m_1_ret - (o, m, a0, r); -} - -// 2 arguments -- -template -gmp_task_args_nm_2* WrapTaskNM(M m, A0 a0, A1 a1) { - return new gmp_task_args_nm_2 - (m, a0, a1); -} - -// 2 arguments -- -template -gmp_task_args_nm_2_ret* WrapTaskNMRet(M m, A0 a0, A1 a1, R* r) { - return new gmp_task_args_nm_2_ret - (m, a0, a1, r); -} - -// 2 arguments -- -template -gmp_task_args_m_2* WrapTask(C o, M m, A0 a0, A1 a1) { - return new gmp_task_args_m_2 - (o, m, a0, a1); -} - -// 2 arguments -- -template -gmp_task_args_m_2_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, R* r) { - return new gmp_task_args_m_2_ret - (o, m, a0, a1, r); -} - -// 3 arguments -- -template -gmp_task_args_nm_3* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2) { - return new gmp_task_args_nm_3 - (m, a0, a1, a2); -} - -// 3 arguments -- -template -gmp_task_args_nm_3_ret* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, R* r) { - return new gmp_task_args_nm_3_ret - (m, a0, a1, a2, r); -} - -// 3 arguments -- -template -gmp_task_args_m_3* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2) { - return new gmp_task_args_m_3 - (o, m, a0, a1, a2); -} - -// 3 arguments -- -template -gmp_task_args_m_3_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, R* r) { - return new gmp_task_args_m_3_ret - (o, m, a0, a1, a2, r); -} - -// 4 arguments -- -template -gmp_task_args_nm_4* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3) { - return new gmp_task_args_nm_4 - (m, a0, a1, a2, a3); -} - -// 4 arguments -- -template -gmp_task_args_nm_4_ret* 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); -} - -// 4 arguments -- -template -gmp_task_args_m_4* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3) { - return new gmp_task_args_m_4 - (o, m, a0, a1, a2, a3); -} - -// 4 arguments -- -template -gmp_task_args_m_4_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, R* r) { - return new gmp_task_args_m_4_ret - (o, m, a0, a1, a2, a3, r); -} - -// 5 arguments -- -template -gmp_task_args_nm_5* 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); -} - -// 5 arguments -- -template -gmp_task_args_nm_5_ret* 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); -} - -// 5 arguments -- -template -gmp_task_args_m_5* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return new gmp_task_args_m_5 - (o, m, a0, a1, a2, a3, a4); -} - -// 5 arguments -- -template -gmp_task_args_m_5_ret* 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 - (o, m, a0, a1, a2, a3, a4, r); -} - -// 6 arguments -- -template -gmp_task_args_nm_6* 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); -} - -// 6 arguments -- -template -gmp_task_args_nm_6_ret* 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); -} - -// 6 arguments -- -template -gmp_task_args_m_6* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { - return new gmp_task_args_m_6 - (o, m, a0, a1, a2, a3, a4, a5); -} - -// 6 arguments -- -template -gmp_task_args_m_6_ret* 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 - (o, m, a0, a1, a2, a3, a4, a5, r); -} - -// 7 arguments -- -template -gmp_task_args_nm_7* 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); -} - -// 7 arguments -- -template -gmp_task_args_nm_7_ret* 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); -} - -// 7 arguments -- -template -gmp_task_args_m_7* 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 - (o, m, a0, a1, a2, a3, a4, a5, a6); -} - -// 7 arguments -- -template -gmp_task_args_m_7_ret* 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 - (o, m, a0, a1, a2, a3, a4, a5, a6, r); -} - -// 8 arguments -- -template -gmp_task_args_nm_8* 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); -} - -// 8 arguments -- -template -gmp_task_args_nm_8_ret* 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); -} - -// 8 arguments -- -template -gmp_task_args_m_8* 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 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7); -} - -// 8 arguments -- -template -gmp_task_args_m_8_ret* 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 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, r); -} - -// 9 arguments -- -template -gmp_task_args_nm_9* 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); -} - -// 9 arguments -- -template -gmp_task_args_nm_9_ret* 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); -} - -// 9 arguments -- -template -gmp_task_args_m_9* 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 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8); -} - -// 9 arguments -- -template -gmp_task_args_m_9_ret* 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 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, r); -} - -// 10 arguments -- -template -gmp_task_args_nm_10* 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); -} - -// 10 arguments -- -template -gmp_task_args_nm_10_ret* 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); -} - -// 10 arguments -- -template -gmp_task_args_m_10* 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 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); -} - -// 10 arguments -- -template -gmp_task_args_m_10_ret* 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 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, r); -} - -// 11 arguments -- -template -gmp_task_args_nm_11* 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); -} - -// 11 arguments -- -template -gmp_task_args_nm_11_ret* 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); -} - -// 11 arguments -- -template -gmp_task_args_m_11* 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 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); -} - -// 11 arguments -- -template -gmp_task_args_m_11_ret* 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 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, r); -} - -// 12 arguments -- -template -gmp_task_args_nm_12* 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); -} - -// 12 arguments -- -template -gmp_task_args_nm_12_ret* 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); -} - -// 12 arguments -- -template -gmp_task_args_m_12* 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 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); -} - -// 12 arguments -- -template -gmp_task_args_m_12_ret* 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 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, r); -} - -// 13 arguments -- -template -gmp_task_args_nm_13* 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); -} - -// 13 arguments -- -template -gmp_task_args_nm_13_ret* 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); -} - -// 13 arguments -- -template -gmp_task_args_m_13* 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 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); -} - -// 13 arguments -- -template -gmp_task_args_m_13_ret* 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 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, r); -} - -// 14 arguments -- -template -gmp_task_args_nm_14* 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); -} - -// 14 arguments -- -template -gmp_task_args_nm_14_ret* 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); -} - -// 14 arguments -- -template -gmp_task_args_m_14* 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 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); -} - -// 14 arguments -- -template -gmp_task_args_m_14_ret* 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 - (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 mRefCounted; -}; - -template -GMPTask* -WrapTaskRefCounted(Type* aType, Method aMethod, Args&&... args) -{ - GMPTask* t = WrapTask(aType, aMethod, std::forward(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 -#include -#include - -#include "../ClearKeyBase64.cpp" - -using namespace std; - -struct B64Test { - string b64; - vector 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 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 - -#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 -#include -#include -#include - -#include "mozilla/Sprintf.h" - -#ifdef WIN32 -#include -#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 -# define STDIO -# endif -# ifndef STDDEF -# include -# 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 */ -- cgit v1.2.3 From d0d9e63809eb0bc1cba3e4afb6378394c32dd56d Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 17 Oct 2023 13:00:38 +0200 Subject: Issue #2346 - Update license (remove OpenAES) --- toolkit/content/license.html | 39 --------------------------------------- 1 file changed, 39 deletions(-) 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 @@ -134,9 +134,6 @@
  • node-properties License
  • #ifdef MOZ_WEBRTC
  • nrappkit License
  • -#endif -#ifdef MOZ_EME -
  • OpenAES License
  • #endif
  • OpenVision License
  • praton License
  • @@ -3972,42 +3969,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -
    -#endif -#ifdef MOZ_EME -

    OpenAES License

    - -

    This license applies to certain files in the directory - media/gmp-clearkey/0.1/openaes. -

    - -
    -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.
    -
    - -
    #endif -- cgit v1.2.3 From ea3785a6d74423b117bd0c5d377973ceba456ecd Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 17 Oct 2023 13:03:29 +0200 Subject: Issue #2346 - Remove EME WebIDL interfaces --- dom/webidl/MediaEncryptedEvent.webidl | 23 ---------------- dom/webidl/MediaKeyError.webidl | 19 ------------- dom/webidl/MediaKeyMessageEvent.webidl | 30 -------------------- dom/webidl/MediaKeySession.webidl | 47 -------------------------------- dom/webidl/MediaKeyStatusMap.webidl | 30 -------------------- dom/webidl/MediaKeySystemAccess.webidl | 41 ---------------------------- dom/webidl/MediaKeys.webidl | 30 -------------------- dom/webidl/MediaKeysRequestStatus.webidl | 23 ---------------- dom/webidl/WidevineCDMManifest.webidl | 15 ---------- dom/webidl/moz.build | 13 --------- 10 files changed, 271 deletions(-) delete mode 100644 dom/webidl/MediaEncryptedEvent.webidl delete mode 100644 dom/webidl/MediaKeyError.webidl delete mode 100644 dom/webidl/MediaKeyMessageEvent.webidl delete mode 100644 dom/webidl/MediaKeySession.webidl delete mode 100644 dom/webidl/MediaKeyStatusMap.webidl delete mode 100644 dom/webidl/MediaKeySystemAccess.webidl delete mode 100644 dom/webidl/MediaKeys.webidl delete mode 100644 dom/webidl/MediaKeysRequestStatus.webidl delete mode 100644 dom/webidl/WidevineCDMManifest.webidl 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 closed; - - readonly attribute MediaKeyStatusMap keyStatuses; - - attribute EventHandler onkeystatuseschange; - - attribute EventHandler onmessage; - - [NewObject] - Promise generateRequest(DOMString initDataType, BufferSource initData); - - [NewObject] - Promise load(DOMString sessionId); - - // session operations - [NewObject] - Promise update(BufferSource response); - - [NewObject] - Promise close(); - - [NewObject] - Promise remove(); -}; diff --git a/dom/webidl/MediaKeyStatusMap.webidl b/dom/webidl/MediaKeyStatusMap.webidl deleted file mode 100644 index 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; - 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 initDataTypes = []; - sequence audioCapabilities = []; - sequence videoCapabilities = []; - MediaKeysRequirement distinctiveIdentifier = "optional"; - MediaKeysRequirement persistentState = "optional"; - sequence sessionTypes; -}; - -[Pref="media.eme.apiVisible"] -interface MediaKeySystemAccess { - readonly attribute DOMString keySystem; - [NewObject] - MediaKeySystemConfiguration getConfiguration(); - [NewObject] - Promise 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 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/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', -- cgit v1.2.3 From a63cf31989546298a7990c2f993239064b2126b5 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 17 Oct 2023 13:04:54 +0200 Subject: Issue #2346 - Update build configuration and remove --{en|dis}able-eme --- build/moz.configure/old.configure | 1 - old-configure.in | 23 ----------------------- toolkit/toolkit.mozbuild | 5 ----- 3 files changed, 29 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/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/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', -- cgit v1.2.3 From 7a10dcaadf95a379a2b7ce242fb3e1fb3f4f4ca9 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 17 Oct 2023 13:05:20 +0200 Subject: Issue #2346 - Update tests --- dom/media/test/mochitest.ini | 35 -- dom/media/test/test_eme_canvas_blocked.html | 58 --- dom/media/test/test_eme_detach_media_keys.html | 63 --- dom/media/test/test_eme_initDataTypes.html | 133 ------ dom/media/test/test_eme_missing_pssh.html | 92 ---- dom/media/test/test_eme_non_mse_fails.html | 103 ----- dom/media/test/test_eme_playback.html | 188 -------- .../test/test_eme_requestKeySystemAccess.html | 484 --------------------- dom/media/test/test_eme_request_notifications.html | 88 ---- .../test/test_eme_session_callable_value.html | 35 -- ...eme_setMediaKeys_before_attach_MediaSource.html | 41 -- .../test_eme_stream_capture_blocked_case1.html | 52 --- .../test_eme_stream_capture_blocked_case2.html | 55 --- .../test_eme_stream_capture_blocked_case3.html | 54 --- dom/media/test/test_eme_waitingforkey.html | 117 ----- 15 files changed, 1598 deletions(-) delete mode 100644 dom/media/test/test_eme_canvas_blocked.html delete mode 100644 dom/media/test/test_eme_detach_media_keys.html delete mode 100644 dom/media/test/test_eme_initDataTypes.html delete mode 100644 dom/media/test/test_eme_missing_pssh.html delete mode 100644 dom/media/test/test_eme_non_mse_fails.html delete mode 100644 dom/media/test/test_eme_playback.html delete mode 100644 dom/media/test/test_eme_requestKeySystemAccess.html delete mode 100644 dom/media/test/test_eme_request_notifications.html delete mode 100644 dom/media/test/test_eme_session_callable_value.html delete mode 100644 dom/media/test/test_eme_setMediaKeys_before_attach_MediaSource.html delete mode 100644 dom/media/test/test_eme_stream_capture_blocked_case1.html delete mode 100644 dom/media/test/test_eme_stream_capture_blocked_case2.html delete mode 100644 dom/media/test/test_eme_stream_capture_blocked_case3.html delete mode 100644 dom/media/test/test_eme_waitingforkey.html 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 @@ - - - - Test Encrypted Media Extensions - - - - - - -
    -
    -
    - - 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 @@ - - - - Test Encrypted Media Extensions - - - - - - -
    -
    -
    -
    - - 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 @@ - - - - Test Encrypted Media Extensions - - - - - - -
    -
    -
    - - 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 @@ - - - - Test Encrypted Media Extensions - - - - - - - -
    -    
    -  
    - - 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 @@ - - - - Bug 1131392 - Test that EME does not work for non-MSE media - - - - - - -
    -
    -
    - - - 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 @@ - - - - Test Encrypted Media Extensions - - - - - - -
    -
    -
    - - 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 @@ - - - - Test Encrypted Media Extensions - - - - - - -
    -
    -
    - - 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 @@ - - - - Test Encrypted Media Extensions - - - - - - -
    -
    -
    - - 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 @@ - - - - Test Encrypted Media Extensions - - - - - - -
    -
    -
    - - 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 @@ - - - - Test Encrypted Media Extensions - - - - - - -
    -
    -
    - - 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 @@ - - - - Test Encrypted Media Extensions - - - - - - -
    -
    -
    - - 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 @@ - - - - Test Encrypted Media Extensions - - - - - - -
    -
    -
    - - 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 @@ - - - - Test Encrypted Media Extensions - - - - - - -
    -
    -
    - - 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 @@ - - - - Test Encrypted Media Extensions - - - - - - -
    -
    -
    - - -- cgit v1.2.3 From 0451648c60831f8cfc1bf5f2eb232e86e6373d68 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 17 Oct 2023 13:31:40 +0200 Subject: Issue #2346 - Remove MDSM "Wait for CDM" state Without EME we don't need the machinery to wait for an external CDM module to be ready in our mediadecoder. --- dom/media/MediaDecoderStateMachine.cpp | 82 +--------------------------------- dom/media/MediaDecoderStateMachine.h | 2 - 2 files changed, 2 insertions(+), 82 deletions(-) diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp index 218bddc4ac..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 @@ -341,60 +340,6 @@ private: MozPromiseRequestHolder mMetadataRequest; }; -/** - * 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 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. * @@ -1231,29 +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 = - false; - 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(); - } else { - SetState(SeekJob{}); - } + SetState(SeekJob{}); } void @@ -1267,13 +1197,6 @@ DormantState::HandlePlayStateChanged(MediaDecoder::PlayState aPlayState) } } -void -MediaDecoderStateMachine:: -WaitForCDMState::HandleCDMProxyReady() -{ - SetState(Move(mPendingSeek)); -} - void MediaDecoderStateMachine:: DecodingFirstFrameState::Enter(SeekJob aPendingSeek) @@ -2249,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"; diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h index 6391c85740..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; -- cgit v1.2.3 From 30d3325148feb564ee8d20e028cf85e707e5ae0c Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 17 Oct 2023 13:38:57 +0200 Subject: Issue #2346 - Remove stub for setting decryptor ID --- dom/media/gmp/GMPDecryptorChild.cpp | 5 ----- dom/media/gmp/GMPDecryptorParent.cpp | 7 ------- dom/media/gmp/GMPDecryptorParent.h | 2 -- dom/media/gmp/PGMPDecryptor.ipdl | 2 -- 4 files changed, 16 deletions(-) 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 410868c33b..c41d5d18f5 100644 --- a/dom/media/gmp/GMPDecryptorParent.cpp +++ b/dom/media/gmp/GMPDecryptorParent.cpp @@ -42,13 +42,6 @@ GMPDecryptorParent::~GMPDecryptorParent() { } -bool -GMPDecryptorParent::RecvSetDecryptorId(const uint32_t& aId) -{ - /* EME stub */ - 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/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); -- cgit v1.2.3 From d0d6e8edf54d720e2858871e2c1e93e87db6622a Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 17 Oct 2023 16:24:41 +0200 Subject: Issue #2346 - Clean up EME code in toolkit extension manager (GMP) --- toolkit/mozapps/extensions/GMPInstallManager.jsm | 3 -- toolkit/mozapps/extensions/GMPUtils.jsm | 5 -- .../mozapps/extensions/internal/GMPProvider.jsm | 59 +++------------------- 3 files changed, 8 insertions(+), 59 deletions(-) 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(); } } }, -- cgit v1.2.3 From 42c8b9470c3c012763677ce0e93ad80bbe0610c9 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 17 Oct 2023 16:37:19 +0200 Subject: Issue #2346 - Remove EME PDM factory creation. --- dom/media/platforms/PDMFactory.cpp | 8 -------- dom/media/platforms/PDMFactory.h | 1 - 2 files changed, 9 deletions(-) diff --git a/dom/media/platforms/PDMFactory.cpp b/dom/media/platforms/PDMFactory.cpp index 389b151994..02cbd3d92b 100644 --- a/dom/media/platforms/PDMFactory.cpp +++ b/dom/media/platforms/PDMFactory.cpp @@ -201,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) { @@ -329,9 +324,6 @@ bool PDMFactory::Supports(const TrackInfo& aTrackInfo, DecoderDoctorDiagnostics* aDiagnostics) const { - if (mEMEPDM) { - return mEMEPDM->Supports(aTrackInfo, aDiagnostics); - } RefPtr current = GetDecoder(aTrackInfo, aDiagnostics); return !!current; } diff --git a/dom/media/platforms/PDMFactory.h b/dom/media/platforms/PDMFactory.h index e288efadd0..313633ab57 100644 --- a/dom/media/platforms/PDMFactory.h +++ b/dom/media/platforms/PDMFactory.h @@ -56,7 +56,6 @@ private: const CreateDecoderParams& aParams); nsTArray> mCurrentPDMs; - RefPtr mEMEPDM; RefPtr mBlankPDM; bool mWMFFailedToLoad = false; -- cgit v1.2.3 From f2ec6ef34d9f38faed6b0b2f556390976353fef7 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Wed, 18 Oct 2023 10:59:39 +0200 Subject: Issue #2346 - Remove IsWaitingOnCDMResource stub --- dom/media/MediaFormatReader.cpp | 11 +---------- dom/media/MediaFormatReader.h | 2 -- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp index 2bdd2621ac..17fa29c080 100644 --- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -583,13 +583,6 @@ MediaFormatReader::InitInternal() return NS_OK; } -bool -MediaFormatReader::IsWaitingOnCDMResource() { - MOZ_ASSERT(OnTaskQueue()); - /* EME stub */ - return false; -} - RefPtr MediaFormatReader::AsyncReadMetadata() { @@ -625,9 +618,7 @@ MediaFormatReader::OnDemuxerInitDone(nsresult) UniquePtr tags(MakeUnique()); RefPtr 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) && diff --git a/dom/media/MediaFormatReader.h b/dom/media/MediaFormatReader.h index 4e084f4158..60ee022264 100644 --- a/dom/media/MediaFormatReader.h +++ b/dom/media/MediaFormatReader.h @@ -100,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 -- cgit v1.2.3 From 5b5672fd5601074dbd06fc077b57879f534b82b6 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Wed, 18 Oct 2023 16:30:27 -0400 Subject: Issue #2332 - Hyphenate rtc stats type as per spec Backport of https://bugzilla.mozilla.org/show_bug.cgi?id=1322503 --- dom/media/PeerConnection.js | 11 ++++- dom/media/tests/mochitest/pc.js | 54 +++++++++++++--------- dom/media/tests/mochitest/templates.js | 4 +- dom/media/webrtc/WebrtcGlobal.h | 2 +- dom/webidl/RTCStatsReport.webidl | 10 ++-- .../src/peerconnection/PeerConnectionImpl.cpp | 16 +++---- .../src/peerconnection/WebrtcGlobalInformation.cpp | 2 +- 7 files changed, 57 insertions(+), 42 deletions(-) diff --git a/dom/media/PeerConnection.js b/dom/media/PeerConnection.js index e4612f8316..784ba822b3 100644 --- a/dom/media/PeerConnection.js +++ b/dom/media/PeerConnection.js @@ -308,13 +308,20 @@ RTCStatsReport.prototype = { // Since maplike is recent, we still also make the stats available as legacy // enumerable read-only properties directly on our content-facing object. // Must be called after our webidl sandwich is made. + _specToLegacyFieldMapping: { + 'inbound-rtp' : 'inboundrtp', + 'outbound-rtp':'outboundrtp', + 'candidate-pair':'candidatepair', + 'local-candidate':'localcandidate', + 'remote-candidate':'remotecandidate' + }, makeStatsPublic: function(warnNullable) { let legacyProps = {}; for (let key in this._report) { + this.setInternal(key, Cu.cloneInto(this._report[key], this._win)); let value = Cu.cloneInto(this._report[key], this._win); - this.setInternal(key, value); - + value.type = this._specToLegacyFieldMapping[value.type] || value.type; legacyProps[key] = { enumerable: true, configurable: false, get: Cu.exportFunction(function() { diff --git a/dom/media/tests/mochitest/pc.js b/dom/media/tests/mochitest/pc.js index 4363841da7..ed6f76edb7 100644 --- a/dom/media/tests/mochitest/pc.js +++ b/dom/media/tests/mochitest/pc.js @@ -1417,12 +1417,12 @@ PeerConnectionWrapper.prototype = { waitForRtpFlow(track) { var hasFlow = stats => { var rtp = stats.get([...stats.keys()].find(key => - !stats.get(key).isRemote && stats.get(key).type.endsWith("boundrtp"))); + !stats.get(key).isRemote && stats.get(key).type.endsWith("bound-rtp"))); ok(rtp, "Should have RTP stats for track " + track.id); if (!rtp) { return false; } - var nrPackets = rtp[rtp.type == "outboundrtp" ? "packetsSent" + var nrPackets = rtp[rtp.type == "outbound-rtp" ? "packetsSent" : "packetsReceived"]; info("Track " + track.id + " has " + nrPackets + " " + rtp.type + " RTP packets."); @@ -1559,15 +1559,15 @@ PeerConnectionWrapper.prototype = { counters[res.type] = (counters[res.type] || 0) + 1; switch (res.type) { - case "inboundrtp": - case "outboundrtp": { + case "inbound-rtp": + case "outbound-rtp": { // ssrc is a 32 bit number returned as a string by spec ok(res.ssrc.length > 0, "Ssrc has length"); ok(res.ssrc.length < 11, "Ssrc not lengthy"); ok(!/[^0-9]/.test(res.ssrc), "Ssrc numeric"); ok(parseInt(res.ssrc) < Math.pow(2,32), "Ssrc within limits"); - if (res.type == "outboundrtp") { + if (res.type == "outbound-rtp") { ok(res.packetsSent !== undefined, "Rtp packetsSent"); // We assume minimum payload to be 1 byte (guess from RFC 3550) ok(res.bytesSent >= res.packetsSent, "Rtp bytesSent"); @@ -1576,11 +1576,11 @@ PeerConnectionWrapper.prototype = { ok(res.bytesReceived >= res.packetsReceived, "Rtp bytesReceived"); } if (res.remoteId) { - var rem = stats[res.remoteId]; + var rem = stats.get(res.remoteId); ok(rem.isRemote, "Remote is rtcp"); ok(rem.remoteId == res.id, "Remote backlink match"); - if(res.type == "outboundrtp") { - ok(rem.type == "inboundrtp", "Rtcp is inbound"); + if(res.type == "outbound-rtp") { + ok(rem.type == "inbound-rtp", "Rtcp is inbound"); ok(rem.packetsReceived !== undefined, "Rtcp packetsReceived"); ok(rem.packetsLost !== undefined, "Rtcp packetsLost"); ok(rem.bytesReceived >= rem.packetsReceived, "Rtcp bytesReceived"); @@ -1593,7 +1593,7 @@ PeerConnectionWrapper.prototype = { ok(rem.mozRtt >= 0, "Rtcp rtt " + rem.mozRtt + " >= 0"); ok(rem.mozRtt < 60000, "Rtcp rtt " + rem.mozRtt + " < 1 min"); } else { - ok(rem.type == "outboundrtp", "Rtcp is outbound"); + ok(rem.type == "outbound-rtp", "Rtcp is outbound"); ok(rem.packetsSent !== undefined, "Rtcp packetsSent"); // We may have received more than outdated Rtcp packetsSent ok(rem.bytesSent >= rem.packetsSent, "Rtcp bytesSent"); @@ -1607,6 +1607,13 @@ PeerConnectionWrapper.prototype = { } } + var legacyToSpecMapping = { + 'inboundrtp':'inbound-rtp', + 'outboundrtp':'outbound-rtp', + 'candidatepair':'candidate-pair', + 'localcandidate':'local-candidate', + 'remotecandidate':'remote-candidate' + }; // Use legacy way of enumerating stats var counters2 = {}; for (let key in stats) { @@ -1614,8 +1621,9 @@ PeerConnectionWrapper.prototype = { continue; } var res = stats[key]; + var type = legacyToSpecMapping[res.type] || res.type; if (!res.isRemote) { - counters2[res.type] = (counters2[res.type] || 0) + 1; + counters2[type] = (counters2[type] || 0) + 1; } } is(JSON.stringify(counters), JSON.stringify(counters2), @@ -1624,21 +1632,21 @@ PeerConnectionWrapper.prototype = { var nout = Object.keys(this.expectedLocalTrackInfoById).length; var ndata = this.dataChannels.length; - // TODO(Bug 957145): Restore stronger inboundrtp test once Bug 948249 is fixed - //is((counters["inboundrtp"] || 0), nin, "Have " + nin + " inboundrtp stat(s)"); - ok((counters.inboundrtp || 0) >= nin, "Have at least " + nin + " inboundrtp stat(s) *"); + // TODO(Bug 957145): Restore stronger inbound-rtp test once Bug 948249 is fixed + //is((counters["inbound-rtp"] || 0), nin, "Have " + nin + " inbound-rtp stat(s)"); + ok((counters["inbound-rtp"] || 0) >= nin, "Have at least " + nin + " inbound-rtp stat(s) *"); - is(counters.outboundrtp || 0, nout, "Have " + nout + " outboundrtp stat(s)"); + is(counters["outbound-rtp"] || 0, nout, "Have " + nout + " outbound-rtp stat(s)"); - var numLocalCandidates = counters.localcandidate || 0; - var numRemoteCandidates = counters.remotecandidate || 0; + var numLocalCandidates = counters["local-candidate"] || 0; + var numRemoteCandidates = counters["remote-candidate"] || 0; // If there are no tracks, there will be no stats either. if (nin + nout + ndata > 0) { - ok(numLocalCandidates, "Have localcandidate stat(s)"); - ok(numRemoteCandidates, "Have remotecandidate stat(s)"); + ok(numLocalCandidates, "Have local-candidate stat(s)"); + ok(numRemoteCandidates, "Have remote-candidate stat(s)"); } else { - is(numLocalCandidates, 0, "Have no localcandidate stats"); - is(numRemoteCandidates, 0, "Have no remotecandidate stats"); + is(numLocalCandidates, 0, "Have no local-candidate stats"); + is(numRemoteCandidates, 0, "Have no remote-candidate stats"); } }, @@ -1653,7 +1661,7 @@ PeerConnectionWrapper.prototype = { let lId; let rId; for (let stat of stats.values()) { - if (stat.type == "candidatepair" && stat.selected) { + if (stat.type == "candidate-pair" && stat.selected) { lId = stat.localCandidateId; rId = stat.remoteCandidateId; break; @@ -1704,8 +1712,8 @@ PeerConnectionWrapper.prototype = { checkStatsIceConnections : function(stats, offerConstraintsList, offerOptions, testOptions) { var numIceConnections = 0; - Object.keys(stats).forEach(key => { - if ((stats[key].type === "candidatepair") && stats[key].selected) { + stats.forEach(stat => { + if ((stat.type === "candidate-pair") && stat.selected) { numIceConnections += 1; } }); diff --git a/dom/media/tests/mochitest/templates.js b/dom/media/tests/mochitest/templates.js index 7a149c146e..89204888a5 100644 --- a/dom/media/tests/mochitest/templates.js +++ b/dom/media/tests/mochitest/templates.js @@ -90,12 +90,12 @@ function checkTrackStats(pc, rtpSenderOrReceiver, outbound) { (audio ? "audio" : "video") + " rtp track id " + track.id; return pc.getStats(track).then(stats => { ok(pc.hasStat(stats, { - type: outbound ? "outboundrtp" : "inboundrtp", + type: outbound ? "outbound-rtp" : "inbound-rtp", isRemote: false, mediaType: audio ? "audio" : "video" }), msg + " - found expected stats"); ok(!pc.hasStat(stats, { - type: outbound ? "inboundrtp" : "outboundrtp", + type: outbound ? "inbound-rtp" : "outbound-rtp", isRemote: false }), msg + " - did not find extra stats with wrong direction"); ok(!pc.hasStat(stats, { diff --git a/dom/media/webrtc/WebrtcGlobal.h b/dom/media/webrtc/WebrtcGlobal.h index 8ab10cb0dd..7a8611afef 100644 --- a/dom/media/webrtc/WebrtcGlobal.h +++ b/dom/media/webrtc/WebrtcGlobal.h @@ -72,7 +72,7 @@ template<> struct ParamTraits : public ContiguousEnumSerializer< mozilla::dom::RTCStatsType, - mozilla::dom::RTCStatsType::Inboundrtp, + mozilla::dom::RTCStatsType::Inbound_rtp, mozilla::dom::RTCStatsType::EndGuard_> {}; diff --git a/dom/webidl/RTCStatsReport.webidl b/dom/webidl/RTCStatsReport.webidl index 04c683e9a1..6a7d5bbc0d 100644 --- a/dom/webidl/RTCStatsReport.webidl +++ b/dom/webidl/RTCStatsReport.webidl @@ -9,14 +9,14 @@ */ enum RTCStatsType { - "inboundrtp", - "outboundrtp", + "inbound-rtp", + "outbound-rtp", "session", "track", "transport", - "candidatepair", - "localcandidate", - "remotecandidate" + "candidate-pair", + "local-candidate", + "remote-candidate" }; dictionary RTCStats { diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp index ad87fa1f91..894a3a9a2d 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp @@ -3602,7 +3602,7 @@ static void ToRTCIceCandidateStats( cand.mPortNumber.Construct(c->cand_addr.port); cand.mTransport.Construct( NS_ConvertASCIItoUTF16(c->cand_addr.transport.c_str())); - if (candidateType == RTCStatsType::Localcandidate) { + if (candidateType == RTCStatsType::Local_candidate) { cand.mMozLocalTransport.Construct( NS_ConvertASCIItoUTF16(c->local_addr.transport.c_str())); } @@ -3636,7 +3636,7 @@ static void RecordIceStats_s( s.mId.Construct(codeword); s.mComponentId.Construct(componentId); s.mTimestamp.Construct(now); - s.mType.Construct(RTCStatsType::Candidatepair); + s.mType.Construct(RTCStatsType::Candidate_pair); s.mLocalCandidateId.Construct(localCodeword); s.mRemoteCandidateId.Construct(remoteCodeword); s.mNominated.Construct(p->nominated); @@ -3649,7 +3649,7 @@ static void RecordIceStats_s( std::vector candidates; if (NS_SUCCEEDED(mediaStream.GetLocalCandidates(&candidates))) { ToRTCIceCandidateStats(candidates, - RTCStatsType::Localcandidate, + RTCStatsType::Local_candidate, componentId, now, report); @@ -3658,7 +3658,7 @@ static void RecordIceStats_s( if (NS_SUCCEEDED(mediaStream.GetRemoteCandidates(&candidates))) { ToRTCIceCandidateStats(candidates, - RTCStatsType::Remotecandidate, + RTCStatsType::Remote_candidate, componentId, now, report); @@ -3710,7 +3710,7 @@ PeerConnectionImpl::ExecuteStatsQuery_s(RTCStatsQuery *query) { RTCInboundRTPStreamStats s; s.mTimestamp.Construct(timestamp); s.mId.Construct(remoteId); - s.mType.Construct(RTCStatsType::Inboundrtp); + s.mType.Construct(RTCStatsType::Inbound_rtp); if (ssrc.Length()) { s.mSsrc.Construct(ssrc); } @@ -3731,7 +3731,7 @@ PeerConnectionImpl::ExecuteStatsQuery_s(RTCStatsQuery *query) { RTCOutboundRTPStreamStats s; s.mTimestamp.Construct(query->now); s.mId.Construct(localId); - s.mType.Construct(RTCStatsType::Outboundrtp); + s.mType.Construct(RTCStatsType::Outbound_rtp); if (ssrc.Length()) { s.mSsrc.Construct(ssrc); } @@ -3784,7 +3784,7 @@ PeerConnectionImpl::ExecuteStatsQuery_s(RTCStatsQuery *query) { RTCOutboundRTPStreamStats s; s.mTimestamp.Construct(timestamp); s.mId.Construct(remoteId); - s.mType.Construct(RTCStatsType::Outboundrtp); + s.mType.Construct(RTCStatsType::Outbound_rtp); if (ssrc.Length()) { s.mSsrc.Construct(ssrc); } @@ -3801,7 +3801,7 @@ PeerConnectionImpl::ExecuteStatsQuery_s(RTCStatsQuery *query) { RTCInboundRTPStreamStats s; s.mTimestamp.Construct(query->now); s.mId.Construct(localId); - s.mType.Construct(RTCStatsType::Inboundrtp); + s.mType.Construct(RTCStatsType::Inbound_rtp); if (ssrc.Length()) { s.mSsrc.Construct(ssrc); } diff --git a/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.cpp b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.cpp index 2f860cac60..8f3c29f116 100644 --- a/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.cpp +++ b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.cpp @@ -1066,7 +1066,7 @@ static void StoreLongTermICEStatisticsImpl_m( uint32_t candBitmask = GetCandidateIpAndTransportMask(&cand); // Note: shift values need to result in the above enum table - if (cand.mType.Value() == RTCStatsType::Localcandidate) { + if (cand.mType.Value() == RTCStatsType::Local_candidate) { candBitmask <<= kLocalShift; } -- cgit v1.2.3 From 6ad6cc9c2d245be3e0ed7526b09f26b8cd5854a7 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Thu, 19 Oct 2023 10:17:11 +0200 Subject: Issue #2350 - Part 0: Add a helper function DefaultNumberOption This is the abstract operation that converts an option value to a number value, checking whether it is in the allowed range, and filling in a fallback value if necessary. --- js/src/builtin/intl/CommonFunctions.js | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/js/src/builtin/intl/CommonFunctions.js b/js/src/builtin/intl/CommonFunctions.js index effabf020f..80a35f1851 100644 --- a/js/src/builtin/intl/CommonFunctions.js +++ b/js/src/builtin/intl/CommonFunctions.js @@ -647,6 +647,52 @@ function GetOption(options, property, type, values, fallback) { return fallback; } + +/** + * The abstract operation DefaultNumberOption converts value to a Number value, + * checks whether it is in the allowed range, and fills in a fallback value if + * necessary. + * + * Spec: ECMAScript Internationalization API Specification, 9.2.11. + */ +function DefaultNumberOption(value, minimum, maximum, fallback) { + assert( + typeof minimum === "number" && (minimum | 0) === minimum, + "DefaultNumberOption" + ); + assert( + typeof maximum === "number" && (maximum | 0) === maximum, + "DefaultNumberOption" + ); + assert( + fallback === undefined || + (typeof fallback === "number" && (fallback | 0) === fallback), + "DefaultNumberOption" + ); + assert( + fallback === undefined || (minimum <= fallback && fallback <= maximum), + "DefaultNumberOption" + ); + + // Step 1. + if (value === undefined) { + return fallback; + } + + // Step 2. + value = ToNumber(value); + + // Step 3. + if (Number_isNaN(value) || value < minimum || value > maximum) { + ThrowRangeError(JSMSG_INVALID_DIGITS_VALUE, value); + } + + // Step 4. + // Apply bitwise-or to convert -0 to +0 per ES2017, 5.2 and to ensure the + // result is an int32 value. + return std_Math_floor(value) | 0; +} + /** * Extracts a property value from the provided options object, converts it to a * Number value, checks whether it is in the allowed range, and fills in a -- cgit v1.2.3 From 6c6c16b7f012b301af8ebc1aa0808017d631b56d Mon Sep 17 00:00:00 2001 From: Moonchild Date: Thu, 19 Oct 2023 10:21:54 +0200 Subject: Issue #2350 - Part 1: Apply "minimumIntegerDigits" to number-formatters with fraction-digits. Implements the changes to `SetNumberFormatDigitOptions` and `FormatNumberToString`, except for the support of the new "compact-rounding" mode. This also includes a few minor fixes for edge cases (like -0 vs. 0) --- js/src/builtin/intl/CommonFunctions.js | 22 +------ js/src/builtin/intl/NumberFormat.cpp | 9 +-- js/src/builtin/intl/NumberFormat.js | 107 ++++++++++++++++++++++++--------- js/src/builtin/intl/PluralRules.cpp | 10 +-- js/src/builtin/intl/PluralRules.js | 32 ++++++---- 5 files changed, 111 insertions(+), 69 deletions(-) diff --git a/js/src/builtin/intl/CommonFunctions.js b/js/src/builtin/intl/CommonFunctions.js index 80a35f1851..69b96d6db1 100644 --- a/js/src/builtin/intl/CommonFunctions.js +++ b/js/src/builtin/intl/CommonFunctions.js @@ -698,29 +698,13 @@ function DefaultNumberOption(value, minimum, maximum, fallback) { * Number value, checks whether it is in the allowed range, and fills in a * fallback value if necessary. * - * Spec: ECMAScript Internationalization API Specification, 9.2.10. + * Spec: ECMAScript Internationalization API Specification, 9.2.12. */ function GetNumberOption(options, property, minimum, maximum, fallback) { - assert(typeof minimum === "number", "GetNumberOption"); - assert(typeof maximum === "number", "GetNumberOption"); - assert(fallback === undefined || (fallback >= minimum && fallback <= maximum), "GetNumberOption"); - - // Step 1. - var value = options[property]; - - // Step 2. - if (value !== undefined) { - value = ToNumber(value); - if (Number_isNaN(value) || value < minimum || value > maximum) - ThrowRangeError(JSMSG_INVALID_DIGITS_VALUE, value); - return std_Math_floor(value); - } - - // Step 3. - return fallback; + // Steps 1-3. + return DefaultNumberOption(options[property], minimum, maximum, fallback); } - // Symbols in the self-hosting compartment can't be cloned, use a separate // object to hold the actual symbol value. // TODO: Can we add support to clone symbols? diff --git a/js/src/builtin/intl/NumberFormat.cpp b/js/src/builtin/intl/NumberFormat.cpp index 8820166f56..a1997c136e 100644 --- a/js/src/builtin/intl/NumberFormat.cpp +++ b/js/src/builtin/intl/NumberFormat.cpp @@ -353,10 +353,6 @@ NewUNumberFormat(JSContext* cx, Handle numberFormat) return nullptr; uMaximumSignificantDigits = value.toInt32(); } else { - if (!GetProperty(cx, internals, internals, cx->names().minimumIntegerDigits, - &value)) - return nullptr; - uMinimumIntegerDigits = AssertedCast(value.toInt32()); if (!GetProperty(cx, internals, internals, cx->names().minimumFractionDigits, &value)) return nullptr; @@ -367,6 +363,11 @@ NewUNumberFormat(JSContext* cx, Handle numberFormat) uMaximumFractionDigits = AssertedCast(value.toInt32()); } + if (!GetProperty(cx, internals, internals, cx->names().minimumIntegerDigits, + &value)) + return nullptr; + uMinimumIntegerDigits = AssertedCast(value.toInt32()); + if (!GetProperty(cx, internals, internals, cx->names().useGrouping, &value)) return nullptr; uUseGrouping = value.toBoolean(); diff --git a/js/src/builtin/intl/NumberFormat.js b/js/src/builtin/intl/NumberFormat.js index 261bff1dc6..60d423efd9 100644 --- a/js/src/builtin/intl/NumberFormat.js +++ b/js/src/builtin/intl/NumberFormat.js @@ -55,8 +55,14 @@ function resolveNumberFormatInternals(lazyNumberFormatData) { // Step 22. internalProps.minimumIntegerDigits = lazyNumberFormatData.minimumIntegerDigits; - internalProps.minimumFractionDigits = lazyNumberFormatData.minimumFractionDigits; - internalProps.maximumFractionDigits = lazyNumberFormatData.maximumFractionDigits; + + if ("minimumFractionDigits" in lazyNumberFormatData) { + // Note: Intl.NumberFormat.prototype.resolvedOptions() exposes the + // actual presence (versus undefined-ness) of these properties. + assert("maximumFractionDigits" in lazyNumberFormatData, "min/max frac digits mismatch"); + internalProps.minimumFractionDigits = lazyNumberFormatData.minimumFractionDigits; + internalProps.maximumFractionDigits = lazyNumberFormatData.maximumFractionDigits; + } if ("minimumSignificantDigits" in lazyNumberFormatData) { // Note: Intl.NumberFormat.prototype.resolvedOptions() exposes the @@ -122,34 +128,75 @@ function UnwrapNumberFormat(nf, methodName) { * * Spec: ECMAScript Internationalization API Specification, 11.1.1. */ -function SetNumberFormatDigitOptions(lazyData, options, mnfdDefault) { +function SetNumberFormatDigitOptions(lazyData, options, mnfdDefault, mxfdDefault) { // We skip step 1 because we set the properties on a lazyData object. // Steps 2-4. assert(IsObject(options), "SetNumberFormatDigitOptions"); assert(typeof mnfdDefault === "number", "SetNumberFormatDigitOptions"); - // Steps 5-8. - const mnid = GetNumberOption(options, "minimumIntegerDigits", 1, 21, 1); - const mnfd = GetNumberOption(options, "minimumFractionDigits", 0, 20, mnfdDefault); - const mxfd = GetNumberOption(options, "maximumFractionDigits", mnfd, 20); + assert(typeof mxfdDefault === "number", "SetNumberFormatDigitOptions"); + assert(mnfdDefault <= mxfdDefault, "SetNumberFormatDigitOptions"); - // Steps 9-10. + // Steps 5-9. + const mnid = GetNumberOption(options, "minimumIntegerDigits", 1, 21, 1); + let mnfd = options.minimumFractionDigits; + let mxfd = options.maximumFractionDigits; let mnsd = options.minimumSignificantDigits; let mxsd = options.maximumSignificantDigits; - // Steps 9-11. + // Step 10. lazyData.minimumIntegerDigits = mnid; - lazyData.minimumFractionDigits = mnfd; - lazyData.maximumFractionDigits = mxfd; - // Step 12. + // Step 11. if (mnsd !== undefined || mxsd !== undefined) { - mnsd = GetNumberOption(options, "minimumSignificantDigits", 1, 21, 1); - mxsd = GetNumberOption(options, "maximumSignificantDigits", mnsd, 21, 21); + // Step 11.a (Omitted). + + // Step 11.b. + mnsd = DefaultNumberOption(mnsd, 1, 21, 1); + + // Step 11.c. + mxsd = DefaultNumberOption(mxsd, mnsd, 21, 21); + + // Step 11.d. lazyData.minimumSignificantDigits = mnsd; + + // Step 11.e. lazyData.maximumSignificantDigits = mxsd; } + + // Step 12. + else if (mnfd !== undefined || mxfd !== undefined) { + // Step 12.a (Omitted). + + // Step 12.b. + mnfd = DefaultNumberOption(mnfd, 0, 20, mnfdDefault); + + // Step 12.c. + const mxfdActualDefault = std_Math_max(mnfd, mxfdDefault); + + // Step 12.d. + mxfd = DefaultNumberOption(mxfd, mnfd, 20, mxfdActualDefault); + + // Step 12.e. + lazyData.minimumFractionDigits = mnfd; + + // Step 12.f. + lazyData.maximumFractionDigits = mxfd; + } + + // Step 13 (TODO: Not yet implemented). + + // Step 14. + else { + // Step 14.a (Omitted). + + // Step 14.b. + lazyData.minimumFractionDigits = mnfdDefault; + + // Step 14.c. + lazyData.maximumFractionDigits = mxfdDefault; + } } /** @@ -291,19 +338,16 @@ function InitializeNumberFormat(numberFormat, thisValue, locales, options) { if (s === "currency") lazyNumberFormatData.currencyDisplay = cd; - // Steps 20-22. - SetNumberFormatDigitOptions(lazyNumberFormatData, options, s === "currency" ? cDigits: 0); - - // Step 25. - if (lazyNumberFormatData.maximumFractionDigits === undefined) { - let mxfdDefault = s === "currency" - ? cDigits - : s === "percent" - ? 0 - : 3; - lazyNumberFormatData.maximumFractionDigits = - std_Math_max(lazyNumberFormatData.minimumFractionDigits, mxfdDefault); + // Steps 22-25. + var mnfdDefault, mxfdDefault; + if (s === "currency") { + mnfdDefault = cDigits; + mxfdDefault = cDigits; + } else { + mnfdDefault = 0; + mxfdDefault = s === "percent" ? 0 : 3; } + SetNumberFormatDigitOptions(lazyNumberFormatData, options, mnfdDefault, mxfdDefault); // Steps 23. var g = GetOption(options, "useGrouping", "boolean", undefined, true); @@ -520,8 +564,6 @@ function Intl_NumberFormat_resolvedOptions() { numberingSystem: internals.numberingSystem, style: internals.style, minimumIntegerDigits: internals.minimumIntegerDigits, - minimumFractionDigits: internals.minimumFractionDigits, - maximumFractionDigits: internals.maximumFractionDigits, useGrouping: internals.useGrouping }; @@ -536,6 +578,15 @@ function Intl_NumberFormat_resolvedOptions() { _DefineDataProperty(result, "currencyDisplay", internals.currencyDisplay); } + // Min/Max fraction digits are either both present or not present at all. + assert(hasOwn("minimumFractionDigits", internals) === + hasOwn("maximumFractionDigits", internals), + "minimumFractionDigits is present iff maximumFractionDigits is present"); + if (hasOwn("minimumFractionDigits", internals)) { + _DefineDataProperty(result, "minimumFractionDigits", internals.minimumFractionDigits); + _DefineDataProperty(result, "maximumFractionDigits", internals.maximumFractionDigits); + } + // Min/Max significant digits are either both present or not at all. assert(hasOwn("minimumSignificantDigits", internals) === hasOwn("maximumSignificantDigits", internals), diff --git a/js/src/builtin/intl/PluralRules.cpp b/js/src/builtin/intl/PluralRules.cpp index ce2f3c3893..dc27b330e9 100644 --- a/js/src/builtin/intl/PluralRules.cpp +++ b/js/src/builtin/intl/PluralRules.cpp @@ -224,11 +224,6 @@ NewUNumberFormatForPluralRules(JSContext* cx, Handle pluralR return nullptr; uMaximumSignificantDigits = value.toInt32(); } else { - if (!GetProperty(cx, internals, internals, cx->names().minimumIntegerDigits, - &value)) - return nullptr; - uMinimumIntegerDigits = AssertedCast(value.toInt32()); - if (!GetProperty(cx, internals, internals, cx->names().minimumFractionDigits, &value)) return nullptr; @@ -240,6 +235,11 @@ NewUNumberFormatForPluralRules(JSContext* cx, Handle pluralR uMaximumFractionDigits = AssertedCast(value.toInt32()); } + if (!GetProperty(cx, internals, internals, cx->names().minimumIntegerDigits, + &value)) + return nullptr; + uMinimumIntegerDigits = AssertedCast(value.toInt32()); + UErrorCode status = U_ZERO_ERROR; UNumberFormat* nf = unum_open(UNUM_DECIMAL, nullptr, 0, IcuLocale(locale.ptr()), nullptr, &status); if (U_FAILURE(status)) { diff --git a/js/src/builtin/intl/PluralRules.js b/js/src/builtin/intl/PluralRules.js index eb19bf067e..ae6a97f0ae 100644 --- a/js/src/builtin/intl/PluralRules.js +++ b/js/src/builtin/intl/PluralRules.js @@ -53,8 +53,12 @@ function resolvePluralRulesInternals(lazyPluralRulesData) { // Step 9. internalProps.minimumIntegerDigits = lazyPluralRulesData.minimumIntegerDigits; - internalProps.minimumFractionDigits = lazyPluralRulesData.minimumFractionDigits; - internalProps.maximumFractionDigits = lazyPluralRulesData.maximumFractionDigits; + + if ("minimumFractionDigits" in lazyPluralRulesData) { + assert("maximumFractionDigits" in lazyPluralRulesData, "min/max frac digits mismatch"); + internalProps.minimumFractionDigits = lazyPluralRulesData.minimumFractionDigits; + internalProps.maximumFractionDigits = lazyPluralRulesData.maximumFractionDigits; + } if ("minimumSignificantDigits" in lazyPluralRulesData) { assert("maximumSignificantDigits" in lazyPluralRulesData, "min/max sig digits mismatch"); @@ -149,14 +153,8 @@ function InitializePluralRules(pluralRules, locales, options) { const type = GetOption(options, "type", "string", ["cardinal", "ordinal"], "cardinal"); lazyPluralRulesData.type = type; - // Step 9. - SetNumberFormatDigitOptions(lazyPluralRulesData, options, 0); - - // Step 12. - if (lazyPluralRulesData.maximumFractionDigits === undefined) { - lazyPluralRulesData.maximumFractionDigits = - std_Math_max(lazyPluralRulesData.minimumFractionDigits, 3); - } + // Steps 11-12. + SetNumberFormatDigitOptions(lazyPluralRulesData, options, 0, 3); // Step 15. // @@ -246,11 +244,19 @@ function Intl_PluralRules_resolvedOptions() { type: internals.type, pluralCategories: callFunction(std_Array_slice, internals.pluralCategories, 0), minimumIntegerDigits: internals.minimumIntegerDigits, - minimumFractionDigits: internals.minimumFractionDigits, - maximumFractionDigits: internals.maximumFractionDigits, }; - // Min/Max significant digits are either both present or not at all. + // Min/Max fraction digits are either both present or not present at all. + assert(hasOwn("minimumFractionDigits", internals) === + hasOwn("maximumFractionDigits", internals), + "minimumFractionDigits is present iff maximumFractionDigits is present"); + + if (hasOwn("minimumFractionDigits", internals)) { + _DefineDataProperty(result, "minimumFractionDigits", internals.minimumFractionDigits); + _DefineDataProperty(result, "maximumFractionDigits", internals.maximumFractionDigits); + } + + // Min/Max significant digits are either both present or not present at all. assert(hasOwn("minimumSignificantDigits", internals) === hasOwn("maximumSignificantDigits", internals), "minimumSignificantDigits is present iff maximumSignificantDigits is present"); -- cgit v1.2.3 From 3e71cd6b93edaf7362e2635a38675bb843cd402a Mon Sep 17 00:00:00 2001 From: Moonchild Date: Thu, 19 Oct 2023 15:46:27 +0200 Subject: Issue #2350 - Part 2: Allow "maximumFractionDigits" option in Intl.NumberFormat to be less than the default minimum fraction digits. This implements the changes from the "has consensus" PR in TC39 The second pair of `DefaultNumberOption()` calls was inlined, because only the fallback case is relevant anyway. Steps 12.d and 12.e from the spec PR were combined into a single `if`-block. That way it also matches step 12.f more closely. Also changed the single `if` steps into an `if-else if` chain, because the steps are mutually exclusive. --- js/src/builtin/intl/NumberFormat.js | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/js/src/builtin/intl/NumberFormat.js b/js/src/builtin/intl/NumberFormat.js index 60d423efd9..85fac41e01 100644 --- a/js/src/builtin/intl/NumberFormat.js +++ b/js/src/builtin/intl/NumberFormat.js @@ -170,18 +170,33 @@ function SetNumberFormatDigitOptions(lazyData, options, mnfdDefault, mxfdDefault // Step 12.a (Omitted). // Step 12.b. - mnfd = DefaultNumberOption(mnfd, 0, 20, mnfdDefault); + mnfd = DefaultNumberOption(mnfd, 0, 20, undefined); // Step 12.c. - const mxfdActualDefault = std_Math_max(mnfd, mxfdDefault); + mxfd = DefaultNumberOption(mxfd, 0, 20, undefined); - // Step 12.d. - mxfd = DefaultNumberOption(mxfd, mnfd, 20, mxfdActualDefault); + // Steps 12.d-e. + // Inlined DefaultNumberOption, only the fallback case applies here. + if (mnfd === undefined) { + assert(mxfd !== undefined, "mxfd isn't undefined when mnfd is undefined"); + mnfd = std_Math_min(mnfdDefault, mxfd); + } + + // Step 12.f. + // Inlined DefaultNumberOption, only the fallback case applies here. + else if (mxfd === undefined) { + mxfd = std_Math_max(mxfdDefault, mnfd); + } - // Step 12.e. + // Step 12.g. + else if (mnfd > mxfd) { + ThrowRangeError(JSMSG_INVALID_DIGITS_VALUE, mxfd); + } + + // Step 12.h. lazyData.minimumFractionDigits = mnfd; - // Step 12.f. + // Step 12.i. lazyData.maximumFractionDigits = mxfd; } -- cgit v1.2.3 From 398486a64bdd0c3ae7df24719dd434d13e58895a Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Fri, 20 Oct 2023 04:21:49 -0500 Subject: Issue #2282 - Align the Performance Observer navigation and resource with the spec. This now passes the conformance tests. https://bugzilla.mozilla.org/show_bug.cgi?id=1425458 Resource timing entries Workers - part 2 - PerformanceTimingData. https://bugzilla.mozilla.org/show_bug.cgi?id=1462605 PerformanceNavigationTiming.name must be the value of the address of the current document. https://bugzilla.mozilla.org/show_bug.cgi?id=1462883 Update PerformanceTimingData::mReportCrossOriginRedirect in SetPropertiesFromHttpChannel. https://bugzilla.mozilla.org/show_bug.cgi?id=1462879 PerformanceNavigationTiming must be notified correctly - part 1 - notify. --- dom/base/nsGlobalWindow.cpp | 9 + dom/base/nsPIDOMWindow.h | 2 + dom/performance/Performance.h | 2 + dom/performance/PerformanceMainThread.cpp | 70 ++++-- dom/performance/PerformanceMainThread.h | 5 +- dom/performance/PerformanceNavigation.cpp | 2 +- dom/performance/PerformanceNavigationTiming.cpp | 20 +- dom/performance/PerformanceNavigationTiming.h | 16 +- dom/performance/PerformanceResourceTiming.cpp | 49 +--- dom/performance/PerformanceResourceTiming.h | 99 +++----- dom/performance/PerformanceTiming.cpp | 255 +++++++++++++-------- dom/performance/PerformanceTiming.h | 288 +++++++++++++++--------- dom/performance/PerformanceWorker.h | 5 + layout/base/nsDocumentViewer.cpp | 5 + 14 files changed, 484 insertions(+), 343 deletions(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index ae84de3a19..a69b5e177a 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -4222,6 +4222,15 @@ nsGlobalWindow::GetPerformance() return AsInner()->GetPerformance(); } +void +nsPIDOMWindowInner::QueuePerformanceNavigationTiming() +{ + CreatePerformanceObjectIfNeeded(); + if (mPerformance) { + mPerformance->QueueNavigationTimingEntry(); + } +} + void nsPIDOMWindowInner::CreatePerformanceObjectIfNeeded() { diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index ffebf6570d..110da38604 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -727,6 +727,8 @@ public: mozilla::dom::Performance* GetPerformance(); + void QueuePerformanceNavigationTiming(); + bool HasMutationListeners(uint32_t aMutationEventType) const { if (!mOuterWindow) { diff --git a/dom/performance/Performance.h b/dom/performance/Performance.h index 7a60eb85a9..2e1b63c45b 100644 --- a/dom/performance/Performance.h +++ b/dom/performance/Performance.h @@ -124,6 +124,8 @@ public: return false; } + virtual void QueueNavigationTimingEntry() = 0; + protected: Performance(); explicit Performance(nsPIDOMWindowInner* aWindow); diff --git a/dom/performance/PerformanceMainThread.cpp b/dom/performance/PerformanceMainThread.cpp index a4dbf88799..b5ca6ca1be 100644 --- a/dom/performance/PerformanceMainThread.cpp +++ b/dom/performance/PerformanceMainThread.cpp @@ -15,6 +15,34 @@ namespace mozilla { namespace dom { +namespace { + +void +GetURLSpecFromChannel(nsITimedChannel* aChannel, nsAString& aSpec) +{ + aSpec.AssignLiteral("document"); + + nsCOMPtr channel = do_QueryInterface(aChannel); + if (!channel) { + return; + } + + nsCOMPtr uri; + nsresult rv = channel->GetURI(getter_AddRefs(uri)); + if (NS_WARN_IF(NS_FAILED(rv)) || !uri) { + return; + } + + nsAutoCString spec; + rv = uri->GetSpec(spec); + if (NS_WARN_IF(NS_FAILED(rv))) { + return; + } + + aSpec = NS_ConvertUTF8toUTF16(spec); +} + +} // anonymous NS_IMPL_CYCLE_COLLECTION_CLASS(PerformanceMainThread) @@ -60,6 +88,7 @@ PerformanceMainThread::PerformanceMainThread(nsPIDOMWindowInner* aWindow, , mChannel(aChannel) { MOZ_ASSERT(aWindow, "Parent window object should be provided"); + CreateNavigationTimingEntry(); } PerformanceMainThread::~PerformanceMainThread() @@ -159,14 +188,14 @@ PerformanceMainThread::AddEntry(nsIHttpChannel* channel, // The last argument is the "zero time" (offset). Since we don't want // any offset for the resource timing, this will be set to "0" - the // resource timing returns a relative timing (no offset). - RefPtr performanceTiming = - new PerformanceTiming(this, timedChannel, channel, - 0); + UniquePtr performanceTimingData( + new PerformanceTimingData(timedChannel, channel, 0)); // The PerformanceResourceTiming object will use the PerformanceTiming // object to get all the required timings. RefPtr performanceEntry = - new PerformanceResourceTiming(performanceTiming, this, entryName, channel); + new PerformanceResourceTiming(std::move(performanceTimingData), this, entryName); + // If the initiator type had no valid value, then set it to the default // ("other") value. if (initiatorType.IsEmpty()) { @@ -299,17 +328,31 @@ PerformanceMainThread::CreationTime() const } void -PerformanceMainThread::EnsureDocEntry() +PerformanceMainThread::CreateNavigationTimingEntry() { - if (!mDocEntry && nsContentUtils::IsPerformanceNavigationTimingEnabled()) { - nsCOMPtr httpChannel = do_QueryInterface(mChannel); - RefPtr timing = - new PerformanceTiming(this, mChannel, nullptr, 0); - mDocEntry = new PerformanceNavigationTiming(timing, this, - httpChannel); + MOZ_ASSERT(!mDocEntry, "mDocEntry should be null."); + + nsAutoString name; + GetURLSpecFromChannel(mChannel, name); + + UniquePtr timing( + new PerformanceTimingData(mChannel, nullptr, 0)); + + nsCOMPtr httpChannel = do_QueryInterface(mChannel); + if (httpChannel) { + timing->SetPropertiesFromHttpChannel(httpChannel, mChannel); } + + mDocEntry = new PerformanceNavigationTiming(std::move(timing), this, name); } +void +PerformanceMainThread::QueueNavigationTimingEntry() +{ + if (mDocEntry) { + QueueEntry(mDocEntry); + } +} void PerformanceMainThread::GetEntries(nsTArray>& aRetval) @@ -317,7 +360,6 @@ PerformanceMainThread::GetEntries(nsTArray>& aRetval) aRetval = mResourceEntries; aRetval.AppendElements(mUserEntries); - EnsureDocEntry(); if (mDocEntry) { aRetval.AppendElement(mDocEntry); } @@ -331,7 +373,7 @@ PerformanceMainThread::GetEntriesByType(const nsAString& aEntryType, { if (aEntryType.EqualsLiteral("navigation")) { aRetval.Clear(); - EnsureDocEntry(); + if (mDocEntry) { aRetval.AppendElement(mDocEntry); } @@ -348,7 +390,7 @@ PerformanceMainThread::GetEntriesByName(const nsAString& aName, { if (aName.EqualsLiteral("document")) { aRetval.Clear(); - EnsureDocEntry(); + if (mDocEntry) { aRetval.AppendElement(mDocEntry); } diff --git a/dom/performance/PerformanceMainThread.h b/dom/performance/PerformanceMainThread.h index 702483e9de..fc81c94e2a 100644 --- a/dom/performance/PerformanceMainThread.h +++ b/dom/performance/PerformanceMainThread.h @@ -62,9 +62,13 @@ public: return true; } + void QueueNavigationTimingEntry() override; + protected: ~PerformanceMainThread(); + void CreateNavigationTimingEntry(); + nsISupports* GetAsISupports() override { return this; @@ -76,7 +80,6 @@ protected: GetPerformanceTimingFromString(const nsAString& aTimingName) override; void DispatchBufferFullEvent() override; - void EnsureDocEntry(); RefPtr mDocEntry; RefPtr mDOMTiming; diff --git a/dom/performance/PerformanceNavigation.cpp b/dom/performance/PerformanceNavigation.cpp index 24b3af11f8..1b96de1cf4 100644 --- a/dom/performance/PerformanceNavigation.cpp +++ b/dom/performance/PerformanceNavigation.cpp @@ -35,7 +35,7 @@ PerformanceNavigation::WrapObject(JSContext *cx, uint16_t PerformanceNavigation::RedirectCount() const { - return GetPerformanceTiming()->GetRedirectCount(); + return GetPerformanceTiming()->Data()->GetRedirectCount(); } } // dom namespace diff --git a/dom/performance/PerformanceNavigationTiming.cpp b/dom/performance/PerformanceNavigationTiming.cpp index 37d54366c6..1c4a30b569 100644 --- a/dom/performance/PerformanceNavigationTiming.cpp +++ b/dom/performance/PerformanceNavigationTiming.cpp @@ -24,55 +24,55 @@ PerformanceNavigationTiming::WrapObject(JSContext* aCx, JS::Handle aG DOMHighResTimeStamp PerformanceNavigationTiming::UnloadEventStart() const { - return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetUnloadEventStartHighRes()); + return mPerformance->GetDOMTiming()->GetUnloadEventStartHighRes(); } DOMHighResTimeStamp PerformanceNavigationTiming::UnloadEventEnd() const { - return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetUnloadEventEndHighRes()); + return mPerformance->GetDOMTiming()->GetUnloadEventEndHighRes(); } DOMHighResTimeStamp PerformanceNavigationTiming::DomInteractive() const { - return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetDomInteractiveHighRes()); + return mPerformance->GetDOMTiming()->GetDomInteractiveHighRes(); } DOMHighResTimeStamp PerformanceNavigationTiming::DomContentLoadedEventStart() const { - return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetDomContentLoadedEventStartHighRes()); + return mPerformance->GetDOMTiming()->GetDomContentLoadedEventStartHighRes(); } DOMHighResTimeStamp PerformanceNavigationTiming::DomContentLoadedEventEnd() const { - return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetDomContentLoadedEventEndHighRes()); + return mPerformance->GetDOMTiming()->GetDomContentLoadedEventEndHighRes(); } DOMHighResTimeStamp PerformanceNavigationTiming::DomComplete() const { - return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetDomCompleteHighRes()); + return mPerformance->GetDOMTiming()->GetDomCompleteHighRes(); } DOMHighResTimeStamp PerformanceNavigationTiming::LoadEventStart() const { - return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetLoadEventStartHighRes()); + return mPerformance->GetDOMTiming()->GetLoadEventStartHighRes(); } DOMHighResTimeStamp PerformanceNavigationTiming::LoadEventEnd() const { - return TimerClamping::ReduceMsTimeValue(mTiming->GetDOMTiming()->GetLoadEventEndHighRes()); + return mPerformance->GetDOMTiming()->GetLoadEventEndHighRes(); } NavigationType PerformanceNavigationTiming::Type() const { - switch(mTiming->GetDOMTiming()->GetType()) { + switch(mPerformance->GetDOMTiming()->GetType()) { case nsDOMNavigationTiming::TYPE_NAVIGATE: return NavigationType::Navigate; break; @@ -92,5 +92,5 @@ PerformanceNavigationTiming::Type() const uint16_t PerformanceNavigationTiming::RedirectCount() const { - return mTiming->GetRedirectCount(); + return mTimingData->GetRedirectCount(); } diff --git a/dom/performance/PerformanceNavigationTiming.h b/dom/performance/PerformanceNavigationTiming.h index f528c5337e..93471e17de 100644 --- a/dom/performance/PerformanceNavigationTiming.h +++ b/dom/performance/PerformanceNavigationTiming.h @@ -27,14 +27,14 @@ public: // so that timestamps are relative to startTime, as opposed to the // performance.timing object for which timestamps are absolute and has a // zeroTime initialized to navigationStart - explicit PerformanceNavigationTiming(PerformanceTiming* aPerformanceTiming, - Performance* aPerformance, - nsIHttpChannel* aChannel) - : PerformanceResourceTiming(aPerformanceTiming, aPerformance, - NS_LITERAL_STRING("document"), aChannel) { - SetEntryType(NS_LITERAL_STRING("navigation")); - SetInitiatorType(NS_LITERAL_STRING("navigation")); - } + PerformanceNavigationTiming(UniquePtr&& aPerformanceTiming, + Performance* aPerformance, + const nsAString& aName) + : PerformanceResourceTiming(Move(aPerformanceTiming), aPerformance, aName) + { + SetEntryType(NS_LITERAL_STRING("navigation")); + SetInitiatorType(NS_LITERAL_STRING("navigation")); + } DOMHighResTimeStamp Duration() const override { diff --git a/dom/performance/PerformanceResourceTiming.cpp b/dom/performance/PerformanceResourceTiming.cpp index 6f84896af1..cb08b39b65 100644 --- a/dom/performance/PerformanceResourceTiming.cpp +++ b/dom/performance/PerformanceResourceTiming.cpp @@ -11,7 +11,7 @@ using namespace mozilla::dom; NS_IMPL_CYCLE_COLLECTION_INHERITED(PerformanceResourceTiming, PerformanceEntry, - mTiming) + mPerformance) NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PerformanceResourceTiming, PerformanceEntry) @@ -23,45 +23,14 @@ NS_INTERFACE_MAP_END_INHERITING(PerformanceEntry) NS_IMPL_ADDREF_INHERITED(PerformanceResourceTiming, PerformanceEntry) NS_IMPL_RELEASE_INHERITED(PerformanceResourceTiming, PerformanceEntry) -PerformanceResourceTiming::PerformanceResourceTiming(PerformanceTiming* aPerformanceTiming, +PerformanceResourceTiming::PerformanceResourceTiming(UniquePtr&& aPerformanceTiming, Performance* aPerformance, - const nsAString& aName, - nsIHttpChannel* aChannel) -: PerformanceEntry(aPerformance, aName, NS_LITERAL_STRING("resource")), - mTiming(aPerformanceTiming), - mEncodedBodySize(0), - mTransferSize(0), - mDecodedBodySize(0) + const nsAString& aName) + : PerformanceEntry(aPerformance->GetParentObject(), aName, NS_LITERAL_STRING("resource")) + , mTimingData(Move(aPerformanceTiming)) + , mPerformance(aPerformance) { MOZ_ASSERT(aPerformance, "Parent performance object should be provided"); - SetPropertiesFromChannel(aChannel); -} - -void -PerformanceResourceTiming::SetPropertiesFromChannel(nsIHttpChannel* aChannel) -{ - if (!aChannel) { - return; - } - - nsAutoCString protocol; - Unused << aChannel->GetProtocolVersion(protocol); - SetNextHopProtocol(NS_ConvertUTF8toUTF16(protocol)); - - uint64_t encodedBodySize = 0; - Unused << aChannel->GetEncodedBodySize(&encodedBodySize); - SetEncodedBodySize(encodedBodySize); - - uint64_t transferSize = 0; - Unused << aChannel->GetTransferSize(&transferSize); - SetTransferSize(transferSize); - - uint64_t decodedBodySize = 0; - Unused << aChannel->GetDecodedBodySize(&decodedBodySize); - if (decodedBodySize == 0) { - decodedBodySize = encodedBodySize; - } - SetDecodedBodySize(decodedBodySize); } PerformanceResourceTiming::~PerformanceResourceTiming() @@ -78,13 +47,13 @@ PerformanceResourceTiming::StartTime() const // Ignore zero values. The RedirectStart and WorkerStart values // can come from earlier redirected channels prior to the AsyncOpen // time being recorded. - DOMHighResTimeStamp redirect = mTiming->RedirectStartHighRes(); + DOMHighResTimeStamp redirect = mTimingData->RedirectStartHighRes(mPerformance); redirect = redirect ? redirect : DBL_MAX; - DOMHighResTimeStamp worker = mTiming->WorkerStartHighRes(); + DOMHighResTimeStamp worker = mTimingData->WorkerStartHighRes(mPerformance); worker = worker ? worker : DBL_MAX; - DOMHighResTimeStamp asyncOpen = mTiming->AsyncOpenHighRes(); + DOMHighResTimeStamp asyncOpen = mTimingData->AsyncOpenHighRes(mPerformance); return std::min(asyncOpen, std::min(redirect, worker)); } diff --git a/dom/performance/PerformanceResourceTiming.h b/dom/performance/PerformanceResourceTiming.h index 63a8c24149..fd085b120a 100644 --- a/dom/performance/PerformanceResourceTiming.h +++ b/dom/performance/PerformanceResourceTiming.h @@ -6,9 +6,8 @@ #ifndef mozilla_dom_PerformanceResourceTiming_h___ #define mozilla_dom_PerformanceResourceTiming_h___ +#include "mozilla/UniquePtr.h" #include "nsCOMPtr.h" -#include "nsIChannel.h" -#include "nsITimedChannel.h" #include "Performance.h" #include "PerformanceEntry.h" #include "PerformanceTiming.h" @@ -27,10 +26,9 @@ public: PerformanceResourceTiming, PerformanceEntry) - PerformanceResourceTiming(PerformanceTiming* aPerformanceTiming, + PerformanceResourceTiming(UniquePtr&& aPerformanceTimingData, Performance* aPerformance, - const nsAString& aName, - nsIHttpChannel* aChannel = nullptr); + const nsAString& aName); virtual JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; @@ -54,93 +52,85 @@ public: void GetNextHopProtocol(nsAString& aNextHopProtocol) const { - if (mTiming && mTiming->TimingAllowed()) { - aNextHopProtocol = mNextHopProtocol; + if (mTimingData) { + aNextHopProtocol = mTimingData->NextHopProtocol(); } } - void SetNextHopProtocol(const nsAString& aNextHopProtocol) - { - mNextHopProtocol = aNextHopProtocol; - } - DOMHighResTimeStamp WorkerStart() const { - return mTiming && mTiming->TimingAllowed() - ? mTiming->WorkerStartHighRes() + return mTimingData + ? mTimingData->WorkerStartHighRes(mPerformance) : 0; } DOMHighResTimeStamp FetchStart() const { - if (mTiming) { - return mTiming->TimingAllowed() - ? mTiming->FetchStartHighRes() - : StartTime(); - } - return 0; + return mTimingData + ? mTimingData->FetchStartHighRes(mPerformance) + : 0; } DOMHighResTimeStamp RedirectStart() const { // We have to check if all the redirect URIs had the same origin (since // there is no check in RedirectEndHighRes()) - return mTiming && mTiming->ShouldReportCrossOriginRedirect() - ? mTiming->RedirectStartHighRes() + return mTimingData && mTimingData->ShouldReportCrossOriginRedirect() + ? mTimingData->RedirectStartHighRes(mPerformance) : 0; } DOMHighResTimeStamp RedirectEnd() const { // We have to check if all the redirect URIs had the same origin (since // there is no check in RedirectEndHighRes()) - return mTiming && mTiming->ShouldReportCrossOriginRedirect() - ? mTiming->RedirectEndHighRes() + return mTimingData && mTimingData->ShouldReportCrossOriginRedirect() + ? mTimingData->RedirectEndHighRes(mPerformance) : 0; } DOMHighResTimeStamp DomainLookupStart() const { - return mTiming && mTiming->TimingAllowed() - ? mTiming->DomainLookupStartHighRes() + return mTimingData && mTimingData->TimingAllowed() + ? mTimingData->DomainLookupStartHighRes(mPerformance) : 0; } DOMHighResTimeStamp DomainLookupEnd() const { - return mTiming && mTiming->TimingAllowed() - ? mTiming->DomainLookupEndHighRes() + return mTimingData && mTimingData->TimingAllowed() + ? mTimingData->DomainLookupEndHighRes(mPerformance) : 0; } DOMHighResTimeStamp ConnectStart() const { - return mTiming && mTiming->TimingAllowed() - ? mTiming->ConnectStartHighRes() + return mTimingData && mTimingData->TimingAllowed() + ? mTimingData->ConnectStartHighRes(mPerformance) : 0; } DOMHighResTimeStamp ConnectEnd() const { - return mTiming && mTiming->TimingAllowed() - ? mTiming->ConnectEndHighRes() + return mTimingData && mTimingData->TimingAllowed() + ? mTimingData->ConnectEndHighRes(mPerformance) : 0; } DOMHighResTimeStamp RequestStart() const { - return mTiming && mTiming->TimingAllowed() - ? mTiming->RequestStartHighRes() + return mTimingData && mTimingData->TimingAllowed() + ? mTimingData->RequestStartHighRes(mPerformance) : 0; } DOMHighResTimeStamp ResponseStart() const { - return mTiming && mTiming->TimingAllowed() - ? mTiming->ResponseStartHighRes() + return mTimingData && mTimingData->TimingAllowed() + ? mTimingData->ResponseStartHighRes(mPerformance) : 0; } DOMHighResTimeStamp ResponseEnd() const { - return mTiming - ? mTiming->ResponseEndHighRes() + return mTimingData + ? mTimingData->ResponseEndHighRes(mPerformance) : 0; } DOMHighResTimeStamp SecureConnectionStart() const { - return mTiming && mTiming->TimingAllowed() - ? mTiming->SecureConnectionStartHighRes() + return mTimingData && mTimingData->TimingAllowed() + ? mTimingData->SecureConnectionStartHighRes(mPerformance) : 0; } @@ -151,44 +141,25 @@ public: uint64_t TransferSize() const { - return mTiming && mTiming->TimingAllowed() ? mTransferSize : 0; + return mTimingData ? mTimingData->TransferSize() : 0; } uint64_t EncodedBodySize() const { - return mTiming && mTiming->TimingAllowed() ? mEncodedBodySize : 0; + return mTimingData ? mTimingData->EncodedBodySize() : 0; } uint64_t DecodedBodySize() const { - return mTiming && mTiming->TimingAllowed() ? mDecodedBodySize : 0; - } - - void SetEncodedBodySize(uint64_t aEncodedBodySize) - { - mEncodedBodySize = aEncodedBodySize; - } - - void SetTransferSize(uint64_t aTransferSize) - { - mTransferSize = aTransferSize; - } - - void SetDecodedBodySize(uint64_t aDecodedBodySize) - { - mDecodedBodySize = aDecodedBodySize; + return mTimingData ? mTimingData->DecodedBodySize() : 0; } protected: virtual ~PerformanceResourceTiming(); - void SetPropertiesFromChannel(nsIHttpChannel* aChannel); nsString mInitiatorType; - nsString mNextHopProtocol; - RefPtr mTiming; - uint64_t mEncodedBodySize; - uint64_t mTransferSize; - uint64_t mDecodedBodySize; + UniquePtr mTimingData; + RefPtr mPerformance; }; } // namespace dom diff --git a/dom/performance/PerformanceTiming.cpp b/dom/performance/PerformanceTiming.cpp index 5c33457d0c..7e10a7edda 100755 --- a/dom/performance/PerformanceTiming.cpp +++ b/dom/performance/PerformanceTiming.cpp @@ -19,34 +19,39 @@ PerformanceTiming::PerformanceTiming(Performance* aPerformance, nsITimedChannel* aChannel, nsIHttpChannel* aHttpChannel, DOMHighResTimeStamp aZeroTime) - : mPerformance(aPerformance), - mFetchStart(0.0), - mZeroTime(TimerClamping::ReduceMsTimeValue(aZeroTime)), - mRedirectCount(0), - mTimingAllowed(true), - mAllRedirectsSameOrigin(true), - mInitialized(!!aChannel), - mReportCrossOriginRedirect(true) + : mPerformance(aPerformance) { MOZ_ASSERT(aPerformance, "Parent performance object should be provided"); + mTimingData.reset(new PerformanceTimingData(aChannel, aHttpChannel, + aZeroTime)); +} + +// Copy the timing info from the channel so we don't need to keep the channel +// alive just to get the timestamps. +PerformanceTimingData::PerformanceTimingData(nsITimedChannel* aChannel, + nsIHttpChannel* aHttpChannel, + DOMHighResTimeStamp aZeroTime) + : mZeroTime(0.0) + , mFetchStart(0.0) + , mEncodedBodySize(0) + , mTransferSize(0) + , mDecodedBodySize(0) + , mRedirectCount(0) + , mAllRedirectsSameOrigin(true) + , mReportCrossOriginRedirect(true) + , mSecureConnection(false) + , mTimingAllowed(true) + , mInitialized(false) +{ + mInitialized = !!aChannel; + + mZeroTime = TimerClamping::ReduceMsTimeValue(aZeroTime); + if (!nsContentUtils::IsPerformanceTimingEnabled()) { mZeroTime = 0; } - // The aHttpChannel argument is null if this PerformanceTiming object is - // being used for navigation timing (which is only relevant for documents). - // It has a non-null value if this PerformanceTiming object is being used - // for resource timing, which can include document loads, both toplevel and - // in subframes, and resources linked from a document. - if (aHttpChannel) { - mTimingAllowed = CheckAllowedOrigin(aHttpChannel, aChannel); - bool redirectsPassCheck = false; - aChannel->GetAllRedirectsPassTimingAllowCheck(&redirectsPassCheck); - mReportCrossOriginRedirect = mTimingAllowed && redirectsPassCheck; - } - - mSecureConnection = false; nsCOMPtr uri; if (aHttpChannel) { aHttpChannel->GetURI(getter_AddRefs(uri)); @@ -63,14 +68,7 @@ PerformanceTiming::PerformanceTiming(Performance* aPerformance, mSecureConnection = false; } } - InitializeTimingInfo(aChannel); -} -// Copy the timing info from the channel so we don't need to keep the channel -// alive just to get the timestamps. -void -PerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel) -{ if (aChannel) { aChannel->GetAsyncOpen(&mAsyncOpen); aChannel->GetDispatchFetchEventStart(&mWorkerStart); @@ -90,11 +88,11 @@ PerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel) aChannel->GetCacheReadEnd(&mCacheReadEnd); // The performance timing api essentially requires that the event timestamps - // have a strict relation with each other. The truth, however, is the browser - // engages in a number of speculative activities that sometimes mean connections - // and lookups begin at different times. Workaround that here by clamping - // these values to what we expect FetchStart to be. This means the later of - // AsyncOpen or WorkerStart times. + // have a strict relation with each other. The truth, however, is the + // browser engages in a number of speculative activities that sometimes mean + // connections and lookups begin at different times. Workaround that here by + // clamping these values to what we expect FetchStart to be. This means the + // later of AsyncOpen or WorkerStart times. if (!mAsyncOpen.IsNull()) { // We want to clamp to the expected FetchStart value. This is later of // the AsyncOpen and WorkerStart values. @@ -125,6 +123,43 @@ PerformanceTiming::InitializeTimingInfo(nsITimedChannel* aChannel) } } } + + // The aHttpChannel argument is null if this PerformanceTiming object is + // being used for navigation timing (which is only relevant for documents). + // It has a non-null value if this PerformanceTiming object is being used + // for resource timing, which can include document loads, both toplevel and + // in subframes, and resources linked from a document. + if (aHttpChannel) { + mTimingAllowed = CheckAllowedOrigin(aHttpChannel, aChannel); + bool redirectsPassCheck = false; + aChannel->GetAllRedirectsPassTimingAllowCheck(&redirectsPassCheck); + mReportCrossOriginRedirect = mTimingAllowed && redirectsPassCheck; + + SetPropertiesFromHttpChannel(aHttpChannel, aChannel); + } +} + +void +PerformanceTimingData::SetPropertiesFromHttpChannel(nsIHttpChannel* aHttpChannel, + nsITimedChannel* aChannel) +{ + MOZ_ASSERT(aHttpChannel); + + nsAutoCString protocol; + Unused << aHttpChannel->GetProtocolVersion(protocol); + mNextHopProtocol = NS_ConvertUTF8toUTF16(protocol); + + Unused << aHttpChannel->GetEncodedBodySize(&mEncodedBodySize); + Unused << aHttpChannel->GetTransferSize(&mTransferSize); + Unused << aHttpChannel->GetDecodedBodySize(&mDecodedBodySize); + if (mDecodedBodySize == 0) { + mDecodedBodySize = mEncodedBodySize; + } + + mTimingAllowed = CheckAllowedOrigin(aHttpChannel, aChannel); + bool redirectsPassCheck = false; + aChannel->GetAllRedirectsPassTimingAllowCheck(&redirectsPassCheck); + mReportCrossOriginRedirect = mTimingAllowed && redirectsPassCheck; } PerformanceTiming::~PerformanceTiming() @@ -132,8 +167,10 @@ PerformanceTiming::~PerformanceTiming() } DOMHighResTimeStamp -PerformanceTiming::FetchStartHighRes() +PerformanceTimingData::FetchStartHighRes(Performance* aPerformance) { + MOZ_ASSERT(aPerformance); + if (!mFetchStart) { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { return mZeroTime; @@ -142,9 +179,9 @@ PerformanceTiming::FetchStartHighRes() "valid if the performance timing is enabled"); if (!mAsyncOpen.IsNull()) { if (!mWorkerStart.IsNull() && mWorkerStart > mAsyncOpen) { - mFetchStart = TimeStampToDOMHighRes(mWorkerStart); + mFetchStart = TimeStampToDOMHighRes(aPerformance, mWorkerRequestStart); } else { - mFetchStart = TimeStampToDOMHighRes(mAsyncOpen); + mFetchStart = TimeStampToDOMHighRes(aPerformance, mAsyncOpen); } } } @@ -154,12 +191,12 @@ PerformanceTiming::FetchStartHighRes() DOMTimeMilliSec PerformanceTiming::FetchStart() { - return static_cast(FetchStartHighRes()); + return static_cast(mTimingData->FetchStartHighRes(mPerformance)); } bool -PerformanceTiming::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel, - nsITimedChannel* aChannel) +PerformanceTimingData::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel, + nsITimedChannel* aChannel) { if (!IsInitialized()) { return false; @@ -187,14 +224,8 @@ PerformanceTiming::CheckAllowedOrigin(nsIHttpChannel* aResourceChannel, return aChannel->TimingAllowCheck(principal); } -bool -PerformanceTiming::TimingAllowed() const -{ - return mTimingAllowed; -} - uint8_t -PerformanceTiming::GetRedirectCount() const +PerformanceTimingData::GetRedirectCount() const { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { return 0; @@ -206,7 +237,7 @@ PerformanceTiming::GetRedirectCount() const } bool -PerformanceTiming::ShouldReportCrossOriginRedirect() const +PerformanceTimingData::ShouldReportCrossOriginRedirect() const { if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { return false; @@ -219,23 +250,27 @@ PerformanceTiming::ShouldReportCrossOriginRedirect() const } DOMHighResTimeStamp -PerformanceTiming::AsyncOpenHighRes() +PerformanceTimingData::AsyncOpenHighRes(Performance* aPerformance) { + MOZ_ASSERT(aPerformance); + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() || mAsyncOpen.IsNull()) { return mZeroTime; } - return TimeStampToReducedDOMHighResOrFetchStart(mAsyncOpen); + return TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(aPerformance, mAsyncOpen)); } DOMHighResTimeStamp -PerformanceTiming::WorkerStartHighRes() +PerformanceTimingData::WorkerStartHighRes(Performance* aPerformance) { + MOZ_ASSERT(aPerformance); + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized() || mWorkerStart.IsNull()) { return mZeroTime; } - return TimeStampToReducedDOMHighResOrFetchStart(mWorkerStart); + return TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(aPerformance, mWorkerStart)); } /** @@ -249,24 +284,27 @@ PerformanceTiming::WorkerStartHighRes() * @return a valid timing if the Performance Timing is enabled */ DOMHighResTimeStamp -PerformanceTiming::RedirectStartHighRes() +PerformanceTimingData::RedirectStartHighRes(Performance* aPerformance) { + MOZ_ASSERT(aPerformance); + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { return mZeroTime; } - return TimeStampToReducedDOMHighResOrFetchStart(mRedirectStart); + return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, mRedirectStart); } DOMTimeMilliSec PerformanceTiming::RedirectStart() { - if (!IsInitialized()) { + if (!mTimingData->IsInitialized()) { return 0; } // We have to check if all the redirect URIs had the same origin (since there // is no check in RedirectStartHighRes()) - if (mAllRedirectsSameOrigin && mRedirectCount) { - return static_cast(RedirectStartHighRes()); + if (mTimingData->AllRedirectsSameOrigin() && + mTimingData->RedirectCountReal()) { + return static_cast(mTimingData->RedirectStartHighRes(mPerformance)); } return 0; } @@ -282,130 +320,155 @@ PerformanceTiming::RedirectStart() * @return a valid timing if the Performance Timing is enabled */ DOMHighResTimeStamp -PerformanceTiming::RedirectEndHighRes() +PerformanceTimingData::RedirectEndHighRes(Performance* aPerformance) { + MOZ_ASSERT(aPerformance); + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { return mZeroTime; } - return TimeStampToReducedDOMHighResOrFetchStart(mRedirectEnd); + return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, mRedirectEnd); } DOMTimeMilliSec PerformanceTiming::RedirectEnd() { - if (!IsInitialized()) { + if (!mTimingData->IsInitialized()) { return 0; } // We have to check if all the redirect URIs had the same origin (since there // is no check in RedirectEndHighRes()) - if (mAllRedirectsSameOrigin && mRedirectCount) { - return static_cast(RedirectEndHighRes()); + if (mTimingData->AllRedirectsSameOrigin() && + mTimingData->RedirectCountReal()) { + return static_cast(mTimingData->RedirectEndHighRes(mPerformance)); } return 0; } DOMHighResTimeStamp -PerformanceTiming::DomainLookupStartHighRes() +PerformanceTimingData::DomainLookupStartHighRes(Performance* aPerformance) { + MOZ_ASSERT(aPerformance); + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { return mZeroTime; } - return TimeStampToReducedDOMHighResOrFetchStart(mDomainLookupStart); + return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, + mDomainLookupStart); } DOMTimeMilliSec PerformanceTiming::DomainLookupStart() { - return static_cast(DomainLookupStartHighRes()); + return static_cast(mTimingData->DomainLookupStartHighRes(mPerformance)); } DOMHighResTimeStamp -PerformanceTiming::DomainLookupEndHighRes() +PerformanceTimingData::DomainLookupEndHighRes(Performance* aPerformance) { + MOZ_ASSERT(aPerformance); + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { return mZeroTime; } - // Bug 1155008 - nsHttpTransaction is racy. Return DomainLookupStart when null - return mDomainLookupEnd.IsNull() ? DomainLookupStartHighRes() - : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mDomainLookupEnd)); + return mDomainLookupEnd.IsNull() + ? DomainLookupStartHighRes(aPerformance) + : TimerClamping::ReduceMsTimeValue( + TimeStampToDOMHighRes(aPerformance, mDomainLookupEnd)); } DOMTimeMilliSec PerformanceTiming::DomainLookupEnd() { - return static_cast(DomainLookupEndHighRes()); + return static_cast(mTimingData->DomainLookupEndHighRes(mPerformance)); } DOMHighResTimeStamp -PerformanceTiming::ConnectStartHighRes() +PerformanceTimingData::ConnectStartHighRes(Performance* aPerformance) { + MOZ_ASSERT(aPerformance); + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { return mZeroTime; } - return mConnectStart.IsNull() ? DomainLookupEndHighRes() - : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mConnectStart)); + return mConnectStart.IsNull() + ? DomainLookupEndHighRes(aPerformance) + : TimerClamping::ReduceMsTimeValue( + TimeStampToDOMHighRes(aPerformance, mConnectStart)); } DOMTimeMilliSec PerformanceTiming::ConnectStart() { - return static_cast(ConnectStartHighRes()); + return static_cast(mTimingData->ConnectStartHighRes(mPerformance)); } DOMHighResTimeStamp -PerformanceTiming::SecureConnectionStartHighRes() +PerformanceTimingData::SecureConnectionStartHighRes(Performance* aPerformance) { + MOZ_ASSERT(aPerformance); + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { return mZeroTime; } return !mSecureConnection ? 0 // We use 0 here, because mZeroTime is sometimes set to the navigation // start time. - : (mSecureConnectionStart.IsNull() ? mZeroTime - : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mSecureConnectionStart))); + : (mSecureConnectionStart.IsNull() + ? mZeroTime + : TimerClamping::ReduceMsTimeValue( + TimeStampToDOMHighRes(aPerformance, mSecureConnectionStart))); } DOMTimeMilliSec PerformanceTiming::SecureConnectionStart() { - return static_cast(SecureConnectionStartHighRes()); + return static_cast(mTimingData->SecureConnectionStartHighRes(mPerformance)); } DOMHighResTimeStamp -PerformanceTiming::ConnectEndHighRes() +PerformanceTimingData::ConnectEndHighRes(Performance* aPerformance) { + MOZ_ASSERT(aPerformance); + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { return mZeroTime; } // Bug 1155008 - nsHttpTransaction is racy. Return ConnectStart when null - return mConnectEnd.IsNull() ? ConnectStartHighRes() - : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mConnectEnd)); + return mConnectEnd.IsNull() + ? ConnectStartHighRes(aPerformance) + : TimerClamping::ReduceMsTimeValue( + TimeStampToDOMHighRes(aPerformance, mConnectEnd)); } DOMTimeMilliSec PerformanceTiming::ConnectEnd() { - return static_cast(ConnectEndHighRes()); + return static_cast(mTimingData->ConnectEndHighRes(mPerformance)); } DOMHighResTimeStamp -PerformanceTiming::RequestStartHighRes() +PerformanceTimingData::RequestStartHighRes(Performance* aPerformance) { + MOZ_ASSERT(aPerformance); + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { return mZeroTime; } - return TimeStampToReducedDOMHighResOrFetchStart(mRequestStart); + return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, mRequestStart); } DOMTimeMilliSec PerformanceTiming::RequestStart() { - return static_cast(RequestStartHighRes()); + return static_cast(mTimingData->RequestStartHighRes(mPerformance)); } DOMHighResTimeStamp -PerformanceTiming::ResponseStartHighRes() +PerformanceTimingData::ResponseStartHighRes(Performance* aPerformance) { + MOZ_ASSERT(aPerformance); + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { return mZeroTime; } @@ -413,18 +476,20 @@ PerformanceTiming::ResponseStartHighRes() (!mCacheReadStart.IsNull() && mCacheReadStart < mResponseStart)) { mResponseStart = mCacheReadStart; } - return TimeStampToReducedDOMHighResOrFetchStart(mResponseStart); + return TimeStampToReducedDOMHighResOrFetchStart(aPerformance, mResponseStart); } DOMTimeMilliSec PerformanceTiming::ResponseStart() { - return static_cast(ResponseStartHighRes()); + return static_cast(mTimingData->ResponseStartHighRes(mPerformance)); } DOMHighResTimeStamp -PerformanceTiming::ResponseEndHighRes() +PerformanceTimingData::ResponseEndHighRes(Performance* aPerformance) { + MOZ_ASSERT(aPerformance); + if (!nsContentUtils::IsPerformanceTimingEnabled() || !IsInitialized()) { return mZeroTime; } @@ -433,20 +498,16 @@ PerformanceTiming::ResponseEndHighRes() mResponseEnd = mCacheReadEnd; } // Bug 1155008 - nsHttpTransaction is racy. Return ResponseStart when null - return mResponseEnd.IsNull() ? ResponseStartHighRes() - : TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(mResponseEnd)); + return mResponseEnd.IsNull() + ? ResponseStartHighRes(aPerformance) + : TimerClamping::ReduceMsTimeValue( + TimeStampToDOMHighRes(aPerformance, mResponseEnd)); } DOMTimeMilliSec PerformanceTiming::ResponseEnd() { - return static_cast(ResponseEndHighRes()); -} - -bool -PerformanceTiming::IsInitialized() const -{ - return mInitialized; + return static_cast(mTimingData->ResponseEndHighRes(mPerformance)); } JSObject* diff --git a/dom/performance/PerformanceTiming.h b/dom/performance/PerformanceTiming.h index c0d4b6237b..91bd14f0d7 100755 --- a/dom/performance/PerformanceTiming.h +++ b/dom/performance/PerformanceTiming.h @@ -19,44 +19,38 @@ class nsITimedChannel; namespace mozilla { namespace dom { -// Script "performance.timing" object -class PerformanceTiming final : public nsWrapperCache +class PerformanceTimingData final { public: -/** - * @param aPerformance - * The performance object (the JS parent). - * This will allow access to "window.performance.timing" attribute for - * the navigation timing (can't be null). - * @param aChannel - * An nsITimedChannel used to gather all the networking timings by both - * the navigation timing and the resource timing (can't be null). - * @param aHttpChannel - * An nsIHttpChannel (the resource's http channel). - * This will be used by the resource timing cross-domain check - * algorithm. - * Argument is null for the navigation timing (navigation timing uses - * another algorithm for the cross-domain redirects). - * @param aZeroTime - * The offset that will be added to the timestamp of each event. This - * argument should be equal to performance.navigationStart for - * navigation timing and "0" for the resource timing. - */ - PerformanceTiming(Performance* aPerformance, - nsITimedChannel* aChannel, - nsIHttpChannel* aHttpChannel, - DOMHighResTimeStamp aZeroTime); - NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PerformanceTiming) - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(PerformanceTiming) + PerformanceTimingData(nsITimedChannel* aChannel, + nsIHttpChannel* aHttpChannel, + DOMHighResTimeStamp aZeroTime); - nsDOMNavigationTiming* GetDOMTiming() const + void SetPropertiesFromHttpChannel(nsIHttpChannel* aHttpChannel, nsITimedChannel* aChannel); + + bool IsInitialized() const { - return mPerformance->GetDOMTiming(); + return mInitialized; } - Performance* GetParentObject() const + const nsString& NextHopProtocol() const { - return mPerformance; + return mNextHopProtocol; + } + + uint64_t TransferSize() const + { + return mTimingAllowed ? mTransferSize : 0; + } + + uint64_t EncodedBodySize() const + { + return mTimingAllowed ? mEncodedBodySize : 0; + } + + uint64_t DecodedBodySize() const + { + return mTimingAllowed ? mDecodedBodySize : 0; } /** @@ -68,11 +62,16 @@ public: * page), if the given TimeStamp is valid. Otherwise, it will return * the FetchStart timing value. */ - inline DOMHighResTimeStamp TimeStampToReducedDOMHighResOrFetchStart(TimeStamp aStamp) + inline DOMHighResTimeStamp + TimeStampToReducedDOMHighResOrFetchStart(Performance* aPerformance, + TimeStamp aStamp) { + MOZ_ASSERT(aPerformance); + return (!aStamp.IsNull()) - ? TimerClamping::ReduceMsTimeValue(TimeStampToDOMHighRes(aStamp)) - : FetchStartHighRes(); + ? TimerClamping::ReduceMsTimeValue( + TimeStampToDOMHighRes(aPerformance, aStamp)) + : FetchStartHighRes(aPerformance); } /** @@ -83,7 +82,7 @@ public: * * The algorithm operates in 2 steps: * 1. The first step is to subtract the two timestamps: the argument (the - * envet's timesramp) and the navigation start timestamp. This will result in + * event's timestamp) and the navigation start timestamp. This will result in * a relative timestamp of the event (relative to the navigation start - * window.performance.timing.navigationStart). * 2. The second step is to add any required offset (the mZeroTime). For now, @@ -99,17 +98,154 @@ public: * be null. * @return number of milliseconds value as one of: * - relative to the navigation start time, time the user has landed on the - * page + * page * - an absolute wall clock time since the unix epoch */ - inline DOMHighResTimeStamp TimeStampToDOMHighRes(TimeStamp aStamp) const + inline DOMHighResTimeStamp + TimeStampToDOMHighRes(Performance* aPerformance, TimeStamp aStamp) const { + MOZ_ASSERT(aPerformance); MOZ_ASSERT(!aStamp.IsNull()); + TimeDuration duration = - aStamp - GetDOMTiming()->GetNavigationStartTimeStamp(); + aStamp - aPerformance->GetDOMTiming()->GetNavigationStartTimeStamp(); return duration.ToMilliseconds() + mZeroTime; } + // The last channel's AsyncOpen time. This may occur before the FetchStart + // in some cases. + DOMHighResTimeStamp AsyncOpenHighRes(Performance* aPerformance); + + // High resolution (used by resource timing) + DOMHighResTimeStamp WorkerStartHighRes(Performance* aPerformance); + DOMHighResTimeStamp FetchStartHighRes(Performance* aPerformance); + DOMHighResTimeStamp RedirectStartHighRes(Performance* aPerformance); + DOMHighResTimeStamp RedirectEndHighRes(Performance* aPerformance); + DOMHighResTimeStamp DomainLookupStartHighRes(Performance* aPerformance); + DOMHighResTimeStamp DomainLookupEndHighRes(Performance* aPerformance); + DOMHighResTimeStamp ConnectStartHighRes(Performance* aPerformance); + DOMHighResTimeStamp SecureConnectionStartHighRes(Performance* aPerformance); + DOMHighResTimeStamp ConnectEndHighRes(Performance* aPerformance); + DOMHighResTimeStamp RequestStartHighRes(Performance* aPerformance); + DOMHighResTimeStamp ResponseStartHighRes(Performance* aPerformance); + DOMHighResTimeStamp ResponseEndHighRes(Performance* aPerformance); + + DOMHighResTimeStamp ZeroTime() const { return mZeroTime; } + + uint8_t RedirectCountReal() const { return mRedirectCount; } + uint8_t GetRedirectCount() const; + + bool AllRedirectsSameOrigin() const { return mAllRedirectsSameOrigin; } + + // If this is false the values of redirectStart/End will be 0 This is false if + // no redirects occured, or if any of the responses failed the + // timing-allow-origin check in HttpBaseChannel::TimingAllowCheck + bool ShouldReportCrossOriginRedirect() const; + + // Cached result of CheckAllowedOrigin. If false, security sensitive + // attributes of the resourceTiming object will be set to 0 + bool TimingAllowed() const + { + return mTimingAllowed; + } + +private: + // Checks if the resource is either same origin as the page that started + // the load, or if the response contains the Timing-Allow-Origin header + // with a value of * or matching the domain of the loading Principal + bool CheckAllowedOrigin(nsIHttpChannel* aResourceChannel, + nsITimedChannel* aChannel); + + nsString mNextHopProtocol; + + TimeStamp mAsyncOpen; + TimeStamp mRedirectStart; + TimeStamp mRedirectEnd; + TimeStamp mDomainLookupStart; + TimeStamp mDomainLookupEnd; + TimeStamp mConnectStart; + TimeStamp mSecureConnectionStart; + TimeStamp mConnectEnd; + TimeStamp mRequestStart; + TimeStamp mResponseStart; + TimeStamp mCacheReadStart; + TimeStamp mResponseEnd; + TimeStamp mCacheReadEnd; + + // ServiceWorker interception timing information + TimeStamp mWorkerStart; + TimeStamp mWorkerRequestStart; + TimeStamp mWorkerResponseEnd; + + // This is an offset that will be added to each timing ([ms] resolution). + // There are only 2 possible values: (1) logicaly equal to navigationStart + // TimeStamp (results are absolute timstamps - wallclock); (2) "0" (results + // are relative to the navigation start). + DOMHighResTimeStamp mZeroTime; + + DOMHighResTimeStamp mFetchStart; + + uint64_t mEncodedBodySize; + uint64_t mTransferSize; + uint64_t mDecodedBodySize; + + uint8_t mRedirectCount; + + bool mAllRedirectsSameOrigin; + + // If the resourceTiming object should have non-zero redirectStart and + // redirectEnd attributes. It is false if there were no redirects, or if any + // of the responses didn't pass the timing-allow-check + bool mReportCrossOriginRedirect; + + bool mSecureConnection; + + bool mTimingAllowed; + + bool mInitialized; + +}; + +// Script "performance.timing" object +class PerformanceTiming final : public nsWrapperCache +{ +public: +/** + * @param aPerformance + * The performance object (the JS parent). + * This will allow access to "window.performance.timing" attribute for + * the navigation timing (can't be null). + * @param aChannel + * An nsITimedChannel used to gather all the networking timings by both + * the navigation timing and the resource timing (can't be null). + * @param aHttpChannel + * An nsIHttpChannel (the resource's http channel). + * This will be used by the resource timing cross-domain check + * algorithm. + * Argument is null for the navigation timing (navigation timing uses + * another algorithm for the cross-domain redirects). + * @param aZeroTime + * The offset that will be added to the timestamp of each event. This + * argument should be equal to performance.navigationStart for + * navigation timing and "0" for the resource timing. + */ + PerformanceTiming(Performance* aPerformance, + nsITimedChannel* aChannel, + nsIHttpChannel* aHttpChannel, + DOMHighResTimeStamp aZeroTime); + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(PerformanceTiming) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(PerformanceTiming) + + nsDOMNavigationTiming* GetDOMTiming() const + { + return mPerformance->GetDOMTiming(); + } + + Performance* GetParentObject() const + { + return mPerformance; + } + virtual JSObject* WrapObject(JSContext *cx, JS::Handle aGivenProto) override; @@ -138,40 +274,6 @@ public: return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetUnloadEventEnd()); } - uint8_t GetRedirectCount() const; - - // Checks if the resource is either same origin as the page that started - // the load, or if the response contains the Timing-Allow-Origin header - // with a value of * or matching the domain of the loading Principal - bool CheckAllowedOrigin(nsIHttpChannel* aResourceChannel, nsITimedChannel* aChannel); - - // Cached result of CheckAllowedOrigin. If false, security sensitive - // attributes of the resourceTiming object will be set to 0 - bool TimingAllowed() const; - - // If this is false the values of redirectStart/End will be 0 - // This is false if no redirects occured, or if any of the responses failed - // the timing-allow-origin check in HttpBaseChannel::TimingAllowCheck - bool ShouldReportCrossOriginRedirect() const; - - // The last channel's AsyncOpen time. This may occur before the FetchStart - // in some cases. - DOMHighResTimeStamp AsyncOpenHighRes(); - - // High resolution (used by resource timing) - DOMHighResTimeStamp WorkerStartHighRes(); - DOMHighResTimeStamp FetchStartHighRes(); - DOMHighResTimeStamp RedirectStartHighRes(); - DOMHighResTimeStamp RedirectEndHighRes(); - DOMHighResTimeStamp DomainLookupStartHighRes(); - DOMHighResTimeStamp DomainLookupEndHighRes(); - DOMHighResTimeStamp ConnectStartHighRes(); - DOMHighResTimeStamp SecureConnectionStartHighRes(); - DOMHighResTimeStamp ConnectEndHighRes(); - DOMHighResTimeStamp RequestStartHighRes(); - DOMHighResTimeStamp ResponseStartHighRes(); - DOMHighResTimeStamp ResponseEndHighRes(); - // Low resolution (used by navigation timing) DOMTimeMilliSec FetchStart(); DOMTimeMilliSec RedirectStart(); @@ -249,46 +351,16 @@ public: return TimerClamping::ReduceMsTimeValue(GetDOMTiming()->GetTimeToNonBlankPaint()); } + PerformanceTimingData* Data() const + { + return mTimingData.get(); + } + private: ~PerformanceTiming(); - bool IsInitialized() const; - void InitializeTimingInfo(nsITimedChannel* aChannel); - RefPtr mPerformance; - DOMHighResTimeStamp mFetchStart; - - // This is an offset that will be added to each timing ([ms] resolution). - // There are only 2 possible values: (1) logicaly equal to navigationStart - // TimeStamp (results are absolute timstamps - wallclock); (2) "0" (results - // are relative to the navigation start). - DOMHighResTimeStamp mZeroTime; - - TimeStamp mAsyncOpen; - TimeStamp mWorkerStart; - TimeStamp mRedirectStart; - TimeStamp mRedirectEnd; - TimeStamp mDomainLookupStart; - TimeStamp mDomainLookupEnd; - TimeStamp mConnectStart; - TimeStamp mSecureConnectionStart; - TimeStamp mConnectEnd; - TimeStamp mRequestStart; - TimeStamp mResponseStart; - TimeStamp mCacheReadStart; - TimeStamp mResponseEnd; - TimeStamp mCacheReadEnd; - uint8_t mRedirectCount; - bool mTimingAllowed; - bool mAllRedirectsSameOrigin; - bool mInitialized; - - // If the resourceTiming object should have non-zero redirectStart and - // redirectEnd attributes. It is false if there were no redirects, or if - // any of the responses didn't pass the timing-allow-check - bool mReportCrossOriginRedirect; - - bool mSecureConnection; + UniquePtr mTimingData; }; } // namespace dom diff --git a/dom/performance/PerformanceWorker.h b/dom/performance/PerformanceWorker.h index 3604e6874f..cdd3a521dd 100644 --- a/dom/performance/PerformanceWorker.h +++ b/dom/performance/PerformanceWorker.h @@ -62,6 +62,11 @@ public: return nullptr; } + void QueueNavigationTimingEntry() override + { + MOZ_CRASH("This should not be called on workers."); + } + protected: ~PerformanceWorker(); diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 879f47b206..a3577fdd12 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -1070,6 +1070,11 @@ nsDocumentViewer::LoadComplete(nsresult aStatus) if (timing) { timing->NotifyLoadEventEnd(); } + + nsPIDOMWindowInner* innerWindow = window->GetCurrentInnerWindow(); + if (innerWindow) { + innerWindow->QueuePerformanceNavigationTiming(); + } } } else { // XXX: Should fire error event to the document... -- cgit v1.2.3 From ccbeea30aa96570af9038ac3af792e99ed6c6ce6 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Fri, 20 Oct 2023 05:00:04 -0500 Subject: Issue #2282 - Part 2 - Re-add some timer clamping that got clobber erroneously. --- dom/performance/PerformanceNavigationTiming.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/dom/performance/PerformanceNavigationTiming.cpp b/dom/performance/PerformanceNavigationTiming.cpp index 1c4a30b569..8696a5bcfa 100644 --- a/dom/performance/PerformanceNavigationTiming.cpp +++ b/dom/performance/PerformanceNavigationTiming.cpp @@ -24,49 +24,49 @@ PerformanceNavigationTiming::WrapObject(JSContext* aCx, JS::Handle aG DOMHighResTimeStamp PerformanceNavigationTiming::UnloadEventStart() const { - return mPerformance->GetDOMTiming()->GetUnloadEventStartHighRes(); + return TimerClamping::ReduceMsTimeValue(mPerformance->GetDOMTiming()->GetUnloadEventStartHighRes()); } DOMHighResTimeStamp PerformanceNavigationTiming::UnloadEventEnd() const { - return mPerformance->GetDOMTiming()->GetUnloadEventEndHighRes(); + return TimerClamping::ReduceMsTimeValue(mPerformance->GetDOMTiming()->GetUnloadEventEndHighRes()); } DOMHighResTimeStamp PerformanceNavigationTiming::DomInteractive() const { - return mPerformance->GetDOMTiming()->GetDomInteractiveHighRes(); + return TimerClamping::ReduceMsTimeValue(mPerformance->GetDOMTiming()->GetDomInteractiveHighRes()); } DOMHighResTimeStamp PerformanceNavigationTiming::DomContentLoadedEventStart() const { - return mPerformance->GetDOMTiming()->GetDomContentLoadedEventStartHighRes(); + return TimerClamping::ReduceMsTimeValue(mPerformance->GetDOMTiming()->GetDomContentLoadedEventStartHighRes()); } DOMHighResTimeStamp PerformanceNavigationTiming::DomContentLoadedEventEnd() const { - return mPerformance->GetDOMTiming()->GetDomContentLoadedEventEndHighRes(); + return TimerClamping::ReduceMsTimeValue(mPerformance->GetDOMTiming()->GetDomContentLoadedEventEndHighRes()); } DOMHighResTimeStamp PerformanceNavigationTiming::DomComplete() const { - return mPerformance->GetDOMTiming()->GetDomCompleteHighRes(); + return TimerClamping::ReduceMsTimeValue(mPerformance->GetDOMTiming()->GetDomCompleteHighRes()); } DOMHighResTimeStamp PerformanceNavigationTiming::LoadEventStart() const { - return mPerformance->GetDOMTiming()->GetLoadEventStartHighRes(); + return TimerClamping::ReduceMsTimeValue(mPerformance->GetDOMTiming()->GetLoadEventStartHighRes()); } DOMHighResTimeStamp PerformanceNavigationTiming::LoadEventEnd() const { - return mPerformance->GetDOMTiming()->GetLoadEventEndHighRes(); + return TimerClamping::ReduceMsTimeValue(mPerformance->GetDOMTiming()->GetLoadEventEndHighRes()); } NavigationType -- cgit v1.2.3 From d5231ca7e78bf66a06133c2aa651d6e24306442a Mon Sep 17 00:00:00 2001 From: Moonchild Date: Sat, 21 Oct 2023 17:06:43 +0200 Subject: Issue #2346 - Follow-up: restore erroneously removed GMP mCrashHelper. --- dom/media/MediaFormatReader.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dom/media/MediaFormatReader.h b/dom/media/MediaFormatReader.h index 60ee022264..4a987c162d 100644 --- a/dom/media/MediaFormatReader.h +++ b/dom/media/MediaFormatReader.h @@ -577,6 +577,10 @@ private: RefPtr mVideoFrameContainer; layers::ImageContainer* GetImageContainer(); +#ifdef MOZ_GMP + RefPtr mCrashHelper; +#endif + void SetBlankDecode(TrackType aTrack, bool aIsBlankDecode); class DecoderFactory; -- cgit v1.2.3 From 6df4c1874704597159f84e7a8cedca6157f25ef8 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Sun, 22 Oct 2023 09:33:22 +0200 Subject: Issue #2355 - Apply self-transforms to the frame of top level We previously didn't do this because we relied on our anonymous wrapper to perform transforms. However, that resulted in only the children transforming, and the frame's cliprect wouldn't be updated, giving the impression of the z-ordering being wrong. Also adds reftests from the relevant BZ bug found later. Resolves #2355 --- layout/reftests/svg/fragmentIdentifier-01.xhtml | 21 ++++++++++------- layout/reftests/svg/reftest.list | 1 + layout/reftests/svg/svg-integration/reftest.list | 2 ++ .../transform-outer-svg-01-ref.xhtml | 18 +++++++++++++++ .../svg-integration/transform-outer-svg-01.xhtml | 18 +++++++++++++++ layout/reftests/svg/transform-outer-svg-01-ref.svg | 9 ++++++++ layout/reftests/svg/transform-outer-svg-01.svg | 10 +++++++++ layout/svg/nsSVGOuterSVGFrame.cpp | 26 ++++++++++++++++++++++ layout/svg/nsSVGOuterSVGFrame.h | 10 +++------ 9 files changed, 100 insertions(+), 15 deletions(-) create mode 100644 layout/reftests/svg/svg-integration/transform-outer-svg-01-ref.xhtml create mode 100644 layout/reftests/svg/svg-integration/transform-outer-svg-01.xhtml create mode 100644 layout/reftests/svg/transform-outer-svg-01-ref.svg create mode 100644 layout/reftests/svg/transform-outer-svg-01.svg diff --git a/layout/reftests/svg/fragmentIdentifier-01.xhtml b/layout/reftests/svg/fragmentIdentifier-01.xhtml index 9173f62fd5..a071bc2d6a 100644 --- a/layout/reftests/svg/fragmentIdentifier-01.xhtml +++ b/layout/reftests/svg/fragmentIdentifier-01.xhtml @@ -1,22 +1,27 @@ Testcases for SVG fragment identifiers +
    - - - +