Bug 505385 - Part 2: Move notification dispatch into imgStatusTracker. r=joe
authorBobby Holley <bobbyholley@gmail.com>
Thu, 11 Oct 2012 21:34:22 -0400
changeset 110147 9a20e6883f785961b02cdd461e35e5c88b3e998c
parent 110146 2440e35a985fc544a24a771a706d6325590290b0
child 110148 5c2493ac96c73111b0d1372b70828ebd26b3f2b1
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersjoe
bugs505385
milestone19.0a1
Bug 505385 - Part 2: Move notification dispatch into imgStatusTracker. r=joe
image/src/imgRequest.cpp
image/src/imgRequest.h
image/src/imgRequestProxy.cpp
image/src/imgRequestProxy.h
--- a/image/src/imgRequest.cpp
+++ b/image/src/imgRequest.cpp
@@ -183,18 +183,16 @@ void imgRequest::AddProxy(imgRequestProx
 
   // If we're empty before adding, we have to tell the loader we now have
   // proxies.
   if (GetStatusTracker().ConsumerCount() == 0) {
     NS_ABORT_IF_FALSE(mURI, "Trying to SetHasProxies without key uri.");
     mLoader->SetHasProxies(mURI);
   }
 
-  proxy->SetPrincipal(mPrincipal);
-
   GetStatusTracker().AddConsumer(proxy);
 }
 
 nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus)
 {
   LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::RemoveProxy", "proxy", proxy);
 
   // This will remove our animation consumers, so after removing
@@ -826,22 +824,16 @@ NS_IMETHODIMP imgRequest::OnStartRequest
     nsCOMPtr<nsIScriptSecurityManager> secMan =
       do_GetService("@mozilla.org/scriptsecuritymanager;1");
     if (secMan) {
       nsresult rv = secMan->GetChannelPrincipal(chan,
                                                 getter_AddRefs(mPrincipal));
       if (NS_FAILED(rv)) {
         return rv;
       }
-
-      // Tell all of our proxies that we have a principal.
-      nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
-      while (iter.HasMore()) {
-        iter.GetNext()->SetPrincipal(mPrincipal);
-      }
     }
   }
 
   SetCacheValidation(mCacheEntry, aRequest);
 
   // Shouldn't we be dead already if this gets hit?  Probably multipart/x-mixed-replace...
   if (GetStatusTracker().ConsumerCount() == 0) {
     this->Cancel(NS_IMAGELIB_ERROR_FAILURE);
--- a/image/src/imgRequest.h
+++ b/image/src/imgRequest.h
@@ -104,16 +104,19 @@ public:
   // The principal for the document that loaded this image. Used when trying to
   // validate a CORS image load.
   already_AddRefed<nsIPrincipal> GetLoadingPrincipal() const
   {
     nsCOMPtr<nsIPrincipal> principal = mLoadingPrincipal;
     return principal.forget();
   }
 
+  // Get the current principal of the image. No AddRefing.
+  inline nsIPrincipal* GetPrincipal() const { return mPrincipal.get(); };
+
 private:
   friend class imgCacheEntry;
   friend class imgRequestProxy;
   friend class imgLoader;
   friend class imgCacheValidator;
   friend class imgStatusTracker;
   friend class imgCacheExpirationTracker;
   friend class imgRequestNotifyRunnable;
--- a/image/src/imgRequestProxy.cpp
+++ b/image/src/imgRequestProxy.cpp
@@ -36,17 +36,16 @@ NS_INTERFACE_MAP_BEGIN(imgRequestProxy)
   NS_INTERFACE_MAP_ENTRY(nsISecurityInfoProvider)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsITimedChannel, TimedChannel() != nullptr)
 NS_INTERFACE_MAP_END
 
 imgRequestProxy::imgRequestProxy() :
   mOwner(nullptr),
   mURI(nullptr),
   mImage(nullptr),
-  mPrincipal(nullptr),
   mListener(nullptr),
   mLoadFlags(nsIRequest::LOAD_NORMAL),
   mLockCount(0),
   mAnimationConsumers(0),
   mCanceled(false),
   mIsInLoadGroup(false),
   mListenerIsStrongRef(false),
   mDecodeRequested(false),
@@ -504,38 +503,35 @@ NS_IMETHODIMP imgRequestProxy::Clone(img
   // request to the loadgroup.
   clone->SetLoadFlags(mLoadFlags);
   nsresult rv = clone->Init(mOwner, mLoadGroup,
                             mImage ? mImage : mOwner->mImage,
                             mURI, aObserver);
   if (NS_FAILED(rv))
     return rv;
 
-  clone->SetPrincipal(mPrincipal);
-
   // Assign to *aClone before calling Notify so that if the caller expects to
   // only be notified for requests it's already holding pointers to it won't be
   // surprised.
   NS_ADDREF(*aClone = clone);
 
   // This is wrong!!! We need to notify asynchronously, but there's code that
   // assumes that we don't. This will be fixed in bug 580466.
   clone->SyncNotifyListener();
 
   return NS_OK;
 }
 
 /* readonly attribute nsIPrincipal imagePrincipal; */
 NS_IMETHODIMP imgRequestProxy::GetImagePrincipal(nsIPrincipal **aPrincipal)
 {
-  if (!mPrincipal)
+  if (!mOwner)
     return NS_ERROR_FAILURE;
 
-  NS_ADDREF(*aPrincipal = mPrincipal);
-
+  NS_ADDREF(*aPrincipal = mOwner->GetPrincipal());
   return NS_OK;
 }
 
 /* readonly attribute bool multipart; */
 NS_IMETHODIMP imgRequestProxy::GetMultipart(bool *aMultipart)
 {
   if (!mOwner)
     return NS_ERROR_FAILURE;
@@ -847,30 +843,26 @@ imgRequestProxy::GetStaticRequest(imgIRe
                                      imgIContainer::FLAG_SYNC_DECODE,
                                      getter_AddRefs(currentFrame));
   if (NS_FAILED(rv))
     return rv;
 
   nsRefPtr<Image> frame = static_cast<Image*>(currentFrame.get());
 
   // Create a static imgRequestProxy with our new extracted frame.
-  nsRefPtr<imgRequestProxy> req = new imgRequestProxy();
+  nsCOMPtr<nsIPrincipal> currentPrincipal;
+  GetImagePrincipal(getter_AddRefs(currentPrincipal));
+  nsRefPtr<imgRequestProxy> req = new imgRequestProxyStatic(currentPrincipal);
   req->Init(nullptr, nullptr, frame, mURI, nullptr);
-  req->SetPrincipal(mPrincipal);
 
   NS_ADDREF(*aReturn = req);
 
   return NS_OK;
 }
 
-void imgRequestProxy::SetPrincipal(nsIPrincipal *aPrincipal)
-{
-  mPrincipal = aPrincipal;
-}
-
 void imgRequestProxy::NotifyListener()
 {
   // It would be nice to notify the observer directly in the status tracker
   // instead of through the proxy, but there are several places we do extra
   // processing when we receive notifications (like OnStopRequest()), and we
   // need to check mCanceled everywhere too.
 
   if (mOwner) {
@@ -919,8 +911,20 @@ imgRequestProxy::GetStatusTracker()
   // NOTE: It's possible that our mOwner has an Image that it didn't notify
   // us about, if we were Canceled before its Image was constructed.
   // (Canceling removes us as an observer, so mOwner has no way to notify us).
   // That's why this method uses mOwner->GetStatusTracker() instead of just
   // mOwner->mStatusTracker -- we might have a null mImage and yet have an
   // mOwner with a non-null mImage (and a null mStatusTracker pointer).
   return mImage ? mImage->GetStatusTracker() : mOwner->GetStatusTracker();
 }
+
+////////////////// imgRequestProxyStatic methods
+
+NS_IMETHODIMP imgRequestProxyStatic::GetImagePrincipal(nsIPrincipal **aPrincipal)
+{
+  if (!mPrincipal)
+    return NS_ERROR_FAILURE;
+
+  NS_ADDREF(*aPrincipal = mPrincipal);
+
+  return NS_OK;
+}
--- a/image/src/imgRequestProxy.h
+++ b/image/src/imgRequestProxy.h
@@ -66,18 +66,16 @@ public:
 
   void AddToLoadGroup();
   void RemoveFromLoadGroup(bool releaseLoadGroup);
 
   inline bool HasObserver() const {
     return mListener != nullptr;
   }
 
-  void SetPrincipal(nsIPrincipal *aPrincipal);
-
   // Asynchronously notify this proxy's listener of the current state of the
   // image, and, if we have an imgRequest mOwner, any status changes that
   // happen between the time this function is called and the time the
   // notification is scheduled.
   void NotifyListener();
 
   // Synchronously notify this proxy's listener of the current state of the
   // image. Only use this function if you are currently servicing an
@@ -196,20 +194,16 @@ private:
 
   // The URI of our request.
   nsCOMPtr<nsIURI> mURI;
 
   // The image we represent. Is null until data has been received, and is then
   // set by imgRequest.
   nsRefPtr<mozilla::image::Image> mImage;
 
-  // Our principal. Is null until data has been received from the channel, and
-  // is then set by imgRequest.
-  nsCOMPtr<nsIPrincipal> mPrincipal;
-
   // mListener is only promised to be a weak ref (see imgILoader.idl),
   // but we actually keep a strong ref to it until we've seen our
   // first OnStopRequest.
   imgIDecoderObserver* mListener;
   nsCOMPtr<nsILoadGroup> mLoadGroup;
 
   nsLoadFlags mLoadFlags;
   uint32_t    mLockCount;
@@ -223,9 +217,26 @@ private:
   // interfaces as image loads proceed.
   bool mDeferNotifications;
 
   // We only want to send OnStartContainer once for each proxy, but we might
   // get multiple OnStartContainer calls.
   bool mSentStartContainer;
 };
 
+// Used for static image proxies for which no requests are available, so
+// certain behaviours must be overridden to compensate.
+class imgRequestProxyStatic : public imgRequestProxy
+{
+
+public:
+  imgRequestProxyStatic(nsIPrincipal* aPrincipal) : mPrincipal(aPrincipal) {};
+
+  NS_IMETHOD GetImagePrincipal(nsIPrincipal** aPrincipal);
+
+protected:
+  // Our principal. We have to cache it, rather than accessing the underlying
+  // request on-demand, because static proxies don't have an underlying request.
+  nsCOMPtr<nsIPrincipal> mPrincipal;
+
+};
+
 #endif // imgRequestProxy_h__