Bug 1395017. P1 - dispatch a task to the main thread to update the principal when necessary. r=cpearce
☠☠ backed out by 0ce1edf053dc ☠ ☠
authorJW Wang <jwwang@mozilla.com>
Tue, 29 Aug 2017 17:57:00 +0800
changeset 428587 78625f947f691ea92380450d2b70a698b94fcf05
parent 428586 b502be79aeb198e3d701ad4f61836b08fd1452eb
child 428588 243ef641e6c33712c910225ed18af627a45a863a
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1395017
milestone57.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1395017. P1 - dispatch a task to the main thread to update the principal when necessary. r=cpearce MozReview-Commit-ID: BWyDmKglWsl
dom/media/MediaCache.cpp
dom/media/MediaCache.h
dom/media/MediaResource.cpp
dom/media/MediaResource.h
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -1871,33 +1871,30 @@ MediaCacheStream::NotifyDataStarted(int6
 
 bool
 MediaCacheStream::UpdatePrincipal(nsIPrincipal* aPrincipal)
 {
   return nsContentUtils::CombineResourcePrincipals(&mPrincipal, aPrincipal);
 }
 
 void
-MediaCacheStream::NotifyDataReceived(int64_t aSize, const char* aData,
-    nsIPrincipal* aPrincipal)
+MediaCacheStream::NotifyDataReceived(int64_t aSize, const char* aData)
 {
   // This might happen off the main thread.
   MOZ_DIAGNOSTIC_ASSERT(!mClosed);
 
   // Update principals before putting the data in the cache. This is important,
   // we want to make sure all principals are updated before any consumer
   // can see the new data.
   // We do this without holding the cache monitor, in case the client wants
   // to do something that takes a lock.
   {
     MediaCache::ResourceStreamIterator iter(mMediaCache, mResourceID);
     while (MediaCacheStream* stream = iter.Next()) {
-      if (stream->UpdatePrincipal(aPrincipal)) {
-        stream->mClient->CacheClientNotifyPrincipalChanged();
-      }
+      stream->mClient->CacheClientUpdatePrincipal();
     }
   }
 
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   int64_t size = aSize;
   const char* data = aData;
 
   LOG("Stream %p DataReceived at %" PRId64 " count=%" PRId64,
--- a/dom/media/MediaCache.h
+++ b/dom/media/MediaCache.h
@@ -256,18 +256,17 @@ public:
   // time by the client, not just after a CacheClientSeek.
   void NotifyDataStarted(int64_t aOffset);
   // Notifies the cache that data has been received. The stream already
   // knows the offset because data is received in sequence and
   // the starting offset is known via NotifyDataStarted or because
   // the cache requested the offset in
   // ChannelMediaResource::CacheClientSeek, or because it defaulted to 0.
   // We pass in the principal that was used to load this data.
-  void NotifyDataReceived(int64_t aSize, const char* aData,
-                          nsIPrincipal* aPrincipal);
+  void NotifyDataReceived(int64_t aSize, const char* aData);
   // Notifies the cache that the current bytes should be written to disk.
   // Called on the main thread.
   void FlushPartialBlock();
   // Notifies the cache that the channel has closed with the given status.
   void NotifyDataEnded(nsresult aStatus);
 
   // Notifies the stream that the channel is reopened. The stream should
   // reset variables such as |mDidNotifyDataEnded|.
@@ -343,16 +342,19 @@ public:
   // 'Read' for argument and return details.
   nsresult ReadAt(int64_t aOffset, char* aBuffer,
                   uint32_t aCount, uint32_t* aBytes);
 
   void ThrottleReadahead(bool bThrottle);
 
   size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const;
 
+  // Update mPrincipal given that data has been received from aPrincipal
+  bool UpdatePrincipal(nsIPrincipal* aPrincipal);
+
 private:
   friend class MediaCache;
 
   /**
    * A doubly-linked list of blocks. Add/Remove/Get methods are all
    * constant time. We declare this here so that a stream can contain a
    * BlockList of its read-ahead blocks. Blocks are referred to by index
    * into the MediaCache::mIndex array.
@@ -420,18 +422,16 @@ private:
   // This method assumes that the cache monitor is held and can be called on
   // any thread.
   int64_t GetNextCachedDataInternal(int64_t aOffset);
   // Writes |mPartialBlock| to disk.
   // Used by |NotifyDataEnded| and |FlushPartialBlock|.
   // If |aNotifyAll| is true, this function will wake up readers who may be
   // waiting on the media cache monitor. Called on the main thread only.
   void FlushPartialBlockInternal(bool aNotify, ReentrantMonitorAutoEnter& aReentrantMonitor);
-  // Update mPrincipal given that data has been received from aPrincipal
-  bool UpdatePrincipal(nsIPrincipal* aPrincipal);
 
   // Instance of MediaCache to use with this MediaCacheStream.
   RefPtr<MediaCache> mMediaCache;
 
   // These fields are main-thread-only.
   ChannelMediaResource*  mClient;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   // Set to true when MediaCache::Update() has finished while this stream
--- a/dom/media/MediaResource.cpp
+++ b/dom/media/MediaResource.cpp
@@ -451,74 +451,58 @@ ChannelMediaResource::OnChannelRedirect(
                                         uint32_t aFlags)
 {
   mChannel = aNew;
   mSuspendAgent.NotifyChannelOpened(mChannel);
   return SetupChannelHeaders();
 }
 
 nsresult
-ChannelMediaResource::CopySegmentToCache(nsIPrincipal* aPrincipal,
-                                         const char* aFromSegment,
+ChannelMediaResource::CopySegmentToCache(const char* aFromSegment,
                                          uint32_t aCount,
                                          uint32_t* aWriteCount)
 {
   // Keep track of where we're up to.
   LOG("CopySegmentToCache at mOffset [%" PRId64 "] add "
       "[%d] bytes for decoder[%p]",
       mOffset, aCount, mCallback.get());
   mOffset += aCount;
-  mCacheStream.NotifyDataReceived(aCount, aFromSegment, aPrincipal);
+  mCacheStream.NotifyDataReceived(aCount, aFromSegment);
   *aWriteCount = aCount;
   return NS_OK;
 }
 
-
-struct CopySegmentClosure {
-  nsCOMPtr<nsIPrincipal> mPrincipal;
-  ChannelMediaResource*  mResource;
-};
-
 nsresult
 ChannelMediaResource::CopySegmentToCache(nsIInputStream* aInStream,
-                                         void* aClosure,
+                                         void* aResource,
                                          const char* aFromSegment,
                                          uint32_t aToOffset,
                                          uint32_t aCount,
                                          uint32_t* aWriteCount)
 {
-  CopySegmentClosure* closure = static_cast<CopySegmentClosure*>(aClosure);
-  return closure->mResource->CopySegmentToCache(
-    closure->mPrincipal, aFromSegment, aCount, aWriteCount);
+  ChannelMediaResource* res = static_cast<ChannelMediaResource*>(aResource);
+  return res->CopySegmentToCache(aFromSegment, aCount, aWriteCount);
 }
 
 nsresult
 ChannelMediaResource::OnDataAvailable(nsIRequest* aRequest,
                                       nsIInputStream* aStream,
                                       uint32_t aCount)
 {
   NS_ASSERTION(mChannel.get() == aRequest, "Wrong channel!");
 
   {
     MutexAutoLock lock(mLock);
     mChannelStatistics.AddBytes(aCount);
   }
 
-  CopySegmentClosure closure;
-  nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
-  if (secMan && mChannel) {
-    secMan->GetChannelResultPrincipal(mChannel, getter_AddRefs(closure.mPrincipal));
-  }
-  closure.mResource = this;
-
   uint32_t count = aCount;
   while (count > 0) {
     uint32_t read;
-    nsresult rv = aStream->ReadSegments(CopySegmentToCache, &closure, count,
-                                        &read);
+    nsresult rv = aStream->ReadSegments(CopySegmentToCache, this, count, &read);
     if (NS_FAILED(rv))
       return rv;
     NS_ASSERTION(read > 0, "Read 0 bytes while data was available?");
     count -= read;
   }
 
   return NS_OK;
 }
@@ -632,17 +616,18 @@ nsresult ChannelMediaResource::Close()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   CloseChannel();
   mCacheStream.Close();
   return NS_OK;
 }
 
-already_AddRefed<nsIPrincipal> ChannelMediaResource::GetCurrentPrincipal()
+already_AddRefed<nsIPrincipal>
+ChannelMediaResource::GetCurrentPrincipal()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   nsCOMPtr<nsIPrincipal> principal = mCacheStream.GetCurrentPrincipal();
   return principal.forget();
 }
 
 bool ChannelMediaResource::CanClone()
@@ -883,21 +868,43 @@ ChannelMediaResource::CacheClientNotifyD
 void
 ChannelMediaResource::CacheClientNotifyDataEnded(nsresult aStatus)
 {
   MOZ_ASSERT(NS_IsMainThread());
   mCallback->NotifyDataEnded(aStatus);
 }
 
 void
-ChannelMediaResource::CacheClientNotifyPrincipalChanged()
+ChannelMediaResource::UpdatePrincipal()
 {
-  NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
+  MOZ_ASSERT(NS_IsMainThread());
+  nsCOMPtr<nsIPrincipal> principal;
+  nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
+  if (secMan && mChannel) {
+    secMan->GetChannelResultPrincipal(mChannel, getter_AddRefs(principal));
+  }
+  if (mCacheStream.UpdatePrincipal(principal)) {
+    mCallback->NotifyPrincipalChanged();
+  }
+}
 
-  mCallback->NotifyPrincipalChanged();
+void
+ChannelMediaResource::CacheClientUpdatePrincipal()
+{
+  // This might happen off the main thread.
+  if (NS_IsMainThread()) {
+    UpdatePrincipal();
+    return;
+  }
+
+  SystemGroup::Dispatch(
+    TaskCategory::Other,
+    NewRunnableMethod("ChannelMediaResource::UpdatePrincipal",
+                      this,
+                      &ChannelMediaResource::UpdatePrincipal));
 }
 
 void
 ChannelMediaResource::CacheClientNotifySuspendedStatusChanged()
 {
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
   mCallback->NotifySuspendedStatusChanged(IsSuspendedByCache());
 }
--- a/dom/media/MediaResource.h
+++ b/dom/media/MediaResource.h
@@ -430,18 +430,18 @@ public:
   // Notify that data is available from the cache. This can happen even
   // if this stream didn't read any data, since another stream might have
   // received data for the same resource.
   void CacheClientNotifyDataReceived();
   // Notify that we reached the end of the stream. This can happen even
   // if this stream didn't read any data, since another stream might have
   // received data for the same resource.
   void CacheClientNotifyDataEnded(nsresult aStatus);
-  // Notify that the principal for the cached resource changed.
-  void CacheClientNotifyPrincipalChanged();
+  // Notified by the cache to update the principal of the resource.
+  void CacheClientUpdatePrincipal();
   // Notify the decoder that the cache suspended status changed.
   void CacheClientNotifySuspendedStatusChanged();
 
   // These are called on the main thread by MediaCache. These shouldn't block,
   // but they may grab locks --- the media cache is not holding its lock
   // when these are called.
   // Start a new load at the given aOffset. The old load is cancelled
   // and no more data from the old load will be notified via
@@ -542,34 +542,35 @@ protected:
   // Opens the channel, using an HTTP byte range request to start at mOffset
   // if possible. Main thread only.
   nsresult OpenChannel(nsIStreamListener** aStreamListener);
   nsresult RecreateChannel();
   // Add headers to HTTP request. Main thread only.
   nsresult SetupChannelHeaders();
   // Closes the channel. Main thread only.
   void CloseChannel();
+  // Update the principal for the resource. Main thread only.
+  void UpdatePrincipal();
 
   // Parses 'Content-Range' header and returns results via parameters.
   // Returns error if header is not available, values are not parse-able or
   // values are out of range.
   nsresult ParseContentRangeHeader(nsIHttpChannel * aHttpChan,
                                    int64_t& aRangeStart,
                                    int64_t& aRangeEnd,
                                    int64_t& aRangeTotal);
 
   static nsresult CopySegmentToCache(nsIInputStream* aInStream,
-                                     void* aClosure,
+                                     void* aResource,
                                      const char* aFromSegment,
                                      uint32_t aToOffset,
                                      uint32_t aCount,
                                      uint32_t* aWriteCount);
 
-  nsresult CopySegmentToCache(nsIPrincipal* aPrincipal,
-                              const char* aFromSegment,
+  nsresult CopySegmentToCache(const char* aFromSegment,
                               uint32_t aCount,
                               uint32_t* aWriteCount);
 
   // Main thread access only
   int64_t            mOffset;
   RefPtr<Listener> mListener;
   // When this flag is set, if we get a network error we should silently
   // reopen the stream.