Bug 1208371 - Make PeerConnectionImpl pass its principal to MediaStreamTrack through a new RemoteTrackSource. r?mt draft
authorAndreas Pehrson <pehrsons@gmail.com>
Thu, 14 Jan 2016 21:07:12 +0800
changeset 342110 cb01ba3ab18e534eb09d75415c117b1b8961caed
parent 342109 d82b0d2f9bec7f922a48fd7634d3816ead72f471
child 342111 0b0cb201417390dcddc9b63b8407a3e9d89ca7c3
push id13352
push userpehrsons@gmail.com
push dateFri, 18 Mar 2016 13:49:47 +0000
reviewersmt
bugs1208371
milestone47.0a1
Bug 1208371 - Make PeerConnectionImpl pass its principal to MediaStreamTrack through a new RemoteTrackSource. r?mt MozReview-Commit-ID: BxjQCHnmbDd
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -490,33 +490,16 @@ already_AddRefed<DOMMediaStream>
 PeerConnectionImpl::MakeMediaStream()
 {
   MediaStreamGraph* graph =
     MediaStreamGraph::GetInstance(MediaStreamGraph::AUDIO_THREAD_DRIVER,
                                   AudioChannel::Normal);
 
   RefPtr<DOMMediaStream> stream =
     DOMMediaStream::CreateSourceStream(GetWindow(), graph);
-#if !defined(MOZILLA_EXTERNAL_LINKAGE)
-  // Make the stream data (audio/video samples) accessible to the receiving page.
-  // We're only certain that privacy hasn't been requested if we're connected.
-  if (mDtlsConnected && !PrivacyRequested()) {
-    nsIDocument* doc = GetWindow()->GetExtantDoc();
-    if (!doc) {
-      return nullptr;
-    }
-    stream->CombineWithPrincipal(doc->NodePrincipal());
-  } else {
-    // we're either certain that we need isolation for the streams, OR
-    // we're not sure and we can fix the stream in SetDtlsConnected
-    nsCOMPtr<nsIPrincipal> principal =
-      do_CreateInstance(NS_NULLPRINCIPAL_CONTRACTID);
-    stream->CombineWithPrincipal(principal);
-  }
-#endif
 
   CSFLogDebug(logTag, "Created media stream %p, inner: %p", stream.get(), stream->GetInputStream());
 
   return stream.forget();
 }
 
 nsresult
 PeerConnectionImpl::CreateRemoteSourceStreamInfo(RefPtr<RemoteSourceStreamInfo>*
@@ -1790,39 +1773,63 @@ PeerConnectionImpl::CreateNewRemoteTrack
       info->GetMediaStream()->AssignId((streamId));
 #endif
     }
 
     size_t numNewAudioTracks = 0;
     size_t numNewVideoTracks = 0;
     size_t numPreexistingTrackIds = 0;
 
+#if !defined(MOZILLA_EXTERNAL_LINKAGE)
+      // Set the principal used for creating the tracks. This makes the stream
+      // data (audio/video samples) accessible to the receiving page. We're
+      // only certain that privacy hasn't been requested if we're connected.
+      nsCOMPtr<nsIPrincipal> principal;
+      if (mDtlsConnected && !PrivacyRequested()) {
+        nsIDocument* doc = GetWindow()->GetExtantDoc();
+        MOZ_ASSERT(doc);
+        if (doc) {
+          principal = doc->NodePrincipal();
+        }
+      } else {
+        // we're either certain that we need isolation for the streams, OR
+        // we're not sure and we can fix the stream in SetDtlsConnected
+        principal = do_CreateInstance(NS_NULLPRINCIPAL_CONTRACTID);
+      }
+#endif
+
     for (auto j = tracks.begin(); j != tracks.end(); ++j) {
       RefPtr<JsepTrack> track = *j;
       if (!info->HasTrack(track->GetTrackId())) {
         if (track->GetMediaType() == SdpMediaSection::kAudio) {
           ++numNewAudioTracks;
         } else if (track->GetMediaType() == SdpMediaSection::kVideo) {
           ++numNewVideoTracks;
         } else {
           MOZ_ASSERT(false);
           continue;
         }
         info->AddTrack(track->GetTrackId());
 #if !defined(MOZILLA_EXTERNAL_LINKAGE)
-        RefPtr<MediaStreamTrackSource> source =
-          new BasicUnstoppableTrackSource(MediaSourceEnum::Other);
+        RefPtr<RemoteTrackSource> source = new RemoteTrackSource(principal);
+        DebugOnly<bool> sourceSet =
+          info->SetTrackSource(track->GetTrackId(), source);
+        NS_ASSERTION(sourceSet, "TrackSource was added in the wrong order. "
+                                "Did someone add a track from elsewhere?");
+        TrackID trackID = info->GetNumericTrackId(track->GetTrackId());
         if (track->GetMediaType() == SdpMediaSection::kAudio) {
-          info->GetMediaStream()->CreateOwnDOMTrack(
-            info->GetNumericTrackId(track->GetTrackId()),
-            MediaSegment::AUDIO, nsString(), source);
+          info->GetMediaStream()->CreateOwnDOMTrack(trackID,
+                                                    MediaSegment::AUDIO,
+                                                    nsString(),
+                                                    source);
         } else {
-          info->GetMediaStream()->CreateOwnDOMTrack(
-            info->GetNumericTrackId(track->GetTrackId()),
-            MediaSegment::VIDEO, nsString(), source);
+          info->GetMediaStream()->CreateOwnDOMTrack(trackID,
+                                                    MediaSegment::VIDEO,
+                                                    nsString(),
+                                                    source);
         }
 #endif
         CSFLogDebug(logTag, "Added remote track %s/%s",
                     info->GetId().c_str(), track->GetTrackId().c_str());
       } else {
         ++numPreexistingTrackIds;
       }
     }
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
@@ -1216,20 +1216,23 @@ LocalSourceStreamInfo::UpdateSinkIdentit
     MediaPipelineTransmit* pipeline =
       static_cast<MediaPipelineTransmit*>((*it).second.get());
     pipeline->UpdateSinkIdentity_m(aPrincipal, aSinkIdentity);
   }
 }
 
 void RemoteSourceStreamInfo::UpdatePrincipal_m(nsIPrincipal* aPrincipal)
 {
-  // this blasts away the existing principal
-  // we only do this when we become certain that the stream is safe to make
-  // accessible to the script principal
-  mMediaStream->SetPrincipal(aPrincipal);
+  // This blasts away the existing principal.
+  // We only do this when we become certain that the all tracks are safe to make
+  // accessible to the script principal.
+  for (RefPtr<RemoteTrackSource>& source : mTrackSources) {
+    MOZ_RELEASE_ASSERT(source);
+    source->SetPrincipal(aPrincipal);
+  }
 }
 #endif // MOZILLA_INTERNAL_API
 
 bool
 PeerConnectionMedia::AnyCodecHasPluginID(uint64_t aPluginID)
 {
   for (uint32_t i=0; i < mLocalSourceStreams.Length(); ++i) {
     if (mLocalSourceStreams[i]->AnyCodecHasPluginID(aPluginID)) {
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h
@@ -141,31 +141,68 @@ public:
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(LocalSourceStreamInfo)
 
 private:
   already_AddRefed<MediaPipeline> ForgetPipelineByTrackId_m(
       const std::string& trackId);
 };
 
+#if !defined(MOZILLA_EXTERNAL_LINKAGE)
+class RemoteTrackSource : public dom::MediaStreamTrackSource
+{
+public:
+  explicit RemoteTrackSource(nsIPrincipal* aPrincipal)
+    : dom::MediaStreamTrackSource(aPrincipal, true) {}
+
+  dom::MediaSourceEnum GetMediaSource() const override
+  {
+    return dom::MediaSourceEnum::Other;
+  }
+
+  void Stop() override { NS_ERROR("Can't stop a remote source!"); }
+
+  void SetPrincipal(nsIPrincipal* aPrincipal)
+  {
+    mPrincipal = aPrincipal;
+    PrincipalChanged();
+  }
+
+protected:
+  virtual ~RemoteTrackSource() {}
+};
+#endif
+
 class RemoteSourceStreamInfo : public SourceStreamInfo {
   ~RemoteSourceStreamInfo() {}
  public:
   RemoteSourceStreamInfo(already_AddRefed<DOMMediaStream> aMediaStream,
                          PeerConnectionMedia *aParent,
                          const std::string& aId)
     : SourceStreamInfo(aMediaStream, aParent, aId),
       mReceiving(false)
   {
   }
 
   void SyncPipeline(RefPtr<MediaPipelineReceive> aPipeline);
 
 #if !defined(MOZILLA_EXTERNAL_LINKAGE)
   void UpdatePrincipal_m(nsIPrincipal* aPrincipal);
+
+  // Track sources may only be set in the same order as tracks were added.
+  // Returns true if the source was added, false otherwise.
+  bool SetTrackSource(const std::string& track, RemoteTrackSource* source)
+  {
+    size_t nextIndex = mTrackSources.size();
+    if (mTrackIdMap.size() < nextIndex || mTrackIdMap[nextIndex] != track) {
+      return false;
+    }
+    mTrackSources.push_back(source);
+    return true;
+  }
 #endif
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteSourceStreamInfo)
 
   virtual void AddTrack(const std::string& track) override
   {
     mTrackIdMap.push_back(track);
     SourceStreamInfo::AddTrack(track);
@@ -208,16 +245,22 @@ class RemoteSourceStreamInfo : public So
   // numeric track id before creation of the MediaStreamTrack, and does not
   // allow us to specify a string-based id until later. We cannot simply use
   // something based on mline index, since renegotiation can move tracks
   // around. Hopefully someday we'll be able to specify the string id up-front,
   // and have the numeric track id selected for us, in which case this variable
   // and its dependencies can go away.
   std::vector<std::string> mTrackIdMap;
 
+#if !defined(MOZILLA_EXTERNAL_LINKAGE)
+  // MediaStreamTrackSources associated with this remote stream.
+  // We use them for updating their principal if that's needed.
+  std::vector<RefPtr<RemoteTrackSource>> mTrackSources;
+#endif
+
   // True iff SetPullEnabled(true) has been called on the DOMMediaStream. This
   // happens when offer/answer concludes.
   bool mReceiving;
 };
 
 class PeerConnectionMedia : public sigslot::has_slots<> {
   ~PeerConnectionMedia()
   {