Bug 929029 - Use nsMainThreadPtrHandle in MediaResource. r=roc, r=doublec
authorSotaro Ikeda <sikeda@mozilla.com>
Mon, 02 Dec 2013 10:22:33 -0500
changeset 173930 f9d8f53e8739d89bbbcf91564cf267c22d094f1e
parent 173929 d4577f8235d97f991a6906d49478f282213ffcb3
child 173986 492fbc8095b807132f96446fcc6a8db62faf9ff8
child 174090 9367f9dbf7461ee0020e8abcf37ecad80efed624
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, doublec
bugs929029
milestone28.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 929029 - Use nsMainThreadPtrHandle in MediaResource. r=roc, r=doublec
content/media/MediaResource.cpp
content/media/MediaResource.h
--- a/content/media/MediaResource.cpp
+++ b/content/media/MediaResource.cpp
@@ -447,17 +447,17 @@ ChannelMediaResource::OnStopRequest(nsIR
 
   return NS_OK;
 }
 
 nsresult
 ChannelMediaResource::OnChannelRedirect(nsIChannel* aOld, nsIChannel* aNew,
                                         uint32_t aFlags)
 {
-  mChannel = aNew;
+  mChannel = new nsMainThreadPtrHolder<nsIChannel>(aNew);
   SetupChannelHeaders();
   return NS_OK;
 }
 
 struct CopySegmentClosure {
   nsCOMPtr<nsIPrincipal> mPrincipal;
   ChannelMediaResource*  mResource;
 };
@@ -496,17 +496,17 @@ ChannelMediaResource::OnDataAvailable(ns
 
   {
     MutexAutoLock lock(mLock);
     mChannelStatistics->AddBytes(aCount);
   }
 
   CopySegmentClosure closure;
   nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
-  if (secMan && mChannel) {
+  if (secMan && mChannel.get()) {
     secMan->GetChannelPrincipal(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,
@@ -528,31 +528,31 @@ nsresult ChannelMediaResource::Open(nsIS
     mChannelStatistics = new MediaChannelStatistics();
   }
 
   nsresult rv = mCacheStream.Init();
   if (NS_FAILED(rv))
     return rv;
   NS_ASSERTION(mOffset == 0, "Who set mOffset already?");
 
-  if (!mChannel) {
+  if (!mChannel.get()) {
     // When we're a clone, the decoder might ask us to Open even though
     // we haven't established an mChannel (because we might not need one)
     NS_ASSERTION(!aStreamListener,
                  "Should have already been given a channel if we're to return a stream listener");
     return NS_OK;
   }
 
   return OpenChannel(aStreamListener);
 }
 
 nsresult ChannelMediaResource::OpenChannel(nsIStreamListener** aStreamListener)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
-  NS_ENSURE_TRUE(mChannel, NS_ERROR_NULL_POINTER);
+  NS_ENSURE_TRUE(mChannel.get(), NS_ERROR_NULL_POINTER);
   NS_ASSERTION(!mListener, "Listener should have been removed by now");
 
   if (aStreamListener) {
     *aStreamListener = nullptr;
   }
 
   if (mByteRange.IsNull()) {
     // We're not making a byte range request, so set the content length,
@@ -708,17 +708,17 @@ void ChannelMediaResource::CloseChannel(
     mChannelStatistics->Stop();
   }
 
   if (mListener) {
     mListener->Revoke();
     mListener = nullptr;
   }
 
-  if (mChannel) {
+  if (mChannel.get()) {
     if (mSuspendCount > 0) {
       // Resume the channel before we cancel it
       PossiblyResume();
     }
     // The status we use here won't be passed to the decoder, since
     // we've already revoked the listener. It can however be passed
     // to nsDocumentViewer::LoadComplete if our channel is the one
     // that kicked off creation of a video document. We don't want that
@@ -806,17 +806,17 @@ void ChannelMediaResource::Suspend(bool 
     return;
   }
   dom::HTMLMediaElement* element = owner->GetMediaElement();
   if (!element) {
     // Shutting down; do nothing.
     return;
   }
 
-  if (mChannel) {
+  if (mChannel.get()) {
     if (aCloseImmediately && mCacheStream.IsTransportSeekable()) {
       // Kill off our channel right now, but don't tell anyone about it.
       mIgnoreClose = true;
       CloseChannel();
       element->DownloadSuspended();
     } else if (mSuspendCount == 0) {
       {
         MutexAutoLock lock(mLock);
@@ -844,17 +844,17 @@ void ChannelMediaResource::Resume()
   if (!element) {
     // Shutting down; do nothing.
     return;
   }
 
   NS_ASSERTION(mSuspendCount > 0, "Resume without previous Suspend!");
   --mSuspendCount;
   if (mSuspendCount == 0) {
-    if (mChannel) {
+    if (mChannel.get()) {
       // Just wake up our existing channel
       {
         MutexAutoLock lock(mLock);
         mChannelStatistics->Start();
       }
       // if an error occurs after Resume, assume it's because the server
       // timed out the connection and we should reopen it.
       mReopenOnError = true;
@@ -892,22 +892,24 @@ ChannelMediaResource::RecreateChannel()
   dom::HTMLMediaElement* element = owner->GetMediaElement();
   if (!element) {
     // The decoder is being shut down, so don't bother opening a new channel
     return NS_OK;
   }
   nsCOMPtr<nsILoadGroup> loadGroup = element->GetDocumentLoadGroup();
   NS_ENSURE_TRUE(loadGroup, NS_ERROR_NULL_POINTER);
 
-  nsresult rv = NS_NewChannel(getter_AddRefs(mChannel),
+  nsCOMPtr<nsIChannel> channel;
+  nsresult rv = NS_NewChannel(getter_AddRefs(channel),
                               mURI,
                               nullptr,
                               loadGroup,
                               nullptr,
                               loadFlags);
+  mChannel = new nsMainThreadPtrHolder<nsIChannel>(channel);
 
   // We have cached the Content-Type, which should not change. Give a hint to
   // the channel to avoid a sniffing failure, which would be expected because we
   // are probably seeking in the middle of the bitstream, and sniffing relies
   // on the presence of a magic number at the beginning of the stream.
   NS_ASSERTION(!GetContentType().IsEmpty(),
       "When recreating a channel, we should know the Content-Type.");
   mChannel->SetContentType(GetContentType());
@@ -985,17 +987,17 @@ ChannelMediaResource::CacheClientSeek(in
     --mSuspendCount;
   }
 
   mOffset = aOffset;
 
   if (mSuspendCount > 0) {
     // Close the existing channel to force the channel to be recreated at
     // the correct offset upon resume.
-    if (mChannel) {
+    if (mChannel.get()) {
       mIgnoreClose = true;
       CloseChannel();
     }
     return NS_OK;
   }
 
   nsresult rv = RecreateChannel();
   if (NS_FAILED(rv))
@@ -1335,31 +1337,31 @@ nsresult FileMediaResource::Open(nsIStre
 }
 
 nsresult FileMediaResource::Close()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   // Since mChennel is only accessed by main thread, there is no necessary to
   // take the lock.
-  if (mChannel) {
+  if (mChannel.get()) {
     mChannel->Cancel(NS_ERROR_PARSED_DATA_CACHED);
     mChannel = nullptr;
   }
 
   return NS_OK;
 }
 
 already_AddRefed<nsIPrincipal> FileMediaResource::GetCurrentPrincipal()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   nsCOMPtr<nsIPrincipal> principal;
   nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
-  if (!secMan || !mChannel)
+  if (!secMan || !mChannel.get())
     return nullptr;
   secMan->GetChannelPrincipal(mChannel, getter_AddRefs(principal));
   return principal.forget();
 }
 
 bool FileMediaResource::CanClone()
 {
   return true;
@@ -1518,17 +1520,17 @@ MediaResource::Create(MediaDecoder* aDec
     resource = new ChannelMediaResource(aDecoder, aChannel, uri, contentType);
   }
   return resource.forget();
 }
 
 void BaseMediaResource::MoveLoadsToBackground() {
   NS_ASSERTION(!mLoadInBackground, "Why are you calling this more than once?");
   mLoadInBackground = true;
-  if (!mChannel) {
+  if (!mChannel.get()) {
     // No channel, resource is probably already loaded.
     return;
   }
 
   MediaDecoderOwner* owner = mDecoder->GetMediaOwner();
   if (!owner) {
     NS_WARNING("Null owner in MediaResource::MoveLoadsToBackground()");
     return;
--- a/content/media/MediaResource.h
+++ b/content/media/MediaResource.h
@@ -8,16 +8,17 @@
 
 #include "mozilla/Mutex.h"
 #include "nsIChannel.h"
 #include "nsIURI.h"
 #include "nsIStreamingProtocolController.h"
 #include "nsIStreamListener.h"
 #include "nsIChannelEventSink.h"
 #include "nsIInterfaceRequestor.h"
+#include "nsProxyRelease.h"
 #include "MediaCache.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/TimeStamp.h"
 #include "nsThreadUtils.h"
 
 // For HTTP seeking, if number of bytes needing to be
 // seeked forward is less than this value then a read is
 // done rather than a byte range request.
@@ -390,27 +391,27 @@ public:
   }
 
 protected:
   virtual ~MediaResource() {};
 };
 
 class BaseMediaResource : public MediaResource {
 public:
-  virtual nsIURI* URI() const { return mURI; }
+  virtual nsIURI* URI() const { return const_cast<nsIURI*>(mURI.get()); }
   virtual void MoveLoadsToBackground();
 
 protected:
   BaseMediaResource(MediaDecoder* aDecoder,
                     nsIChannel* aChannel,
                     nsIURI* aURI,
                     const nsACString& aContentType) :
     mDecoder(aDecoder),
-    mChannel(aChannel),
-    mURI(aURI),
+    mChannel(new nsMainThreadPtrHolder<nsIChannel>(aChannel)),
+    mURI(new nsMainThreadPtrHolder<nsIURI>(aURI)),
     mContentType(aContentType),
     mLoadInBackground(false)
   {
     MOZ_COUNT_CTOR(BaseMediaResource);
     NS_ASSERTION(!mContentType.IsEmpty(), "Must know content type");
   }
   virtual ~BaseMediaResource()
   {
@@ -433,21 +434,21 @@ protected:
 
   // This is not an nsCOMPointer to prevent a circular reference
   // between the decoder to the media stream object. The stream never
   // outlives the lifetime of the decoder.
   MediaDecoder* mDecoder;
 
   // Channel used to download the media data. Must be accessed
   // from the main thread only.
-  nsCOMPtr<nsIChannel> mChannel;
+  nsMainThreadPtrHandle<nsIChannel> mChannel;
 
   // URI in case the stream needs to be re-opened. Access from
   // main thread only.
-  nsCOMPtr<nsIURI> mURI;
+  nsMainThreadPtrHandle<nsIURI> mURI;
 
   // Content-Type of the channel. This is copied from the nsIChannel when the
   // MediaResource is created. This is constant, so accessing from any thread
   // is safe.
   const nsAutoCString mContentType;
 
   // True if MoveLoadsToBackground() has been called, i.e. the load event
   // has been fired, and all channel loads will be in the background.