Bug 1208371 - Create MediaStreamTrackSource::Sink that forwards principal changes from the source. r?mt
MozReview-Commit-ID: 2jsQCC7MMRj
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -908,17 +908,17 @@ public:
window->SetAudioCapture(true);
} else {
class LocalTrackSource : public MediaStreamTrackSource
{
public:
LocalTrackSource(GetUserMediaCallbackMediaStreamListener* aListener,
const MediaSourceEnum aSource,
const TrackID aTrackID)
- : MediaStreamTrackSource(false), mListener(aListener),
+ : MediaStreamTrackSource(nullptr, false), mListener(aListener),
mSource(aSource), mTrackID(aTrackID) {}
MediaSourceEnum GetMediaSource() const override
{
return mSource;
}
void Stop() override
--- a/dom/media/MediaStreamTrack.cpp
+++ b/dom/media/MediaStreamTrack.cpp
@@ -19,32 +19,31 @@ static PRLogModuleInfo* gMediaStreamTrac
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaStreamTrackSource)
NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaStreamTrackSource)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaStreamTrackSource)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
-NS_IMPL_CYCLE_COLLECTION_0(MediaStreamTrackSource)
+NS_IMPL_CYCLE_COLLECTION(MediaStreamTrackSource, mPrincipal)
MediaStreamTrack::MediaStreamTrack(DOMMediaStream* aStream, TrackID aTrackID,
TrackID aInputTrackID, const nsString& aLabel,
MediaStreamTrackSource* aSource)
: mOwningStream(aStream), mTrackID(aTrackID),
mInputTrackID(aInputTrackID), mSource(aSource), mLabel(aLabel),
mEnded(false), mEnabled(true), mRemote(aSource->IsRemote()), mStopped(false)
{
if (!gMediaStreamTrackLog) {
gMediaStreamTrackLog = PR_NewLogModule("MediaStreamTrack");
}
- MOZ_RELEASE_ASSERT(mSource);
- mSource->RegisterSink();
+ GetSource().RegisterSink(this);
nsresult rv;
nsCOMPtr<nsIUUIDGenerator> uuidgen =
do_GetService("@mozilla.org/uuid-generator;1", &rv);
nsID uuid;
memset(&uuid, 0, sizeof(uuid));
if (uuidgen) {
@@ -60,17 +59,19 @@ MediaStreamTrack::~MediaStreamTrack()
{
}
NS_IMPL_CYCLE_COLLECTION_CLASS(MediaStreamTrack)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaStreamTrack,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwningStream)
- tmp->mSource->UnregisterSink();
+ if (tmp->mSource) {
+ tmp->mSource->UnregisterSink(tmp);
+ }
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSource)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOriginalTrack)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaStreamTrack,
DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwningStream)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSource)
@@ -114,17 +115,17 @@ MediaStreamTrack::Stop()
return;
}
if (!mSource) {
MOZ_ASSERT(false);
return;
}
- mSource->UnregisterSink();
+ mSource->UnregisterSink(this);
mStopped = true;
}
already_AddRefed<Promise>
MediaStreamTrack::ApplyConstraints(const MediaTrackConstraints& aConstraints,
ErrorResult &aRv)
{
if (MOZ_LOG_TEST(gMediaStreamTrackLog, LogLevel::Info)) {
@@ -139,16 +140,25 @@ MediaStreamTrack::ApplyConstraints(const
}
MediaStreamGraph*
MediaStreamTrack::Graph()
{
return GetOwnedStream()->Graph();
}
+void
+MediaStreamTrack::PrincipalChanged()
+{
+ for (PrincipalChangeObserver<MediaStreamTrack>* observer
+ : mPrincipalChangeObservers) {
+ observer->PrincipalChanged(this);
+ }
+}
+
bool
MediaStreamTrack::AddPrincipalChangeObserver(
PrincipalChangeObserver<MediaStreamTrack>* aObserver)
{
return mPrincipalChangeObservers.AppendElement(aObserver) != nullptr;
}
bool
--- a/dom/media/MediaStreamTrack.h
+++ b/dom/media/MediaStreamTrack.h
@@ -34,28 +34,41 @@ class VideoStreamTrack;
* sharing this source.
*/
class MediaStreamTrackSource : public nsISupports
{
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(MediaStreamTrackSource)
public:
- explicit MediaStreamTrackSource(const bool aIsRemote)
- : mNrSinks(0), mIsRemote(aIsRemote), mStopped(false)
+ class Sink
+ {
+ public:
+ virtual void PrincipalChanged() = 0;
+ };
+
+ MediaStreamTrackSource(nsIPrincipal* aPrincipal, const bool aIsRemote)
+ : mPrincipal(aPrincipal),
+ mIsRemote(aIsRemote),
+ mStopped(false)
{
MOZ_COUNT_CTOR(MediaStreamTrackSource);
}
/**
* Gets the source's MediaSourceEnum for usage by PeerConnections.
*/
virtual MediaSourceEnum GetMediaSource() const = 0;
/**
+ * Get this TrackSource's principal.
+ */
+ nsIPrincipal* GetPrincipal() const { return mPrincipal; }
+
+ /**
* Indicates whether the track is remote or not per the MediaCapture and
* Streams spec.
*/
virtual bool IsRemote() const { return mIsRemote; }
/**
* Forwards a photo request to backends that support it. Other backends return
* NS_ERROR_NOT_IMPLEMENTED to indicate that a MediaStreamGraph-based fallback
@@ -66,48 +79,60 @@ public:
/**
* Called by the source interface when all registered sinks have unregistered.
*/
virtual void Stop() = 0;
/**
* Called by each MediaStreamTrack clone on initialization.
*/
- void RegisterSink()
+ void RegisterSink(Sink* aSink)
{
MOZ_ASSERT(NS_IsMainThread());
if (mStopped) {
return;
}
- ++mNrSinks;
+ mSinks.AppendElement(aSink);
}
/**
- * Called by each MediaStreamTrack clone on track.Stop().
+ * Called by each MediaStreamTrack clone on Stop() if supported by the
+ * source (us) or destruction.
*/
- void UnregisterSink()
+ void UnregisterSink(Sink* aSink)
{
MOZ_ASSERT(NS_IsMainThread());
- NS_ASSERTION(mNrSinks > 0, "Unmatched UnregisterSink()");
- --mNrSinks;
- if (mNrSinks == 0 && !IsRemote()) {
+ if (mSinks.RemoveElement(aSink) && mSinks.IsEmpty() && !IsRemote()) {
Stop();
mStopped = true;
}
}
protected:
virtual ~MediaStreamTrackSource()
{
MOZ_COUNT_DTOR(MediaStreamTrackSource);
- NS_ASSERTION(mNrSinks == 0, "Some sinks did not unregister");
}
- // Number of currently registered sinks.
- size_t mNrSinks;
+ /**
+ * Called by a sub class when the principal has changed.
+ * Notifies all sinks.
+ */
+ void PrincipalChanged()
+ {
+ for (Sink* sink : mSinks) {
+ sink->PrincipalChanged();
+ }
+ }
+
+ // Principal identifying who may access the contents of this source.
+ nsCOMPtr<nsIPrincipal> mPrincipal;
+
+ // Currently registered sinks.
+ nsTArray<Sink*> mSinks;
// True if this is a remote track source, i.e., a PeerConnection.
const bool mIsRemote;
// True if this source is not remote, all MediaStreamTrack users have
// unregistered from this source and Stop() has been called.
bool mStopped;
};
@@ -115,32 +140,34 @@ protected:
/**
* Basic implementation of MediaStreamTrackSource that ignores Stop().
*/
class BasicUnstoppableTrackSource : public MediaStreamTrackSource
{
public:
explicit BasicUnstoppableTrackSource(const MediaSourceEnum aMediaSource =
MediaSourceEnum::Other)
- : MediaStreamTrackSource(true), mMediaSource(aMediaSource) {}
+ : MediaStreamTrackSource(nullptr, true), mMediaSource(aMediaSource) {}
MediaSourceEnum GetMediaSource() const override { return mMediaSource; }
void Stop() override {}
protected:
~BasicUnstoppableTrackSource() {}
const MediaSourceEnum mMediaSource;
};
/**
* Class representing a track in a DOMMediaStream.
*/
-class MediaStreamTrack : public DOMEventTargetHelper {
+class MediaStreamTrack : public DOMEventTargetHelper,
+ public MediaStreamTrackSource::Sink
+{
public:
/**
* aTrackID is the MediaStreamGraph track ID for the track in the
* MediaStream owned by aStream.
*/
MediaStreamTrack(DOMMediaStream* aStream, TrackID aTrackID,
TrackID aInputTrackID, const nsString& aLabel,
MediaStreamTrackSource* aSource);
@@ -183,30 +210,33 @@ public:
bool Ended() const { return mEnded; }
// Notifications from the MediaStreamGraph
void NotifyEnded() { mEnded = true; }
/**
* Get this track's principal.
*/
- nsIPrincipal* GetPrincipal() const { return nullptr; }
+ nsIPrincipal* GetPrincipal() const { return GetSource().GetPrincipal(); }
MediaStreamGraph* Graph();
MediaStreamTrackSource& GetSource() const
{
MOZ_RELEASE_ASSERT(mSource, "The track source is only removed on destruction");
return *mSource;
}
// Webrtc allows the remote side to name tracks whatever it wants, and we
// need to surface this to content.
void AssignId(const nsAString& aID) { mID = aID; }
+ // Implementation of MediaStreamTrackSource::Sink
+ void PrincipalChanged() override;
+
/**
* Add a PrincipalChangeObserver to this track.
*
* Returns true if it was successfully added.
*
* Ownership of the PrincipalChangeObserver remains with the caller, and it's
* the caller's responsibility to remove the observer before it dies.
*/