Bug 1208371 - Make HTMLMediaElement::CaptureStream pass its principal to MediaStreamTrack. r?mt
MozReview-Commit-ID: 7ERLRSM8fz6
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1859,33 +1859,118 @@ NS_IMETHODIMP HTMLMediaElement::SetMuted
} else {
SetMutedInternal(mMuted & ~MUTED_BY_CONTENT);
}
DispatchAsyncEvent(NS_LITERAL_STRING("volumechange"));
return NS_OK;
}
+class HTMLMediaElement::CaptureStreamTrackSource :
+ public MediaStreamTrackSource,
+ public DecoderPrincipalChangeObserver
+{
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CaptureStreamTrackSource,
+ MediaStreamTrackSource)
+
+ explicit CaptureStreamTrackSource(HTMLMediaElement* aElement)
+ : MediaStreamTrackSource(nsCOMPtr<nsIPrincipal>(aElement->GetCurrentPrincipal()), true)
+ , mElement(aElement)
+ {
+ MOZ_ASSERT(mElement);
+ mElement->AddDecoderPrincipalChangeObserver(this);
+ }
+
+ MediaSourceEnum GetMediaSource() const override
+ {
+ return MediaSourceEnum::Other;
+ }
+
+ void Stop() override
+ {
+ NS_ERROR("We're reporting remote=true to not be stoppable. "
+ "Stop() should not be called.");
+ }
+
+ void NotifyDecoderPrincipalChanged() override
+ {
+ nsCOMPtr<nsIPrincipal> newPrincipal = mElement->GetCurrentPrincipal();
+ if (nsContentUtils::CombineResourcePrincipals(&mPrincipal, newPrincipal)) {
+ PrincipalChanged();
+ }
+ }
+
+protected:
+ virtual ~CaptureStreamTrackSource()
+ {
+ if (mElement) {
+ DebugOnly<bool> res = mElement->RemoveDecoderPrincipalChangeObserver(this);
+ NS_ASSERTION(res, "Removing decoder principal changed observer failed. "
+ "Had it already been removed?");
+ }
+ }
+
+ RefPtr<HTMLMediaElement> mElement;
+};
+
+NS_IMPL_ADDREF_INHERITED(HTMLMediaElement::CaptureStreamTrackSource,
+ MediaStreamTrackSource)
+NS_IMPL_RELEASE_INHERITED(HTMLMediaElement::CaptureStreamTrackSource,
+ MediaStreamTrackSource)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLMediaElement::CaptureStreamTrackSource)
+NS_INTERFACE_MAP_END_INHERITING(MediaStreamTrackSource)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLMediaElement::CaptureStreamTrackSource,
+ MediaStreamTrackSource,
+ mElement)
+
+class HTMLMediaElement::CaptureStreamTrackSourceGetter :
+ public MediaStreamTrackSourceGetter
+{
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CaptureStreamTrackSourceGetter,
+ MediaStreamTrackSourceGetter)
+
+ explicit CaptureStreamTrackSourceGetter(HTMLMediaElement* aElement)
+ : mElement(aElement) {}
+
+ already_AddRefed<dom::MediaStreamTrackSource>
+ GetMediaStreamTrackSource(TrackID aInputTrackID) override
+ {
+ // We can return a new source each time here, even for different streams,
+ // since the sources don't keep any internal state and all of them call
+ // through to the same HTMLMediaElement.
+ // If this changes (after implementing Stop()?) we'll have to ensure we
+ // return the same source for all requests to the same TrackID, and only
+ // have one getter.
+ return do_AddRef(new CaptureStreamTrackSource(mElement));
+ }
+
+protected:
+ virtual ~CaptureStreamTrackSourceGetter() {}
+
+ RefPtr<HTMLMediaElement> mElement;
+};
+
+NS_IMPL_ADDREF_INHERITED(HTMLMediaElement::CaptureStreamTrackSourceGetter,
+ MediaStreamTrackSourceGetter)
+NS_IMPL_RELEASE_INHERITED(HTMLMediaElement::CaptureStreamTrackSourceGetter,
+ MediaStreamTrackSourceGetter)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLMediaElement::CaptureStreamTrackSourceGetter)
+NS_INTERFACE_MAP_END_INHERITING(MediaStreamTrackSourceGetter)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLMediaElement::CaptureStreamTrackSourceGetter,
+ MediaStreamTrackSourceGetter,
+ mElement)
+
already_AddRefed<DOMMediaStream>
HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded,
MediaStreamGraph* aGraph)
{
- class CaptureStreamTrackSourceGetter : public MediaStreamTrackSourceGetter
- {
- public:
- already_AddRefed<dom::MediaStreamTrackSource>
- GetMediaStreamTrackSource(TrackID aInputTrackID) override
- {
- return do_AddRef(new BasicUnstoppableTrackSource());
- }
-
- protected:
- virtual ~CaptureStreamTrackSourceGetter() {}
- };
-
nsPIDOMWindowInner* window = OwnerDoc()->GetInnerWindow();
if (!window) {
return nullptr;
}
#ifdef MOZ_EME
if (ContainsRestrictedContent()) {
return nullptr;
}
@@ -1899,38 +1984,38 @@ HTMLMediaElement::CaptureStreamInternal(
}
if (!mOutputStreams.IsEmpty() &&
aGraph != mOutputStreams[0].mStream->GetInputStream()->Graph()) {
return nullptr;
}
OutputMediaStream* out = mOutputStreams.AppendElement();
- MediaStreamTrackSourceGetter* getter = new CaptureStreamTrackSourceGetter();
+ MediaStreamTrackSourceGetter* getter = new CaptureStreamTrackSourceGetter(this);
out->mStream = DOMMediaStream::CreateTrackUnionStream(window, aGraph, getter);
- RefPtr<nsIPrincipal> principal = GetCurrentPrincipal();
- out->mStream->CombineWithPrincipal(principal);
out->mStream->SetCORSMode(mCORSMode);
out->mFinishWhenEnded = aFinishWhenEnded;
mAudioCaptured = true;
if (mDecoder) {
mDecoder->AddOutputStream(out->mStream->GetInputStream()->AsProcessedStream(),
aFinishWhenEnded);
if (mReadyState >= HAVE_METADATA) {
// Expose the tracks to JS directly.
if (HasAudio()) {
TrackID audioTrackId = mMediaInfo.mAudio.mTrackId;
- RefPtr<MediaStreamTrackSource> trackSource = new BasicUnstoppableTrackSource();
+ RefPtr<MediaStreamTrackSource> trackSource =
+ getter->GetMediaStreamTrackSource(audioTrackId);
out->mStream->CreateOwnDOMTrack(audioTrackId, MediaSegment::AUDIO,
nsString(), trackSource);
}
if (HasVideo()) {
TrackID videoTrackId = mMediaInfo.mVideo.mTrackId;
- RefPtr<MediaStreamTrackSource> trackSource = new BasicUnstoppableTrackSource();
+ RefPtr<MediaStreamTrackSource> trackSource =
+ getter->GetMediaStreamTrackSource(videoTrackId);
out->mStream->CreateOwnDOMTrack(videoTrackId, MediaSegment::VIDEO,
nsString(), trackSource);
}
}
}
RefPtr<DOMMediaStream> result = out->mStream;
return result.forget();
}
@@ -4177,20 +4262,18 @@ already_AddRefed<nsIPrincipal> HTMLMedia
}
void HTMLMediaElement::NotifyDecoderPrincipalChanged()
{
RefPtr<nsIPrincipal> principal = GetCurrentPrincipal();
mDecoder->UpdateSameOriginStatus(!principal || IsCORSSameOrigin());
- for (uint32_t i = 0; i < mOutputStreams.Length(); ++i) {
- OutputMediaStream* ms = &mOutputStreams[i];
- ms->mStream->SetCORSMode(mCORSMode);
- ms->mStream->CombineWithPrincipal(principal);
+ for (OutputMediaStream& ms : mOutputStreams) {
+ ms.mStream->SetCORSMode(mCORSMode);
}
for (DecoderPrincipalChangeObserver* observer :
mDecoderPrincipalChangeObservers) {
observer->NotifyDecoderPrincipalChanged();
}
}
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -285,16 +285,19 @@ public:
/**
* Remove an added DecoderPrincipalChangeObserver from this media element.
*
* Returns true if it was successfully removed.
*/
bool RemoveDecoderPrincipalChangeObserver(DecoderPrincipalChangeObserver* aObserver);
+ class CaptureStreamTrackSource;
+ class CaptureStreamTrackSourceGetter;
+
// Update the visual size of the media. Called from the decoder on the
// main thread when/if the size changes.
void UpdateMediaSize(const nsIntSize& aSize);
// Like UpdateMediaSize, but only updates the size if no size has yet
// been set.
void UpdateInitialMediaSize(const nsIntSize& aSize);
// Returns the CanPlayStatus indicating if we can handle the
--- a/dom/media/DOMMediaStream.h
+++ b/dom/media/DOMMediaStream.h
@@ -205,16 +205,17 @@ protected:
* \ (pointing to t1 in A')
* ----> t2 ------------> t2 <- MediaStreamTrack Z'
* (pointing to t2 in A')
*/
class DOMMediaStream : public DOMEventTargetHelper,
public dom::PrincipalChangeObserver<dom::MediaStreamTrack>
{
friend class DOMLocalMediaStream;
+ friend class dom::MediaStreamTrack;
typedef dom::MediaStreamTrack MediaStreamTrack;
typedef dom::AudioStreamTrack AudioStreamTrack;
typedef dom::VideoStreamTrack VideoStreamTrack;
typedef dom::MediaStreamTrackSource MediaStreamTrackSource;
typedef dom::AudioTrack AudioTrack;
typedef dom::VideoTrack VideoTrack;
typedef dom::AudioTrackList AudioTrackList;
typedef dom::VideoTrackList VideoTrackList;