Bug 1208371 - Create MediaStreamTrackSource::Sink that forwards principal changes from the source. r?mt draft
authorAndreas Pehrson <pehrsons@gmail.com>
Fri, 22 Jan 2016 12:28:57 +0800
changeset 342103 8ec82eaa53bdd005501373f6437f9ee3517a3fd6
parent 342102 e46aaf05cbd9a03fa2616ec13403d2e9407134e2
child 342104 f30344e8e9586c921de08c627950534d24404651
push id13352
push userpehrsons@gmail.com
push dateFri, 18 Mar 2016 13:49:47 +0000
reviewersmt
bugs1208371
milestone47.0a1
Bug 1208371 - Create MediaStreamTrackSource::Sink that forwards principal changes from the source. r?mt MozReview-Commit-ID: 2jsQCC7MMRj
dom/media/MediaManager.cpp
dom/media/MediaStreamTrack.cpp
dom/media/MediaStreamTrack.h
--- 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.
    */