Bug 505385 - Part 8: Remove image reference from proxies, and delegate operations on images to the owning request or the status tracker. r=joe

This commit is contained in:
Josh Matthews 2012-10-11 21:34:23 -04:00
parent c63c777ca4
commit af9ce4332d
3 changed files with 76 additions and 53 deletions

View File

@ -995,7 +995,7 @@ imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt,
if (mResniffMimeType) {
NS_ABORT_IF_FALSE(mIsMultiPartChannel, "Resniffing a non-multipart image");
imgStatusTracker* freshTracker = new imgStatusTracker(nullptr, this);
freshTracker->AdoptConsumers(mStatusTracker);
freshTracker->AdoptConsumers(&GetStatusTracker());
mStatusTracker = freshTracker;
}
@ -1012,7 +1012,7 @@ imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt,
// Notify any imgRequestProxys that are observing us that we have an Image.
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(GetStatusTracker().GetConsumers());
while (iter.HasMore()) {
iter.GetNext()->SetImage(mImage);
iter.GetNext()->SetHasImage();
}
/* set our mimetype as a property */

View File

@ -40,7 +40,6 @@ NS_INTERFACE_MAP_END
imgRequestProxy::imgRequestProxy() :
mOwner(nullptr),
mURI(nullptr),
mImage(nullptr),
mListener(nullptr),
mLoadFlags(nsIRequest::LOAD_NORMAL),
mLockCount(0),
@ -50,7 +49,8 @@ imgRequestProxy::imgRequestProxy() :
mListenerIsStrongRef(false),
mDecodeRequested(false),
mDeferNotifications(false),
mSentStartContainer(false)
mSentStartContainer(false),
mOwnerHasImage(false)
{
/* member initializers and constructor code */
@ -100,6 +100,8 @@ nsresult imgRequestProxy::Init(imgStatusTracker* aStatusTracker,
mStatusTracker = aStatusTracker;
mOwner = aStatusTracker->GetRequest();
mOwnerHasImage = !!aStatusTracker->GetImage();
MOZ_ASSERT_IF(mOwner, mStatusTracker == &mOwner->GetStatusTracker());
mListener = aObserver;
// Make sure to addref mListener before the AddProxy call below, since
// that call might well want to release it if the imgRequest has
@ -109,7 +111,6 @@ nsresult imgRequestProxy::Init(imgStatusTracker* aStatusTracker,
NS_ADDREF(mListener);
}
mLoadGroup = aLoadGroup;
mImage = aStatusTracker->GetImage();
mURI = aURI;
// Note: AddProxy won't send all the On* notifications immediately
@ -133,9 +134,9 @@ nsresult imgRequestProxy::ChangeOwner(imgRequest *aNewOwner)
uint32_t oldAnimationConsumers = mAnimationConsumers;
ClearAnimationConsumers();
// Even if we are cancelled, we MUST change our image, because the image
// holds our status, and the status must always be correct.
mImage = aNewOwner->mImage;
nsRefPtr<imgRequest> oldOwner = mOwner;
mOwner = aNewOwner;
mStatusTracker = &aNewOwner->GetStatusTracker();
// If we were locked, apply the locks here
for (uint32_t i = 0; i < oldLockCount; i++)
@ -152,13 +153,12 @@ nsresult imgRequestProxy::ChangeOwner(imgRequest *aNewOwner)
// Were we decoded before?
bool wasDecoded = false;
if (mImage &&
(mImage->GetStatusTracker().GetImageStatus() &
imgIRequest::STATUS_FRAME_COMPLETE)) {
if (GetImage() &&
(GetStatusTracker().GetImageStatus() & imgIRequest::STATUS_FRAME_COMPLETE)) {
wasDecoded = true;
}
mOwner->RemoveProxy(this, NS_IMAGELIB_CHANGING_OWNER);
oldOwner->RemoveProxy(this, NS_IMAGELIB_CHANGING_OWNER, false);
// If we had animation requests, restore them here. Note that we
// do this *after* RemoveProxy, which clears out animation consumers
@ -166,8 +166,6 @@ nsresult imgRequestProxy::ChangeOwner(imgRequest *aNewOwner)
for (uint32_t i = 0; i < oldAnimationConsumers; i++)
IncrementAnimationConsumers();
mOwner = aNewOwner;
mOwner->AddProxy(this);
// If we were decoded, or if we'd previously requested a decode, request a
@ -330,8 +328,8 @@ NS_IMETHODIMP
imgRequestProxy::LockImage()
{
mLockCount++;
if (mImage)
return mImage->LockImage();
if (GetImage())
return GetImage()->LockImage();
return NS_OK;
}
@ -342,8 +340,8 @@ imgRequestProxy::UnlockImage()
NS_ABORT_IF_FALSE(mLockCount > 0, "calling unlock but no locks!");
mLockCount--;
if (mImage)
return mImage->UnlockImage();
if (GetImage())
return GetImage()->UnlockImage();
return NS_OK;
}
@ -351,9 +349,8 @@ imgRequestProxy::UnlockImage()
NS_IMETHODIMP
imgRequestProxy::RequestDiscard()
{
if (mImage) {
return mImage->RequestDiscard();
}
if (GetImage())
return GetImage()->RequestDiscard();
return NS_OK;
}
@ -361,8 +358,8 @@ NS_IMETHODIMP
imgRequestProxy::IncrementAnimationConsumers()
{
mAnimationConsumers++;
if (mImage)
mImage->IncrementAnimationConsumers();
if (GetImage())
GetImage()->IncrementAnimationConsumers();
return NS_OK;
}
@ -377,8 +374,8 @@ imgRequestProxy::DecrementAnimationConsumers()
// early, but not the observer.)
if (mAnimationConsumers > 0) {
mAnimationConsumers--;
if (mImage)
mImage->DecrementAnimationConsumers();
if (GetImage())
GetImage()->DecrementAnimationConsumers();
}
return NS_OK;
}
@ -435,7 +432,7 @@ NS_IMETHODIMP imgRequestProxy::GetImage(imgIContainer * *aImage)
// that'll happen if we get Canceled before the owner instantiates its image
// (because Canceling unregisters us as a listener on mOwner). If we're
// in that situation, just grab the image off of mOwner.
imgIContainer* imageToReturn = mImage ? mImage : mOwner->mImage;
imgIContainer* imageToReturn = GetImage() ? GetImage() : mOwner->mImage.get();
if (!imageToReturn)
return NS_ERROR_FAILURE;
@ -824,9 +821,10 @@ NS_IMETHODIMP
imgRequestProxy::GetStaticRequest(imgIRequest** aReturn)
{
*aReturn = nullptr;
mozilla::image::Image* image = GetImage();
bool animated;
if (!mImage || (NS_SUCCEEDED(mImage->GetAnimated(&animated)) && !animated)) {
if (!image || (NS_SUCCEEDED(image->GetAnimated(&animated)) && !animated)) {
// Early exit - we're not animated, so we don't have to do anything.
NS_ADDREF(*aReturn = this);
return NS_OK;
@ -835,13 +833,13 @@ imgRequestProxy::GetStaticRequest(imgIRequest** aReturn)
// We are animated. We need to extract the current frame from this image.
int32_t w = 0;
int32_t h = 0;
mImage->GetWidth(&w);
mImage->GetHeight(&h);
image->GetWidth(&w);
image->GetHeight(&h);
nsIntRect rect(0, 0, w, h);
nsCOMPtr<imgIContainer> currentFrame;
nsresult rv = mImage->ExtractFrame(imgIContainer::FRAME_CURRENT, rect,
imgIContainer::FLAG_SYNC_DECODE,
getter_AddRefs(currentFrame));
nsresult rv = image->ExtractFrame(imgIContainer::FRAME_CURRENT, rect,
imgIContainer::FLAG_SYNC_DECODE,
getter_AddRefs(currentFrame));
if (NS_FAILED(rv))
return rv;
@ -850,7 +848,7 @@ imgRequestProxy::GetStaticRequest(imgIRequest** aReturn)
// Create a static imgRequestProxy with our new extracted frame.
nsCOMPtr<nsIPrincipal> currentPrincipal;
GetImagePrincipal(getter_AddRefs(currentPrincipal));
nsRefPtr<imgRequestProxy> req = new imgRequestProxyStatic(currentPrincipal);
nsRefPtr<imgRequestProxy> req = new imgRequestProxyStatic(frame, currentPrincipal);
req->Init(&frame->GetStatusTracker(), nullptr, mURI, nullptr);
NS_ADDREF(*aReturn = req);
@ -871,9 +869,9 @@ void imgRequestProxy::NotifyListener()
} else {
// We don't have an imgRequest, so we can only notify the clone of our
// current state, but we still have to do that asynchronously.
NS_ABORT_IF_FALSE(mImage,
NS_ABORT_IF_FALSE(GetImage(),
"if we have no imgRequest, we should have an Image");
mImage->GetStatusTracker().NotifyCurrentState(this);
GetStatusTracker().NotifyCurrentState(this);
}
}
@ -888,25 +886,23 @@ void imgRequestProxy::SyncNotifyListener()
}
void
imgRequestProxy::SetImage(Image* aImage)
imgRequestProxy::SetHasImage()
{
NS_ABORT_IF_FALSE(aImage, "Setting null image");
NS_ABORT_IF_FALSE(!mImage || mOwner->GetMultipart(),
"Setting image when we already have one");
Image* image = GetStatusTracker().GetImage();
mImage = aImage;
mOwnerHasImage = true;
// Apply any locks we have
for (uint32_t i = 0; i < mLockCount; ++i)
mImage->LockImage();
image->LockImage();
// Apply any animation consumers we have
for (uint32_t i = 0; i < mAnimationConsumers; i++)
mImage->IncrementAnimationConsumers();
image->IncrementAnimationConsumers();
}
imgStatusTracker&
imgRequestProxy::GetStatusTracker()
imgRequestProxy::GetStatusTracker() const
{
// 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.
@ -914,7 +910,15 @@ imgRequestProxy::GetStatusTracker()
// 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();
return *mStatusTracker;
}
mozilla::image::Image*
imgRequestProxy::GetImage() const
{
if (!mOwnerHasImage)
return nullptr;
return GetStatusTracker().GetImage();
}
////////////////// imgRequestProxyStatic methods
@ -928,3 +932,9 @@ NS_IMETHODIMP imgRequestProxyStatic::GetImagePrincipal(nsIPrincipal **aPrincipal
return NS_OK;
}
mozilla::image::Image*
imgRequestProxyStatic::GetImage() const
{
return mImage;
}

View File

@ -93,9 +93,8 @@ public:
mDeferNotifications = aDeferNotifications;
}
// Setter for our |mImage| pointer, for imgRequest to use, once it
// instantiates an Image.
void SetImage(mozilla::image::Image* aImage);
// XXXbholley - This eventually gets folded into the new notification API.
void SetHasImage();
// Removes all animation consumers that were created with
// IncrementAnimationConsumers. This is necessary since we need
@ -169,7 +168,7 @@ protected:
// live either on mOwner or mImage, depending on whether
// (a) we have an mOwner at all
// (b) whether mOwner has instantiated its image yet
imgStatusTracker& GetStatusTracker();
imgStatusTracker& GetStatusTracker() const;
nsITimedChannel* TimedChannel()
{
@ -178,6 +177,8 @@ protected:
return mOwner->mTimedChannel;
}
virtual mozilla::image::Image* GetImage() const;
public:
NS_FORWARD_SAFE_NSITIMEDCHANNEL(TimedChannel())
@ -198,10 +199,6 @@ 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;
// 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.
@ -223,6 +220,9 @@ private:
// We only want to send OnStartContainer once for each proxy, but we might
// get multiple OnStartContainer calls.
bool mSentStartContainer;
protected:
bool mOwnerHasImage;
};
// Used for static image proxies for which no requests are available, so
@ -231,15 +231,28 @@ class imgRequestProxyStatic : public imgRequestProxy
{
public:
imgRequestProxyStatic(nsIPrincipal* aPrincipal) : mPrincipal(aPrincipal) {};
imgRequestProxyStatic(mozilla::image::Image* aImage,
nsIPrincipal* aPrincipal)
: mImage(aImage)
, mPrincipal(aPrincipal)
{
mOwnerHasImage = true;
};
NS_IMETHOD GetImagePrincipal(nsIPrincipal** aPrincipal);
protected:
// Our image. We have to hold a strong reference here, because that's normally
// the job of the underlying request.
nsRefPtr<mozilla::image::Image> mImage;
// 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;
private:
mozilla::image::Image* GetImage() const MOZ_OVERRIDE;
using imgRequestProxy::GetImage;
};
#endif // imgRequestProxy_h__