Bug 803121 - Avoid using virtual functions in imgRequestProxy's destructor. r=joe

This commit is contained in:
Josh Matthews 2012-10-19 15:39:38 -04:00
Родитель 1da45a12a7
Коммит 3c46b167b3
2 изменённых файлов: 166 добавлений и 100 удалений

Просмотреть файл

@ -25,6 +25,70 @@
using namespace mozilla::image; using namespace mozilla::image;
// The split of imgRequestProxy and imgRequestProxyStatic means that
// certain overridden functions need to be usable in the destructor.
// Since virtual functions can't be used in that way, this class
// provides a behavioural trait for each class to use instead.
class ProxyBehaviour
{
public:
virtual ~ProxyBehaviour() {}
virtual mozilla::image::Image* GetImage() const = 0;
virtual imgStatusTracker& GetStatusTracker() const = 0;
virtual imgRequest* GetOwner() const = 0;
virtual void SetOwner(imgRequest* aOwner) = 0;
};
class RequestBehaviour : public ProxyBehaviour
{
public:
RequestBehaviour() : mOwner(nullptr), mOwnerHasImage(false) {}
virtual mozilla::image::Image* GetImage() const MOZ_OVERRIDE;
virtual imgStatusTracker& GetStatusTracker() const MOZ_OVERRIDE;
virtual imgRequest* GetOwner() const MOZ_OVERRIDE {
return mOwner;
}
virtual void SetOwner(imgRequest* aOwner) MOZ_OVERRIDE {
mOwner = aOwner;
mOwnerHasImage = !!aOwner->GetStatusTracker().GetImage();
}
private:
// We maintain the following invariant:
// The proxy is registered at most with a single imgRequest as an observer,
// and whenever it is, mOwner points to that object. This helps ensure that
// imgRequestProxy::~imgRequestProxy unregisters the proxy as an observer
// from whatever request it was registered with (if any). This, in turn,
// means that imgRequest::mObservers will not have any stale pointers in it.
nsRefPtr<imgRequest> mOwner;
bool mOwnerHasImage;
};
mozilla::image::Image*
RequestBehaviour::GetImage() const
{
if (!mOwnerHasImage)
return nullptr;
return GetStatusTracker().GetImage();
}
imgStatusTracker&
RequestBehaviour::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.
// (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 mOwner->GetStatusTracker();
}
NS_IMPL_ADDREF(imgRequestProxy) NS_IMPL_ADDREF(imgRequestProxy)
NS_IMPL_RELEASE(imgRequestProxy) NS_IMPL_RELEASE(imgRequestProxy)
@ -38,7 +102,7 @@ NS_INTERFACE_MAP_BEGIN(imgRequestProxy)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
imgRequestProxy::imgRequestProxy() : imgRequestProxy::imgRequestProxy() :
mOwner(nullptr), mBehaviour(new RequestBehaviour),
mURI(nullptr), mURI(nullptr),
mListener(nullptr), mListener(nullptr),
mLoadFlags(nsIRequest::LOAD_NORMAL), mLoadFlags(nsIRequest::LOAD_NORMAL),
@ -49,8 +113,7 @@ imgRequestProxy::imgRequestProxy() :
mListenerIsStrongRef(false), mListenerIsStrongRef(false),
mDecodeRequested(false), mDecodeRequested(false),
mDeferNotifications(false), mDeferNotifications(false),
mSentStartContainer(false), mSentStartContainer(false)
mOwnerHasImage(false)
{ {
/* member initializers and constructor code */ /* member initializers and constructor code */
@ -74,14 +137,14 @@ imgRequestProxy::~imgRequestProxy()
// above assert. // above assert.
NullOutListener(); NullOutListener();
if (mOwner) { if (GetOwner()) {
/* Call RemoveProxy with a successful status. This will keep the /* Call RemoveProxy with a successful status. This will keep the
channel, if still downloading data, from being canceled if 'this' is channel, if still downloading data, from being canceled if 'this' is
the last observer. This allows the image to continue to download and the last observer. This allows the image to continue to download and
be cached even if no one is using it currently. be cached even if no one is using it currently.
*/ */
mCanceled = true; mCanceled = true;
mOwner->RemoveProxy(this, NS_OK); GetOwner()->RemoveProxy(this, NS_OK);
} }
} }
@ -89,14 +152,13 @@ nsresult imgRequestProxy::Init(imgStatusTracker* aStatusTracker,
nsILoadGroup* aLoadGroup, nsILoadGroup* aLoadGroup,
nsIURI* aURI, imgINotificationObserver* aObserver) nsIURI* aURI, imgINotificationObserver* aObserver)
{ {
NS_PRECONDITION(!mOwner && !mListener, "imgRequestProxy is already initialized"); NS_PRECONDITION(!GetOwner() && !mListener, "imgRequestProxy is already initialized");
LOG_SCOPE_WITH_PARAM(GetImgLog(), "imgRequestProxy::Init", "request", aStatusTracker->GetRequest()); LOG_SCOPE_WITH_PARAM(GetImgLog(), "imgRequestProxy::Init", "request", aStatusTracker->GetRequest());
NS_ABORT_IF_FALSE(mAnimationConsumers == 0, "Cannot have animation before Init"); NS_ABORT_IF_FALSE(mAnimationConsumers == 0, "Cannot have animation before Init");
mOwner = aStatusTracker->GetRequest(); mBehaviour->SetOwner(aStatusTracker->GetRequest());
mOwnerHasImage = !!aStatusTracker->GetImage();
mListener = aObserver; mListener = aObserver;
// Make sure to addref mListener before the AddProxy call below, since // Make sure to addref mListener before the AddProxy call below, since
// that call might well want to release it if the imgRequest has // that call might well want to release it if the imgRequest has
@ -109,15 +171,15 @@ nsresult imgRequestProxy::Init(imgStatusTracker* aStatusTracker,
mURI = aURI; mURI = aURI;
// Note: AddProxy won't send all the On* notifications immediately // Note: AddProxy won't send all the On* notifications immediately
if (mOwner) if (GetOwner())
mOwner->AddProxy(this); GetOwner()->AddProxy(this);
return NS_OK; return NS_OK;
} }
nsresult imgRequestProxy::ChangeOwner(imgRequest *aNewOwner) nsresult imgRequestProxy::ChangeOwner(imgRequest *aNewOwner)
{ {
NS_PRECONDITION(mOwner, "Cannot ChangeOwner on a proxy without an owner!"); NS_PRECONDITION(GetOwner(), "Cannot ChangeOwner on a proxy without an owner!");
if (mCanceled) { if (mCanceled) {
// Ensure that this proxy has received all notifications to date before // Ensure that this proxy has received all notifications to date before
@ -142,10 +204,9 @@ nsresult imgRequestProxy::ChangeOwner(imgRequest *aNewOwner)
wasDecoded = true; wasDecoded = true;
} }
mOwner->RemoveProxy(this, NS_IMAGELIB_CHANGING_OWNER); GetOwner()->RemoveProxy(this, NS_IMAGELIB_CHANGING_OWNER);
mOwner = aNewOwner; mBehaviour->SetOwner(aNewOwner);
mOwnerHasImage = !!GetStatusTracker().GetImage();
// If we were locked, apply the locks here // If we were locked, apply the locks here
for (uint32_t i = 0; i < oldLockCount; i++) for (uint32_t i = 0; i < oldLockCount; i++)
@ -157,12 +218,12 @@ nsresult imgRequestProxy::ChangeOwner(imgRequest *aNewOwner)
for (uint32_t i = 0; i < oldAnimationConsumers; i++) for (uint32_t i = 0; i < oldAnimationConsumers; i++)
IncrementAnimationConsumers(); IncrementAnimationConsumers();
mOwner->AddProxy(this); GetOwner()->AddProxy(this);
// If we were decoded, or if we'd previously requested a decode, request a // If we were decoded, or if we'd previously requested a decode, request a
// decode on the new image // decode on the new image
if (wasDecoded || mDecodeRequested) if (wasDecoded || mDecodeRequested)
mOwner->StartDecoding(); GetOwner()->StartDecoding();
return NS_OK; return NS_OK;
} }
@ -241,8 +302,8 @@ NS_IMETHODIMP imgRequestProxy::Cancel(nsresult status)
void void
imgRequestProxy::DoCancel(nsresult status) imgRequestProxy::DoCancel(nsresult status)
{ {
if (mOwner) { if (GetOwner()) {
mOwner->RemoveProxy(this, status); GetOwner()->RemoveProxy(this, status);
} }
NullOutListener(); NullOutListener();
@ -268,8 +329,8 @@ NS_IMETHODIMP imgRequestProxy::CancelAndForgetObserver(nsresult aStatus)
bool oldIsInLoadGroup = mIsInLoadGroup; bool oldIsInLoadGroup = mIsInLoadGroup;
mIsInLoadGroup = false; mIsInLoadGroup = false;
if (mOwner) { if (GetOwner()) {
mOwner->RemoveProxy(this, aStatus); GetOwner()->RemoveProxy(this, aStatus);
} }
mIsInLoadGroup = oldIsInLoadGroup; mIsInLoadGroup = oldIsInLoadGroup;
@ -289,28 +350,28 @@ NS_IMETHODIMP imgRequestProxy::CancelAndForgetObserver(nsresult aStatus)
NS_IMETHODIMP NS_IMETHODIMP
imgRequestProxy::StartDecoding() imgRequestProxy::StartDecoding()
{ {
if (!mOwner) if (!GetOwner())
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
// Flag this, so we know to transfer the request if our owner changes // Flag this, so we know to transfer the request if our owner changes
mDecodeRequested = true; mDecodeRequested = true;
// Forward the request // Forward the request
return mOwner->StartDecoding(); return GetOwner()->StartDecoding();
} }
/* void requestDecode (); */ /* void requestDecode (); */
NS_IMETHODIMP NS_IMETHODIMP
imgRequestProxy::RequestDecode() imgRequestProxy::RequestDecode()
{ {
if (!mOwner) if (!GetOwner())
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
// Flag this, so we know to transfer the request if our owner changes // Flag this, so we know to transfer the request if our owner changes
mDecodeRequested = true; mDecodeRequested = true;
// Forward the request // Forward the request
return mOwner->RequestDecode(); return GetOwner()->RequestDecode();
} }
@ -423,7 +484,9 @@ NS_IMETHODIMP imgRequestProxy::GetImage(imgIContainer * *aImage)
// that'll happen if we get Canceled before the owner instantiates its image // 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 // (because Canceling unregisters us as a listener on mOwner). If we're
// in that situation, just grab the image off of mOwner. // in that situation, just grab the image off of mOwner.
imgIContainer* imageToReturn = GetImage() ? GetImage() : mOwner->mImage.get(); imgIContainer* imageToReturn = GetImage();
if (!imageToReturn && GetOwner())
imageToReturn = GetOwner()->mImage.get();
if (!imageToReturn) if (!imageToReturn)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -463,10 +526,10 @@ NS_IMETHODIMP imgRequestProxy::GetNotificationObserver(imgINotificationObserver
/* readonly attribute string mimeType; */ /* readonly attribute string mimeType; */
NS_IMETHODIMP imgRequestProxy::GetMimeType(char **aMimeType) NS_IMETHODIMP imgRequestProxy::GetMimeType(char **aMimeType)
{ {
if (!mOwner) if (!GetOwner())
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
const char *type = mOwner->GetMimeType(); const char *type = GetOwner()->GetMimeType();
if (!type) if (!type)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
@ -484,8 +547,7 @@ imgRequestProxy* NewStaticProxy(imgRequestProxy* aThis)
{ {
nsCOMPtr<nsIPrincipal> currentPrincipal; nsCOMPtr<nsIPrincipal> currentPrincipal;
aThis->GetImagePrincipal(getter_AddRefs(currentPrincipal)); aThis->GetImagePrincipal(getter_AddRefs(currentPrincipal));
return new imgRequestProxyStatic( return new imgRequestProxyStatic(aThis->GetImage(), currentPrincipal);
static_cast<imgRequestProxyStatic*>(aThis)->mImage, currentPrincipal);
} }
NS_IMETHODIMP imgRequestProxy::Clone(imgINotificationObserver* aObserver, NS_IMETHODIMP imgRequestProxy::Clone(imgINotificationObserver* aObserver,
@ -531,20 +593,20 @@ nsresult imgRequestProxy::PerformClone(imgINotificationObserver* aObserver,
/* readonly attribute nsIPrincipal imagePrincipal; */ /* readonly attribute nsIPrincipal imagePrincipal; */
NS_IMETHODIMP imgRequestProxy::GetImagePrincipal(nsIPrincipal **aPrincipal) NS_IMETHODIMP imgRequestProxy::GetImagePrincipal(nsIPrincipal **aPrincipal)
{ {
if (!mOwner) if (!GetOwner())
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
NS_ADDREF(*aPrincipal = mOwner->GetPrincipal()); NS_ADDREF(*aPrincipal = GetOwner()->GetPrincipal());
return NS_OK; return NS_OK;
} }
/* readonly attribute bool multipart; */ /* readonly attribute bool multipart; */
NS_IMETHODIMP imgRequestProxy::GetMultipart(bool *aMultipart) NS_IMETHODIMP imgRequestProxy::GetMultipart(bool *aMultipart)
{ {
if (!mOwner) if (!GetOwner())
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
*aMultipart = mOwner->GetMultipart(); *aMultipart = GetOwner()->GetMultipart();
return NS_OK; return NS_OK;
} }
@ -552,10 +614,10 @@ NS_IMETHODIMP imgRequestProxy::GetMultipart(bool *aMultipart)
/* readonly attribute int32_t CORSMode; */ /* readonly attribute int32_t CORSMode; */
NS_IMETHODIMP imgRequestProxy::GetCORSMode(int32_t* aCorsMode) NS_IMETHODIMP imgRequestProxy::GetCORSMode(int32_t* aCorsMode)
{ {
if (!mOwner) if (!GetOwner())
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
*aCorsMode = mOwner->GetCORSMode(); *aCorsMode = GetOwner()->GetCORSMode();
return NS_OK; return NS_OK;
} }
@ -564,22 +626,22 @@ NS_IMETHODIMP imgRequestProxy::GetCORSMode(int32_t* aCorsMode)
NS_IMETHODIMP imgRequestProxy::GetPriority(int32_t *priority) NS_IMETHODIMP imgRequestProxy::GetPriority(int32_t *priority)
{ {
NS_ENSURE_STATE(mOwner); NS_ENSURE_STATE(GetOwner());
*priority = mOwner->Priority(); *priority = GetOwner()->Priority();
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP imgRequestProxy::SetPriority(int32_t priority) NS_IMETHODIMP imgRequestProxy::SetPriority(int32_t priority)
{ {
NS_ENSURE_STATE(mOwner && !mCanceled); NS_ENSURE_STATE(GetOwner() && !mCanceled);
mOwner->AdjustPriority(this, priority - mOwner->Priority()); GetOwner()->AdjustPriority(this, priority - GetOwner()->Priority());
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP imgRequestProxy::AdjustPriority(int32_t priority) NS_IMETHODIMP imgRequestProxy::AdjustPriority(int32_t priority)
{ {
NS_ENSURE_STATE(mOwner && !mCanceled); NS_ENSURE_STATE(GetOwner() && !mCanceled);
mOwner->AdjustPriority(this, priority); GetOwner()->AdjustPriority(this, priority);
return NS_OK; return NS_OK;
} }
@ -587,8 +649,8 @@ NS_IMETHODIMP imgRequestProxy::AdjustPriority(int32_t priority)
NS_IMETHODIMP imgRequestProxy::GetSecurityInfo(nsISupports** _retval) NS_IMETHODIMP imgRequestProxy::GetSecurityInfo(nsISupports** _retval)
{ {
if (mOwner) if (GetOwner())
return mOwner->GetSecurityInfo(_retval); return GetOwner()->GetSecurityInfo(_retval);
*_retval = nullptr; *_retval = nullptr;
return NS_OK; return NS_OK;
@ -596,8 +658,8 @@ NS_IMETHODIMP imgRequestProxy::GetSecurityInfo(nsISupports** _retval)
NS_IMETHODIMP imgRequestProxy::GetHasTransferredData(bool* hasData) NS_IMETHODIMP imgRequestProxy::GetHasTransferredData(bool* hasData)
{ {
if (mOwner) { if (GetOwner()) {
*hasData = mOwner->HasTransferredData(); *hasData = GetOwner()->HasTransferredData();
} else { } else {
// The safe thing to do is to claim we have data // The safe thing to do is to claim we have data
*hasData = true; *hasData = true;
@ -652,7 +714,7 @@ void imgRequestProxy::OnStopDecode()
} }
// Multipart needs reset for next OnStartContainer // Multipart needs reset for next OnStartContainer
if (mOwner && mOwner->GetMultipart()) if (GetOwner() && GetOwner()->GetMultipart())
mSentStartContainer = false; mSentStartContainer = false;
} }
@ -819,9 +881,9 @@ void imgRequestProxy::NotifyListener()
// processing when we receive notifications (like OnStopRequest()), and we // processing when we receive notifications (like OnStopRequest()), and we
// need to check mCanceled everywhere too. // need to check mCanceled everywhere too.
if (mOwner) { if (GetOwner()) {
// Send the notifications to our listener asynchronously. // Send the notifications to our listener asynchronously.
GetStatusTracker().Notify(mOwner, this); GetStatusTracker().Notify(GetOwner(), this);
} else { } else {
// We don't have an imgRequest, so we can only notify the clone of our // 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. // current state, but we still have to do that asynchronously.
@ -846,7 +908,9 @@ imgRequestProxy::SetHasImage()
{ {
Image* image = GetStatusTracker().GetImage(); Image* image = GetStatusTracker().GetImage();
mOwnerHasImage = true; // Force any private status related to the owner to reflect
// the presence of an image;
mBehaviour->SetOwner(mBehaviour->GetOwner());
// Apply any locks we have // Apply any locks we have
for (uint32_t i = 0; i < mLockCount; ++i) for (uint32_t i = 0; i < mLockCount; ++i)
@ -860,25 +924,57 @@ imgRequestProxy::SetHasImage()
imgStatusTracker& imgStatusTracker&
imgRequestProxy::GetStatusTracker() const imgRequestProxy::GetStatusTracker() const
{ {
// NOTE: It's possible that our mOwner has an Image that it didn't notify return mBehaviour->GetStatusTracker();
// 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 mOwner->GetStatusTracker();
} }
mozilla::image::Image* mozilla::image::Image*
imgRequestProxy::GetImage() const imgRequestProxy::GetImage() const
{ {
if (!mOwnerHasImage) return mBehaviour->GetImage();
return nullptr; }
return GetStatusTracker().GetImage();
imgRequest*
imgRequestProxy::GetOwner() const
{
return mBehaviour->GetOwner();
} }
////////////////// imgRequestProxyStatic methods ////////////////// imgRequestProxyStatic methods
class StaticBehaviour : public ProxyBehaviour
{
public:
StaticBehaviour(mozilla::image::Image* aImage) : mImage(aImage) {}
virtual mozilla::image::Image* GetImage() const MOZ_OVERRIDE {
return mImage;
}
virtual imgStatusTracker& GetStatusTracker() const MOZ_OVERRIDE {
return mImage->GetStatusTracker();
}
virtual imgRequest* GetOwner() const MOZ_OVERRIDE {
return nullptr;
}
virtual void SetOwner(imgRequest* aOwner) MOZ_OVERRIDE {
MOZ_ASSERT_IF(aOwner, "We shouldn't be giving static requests a non-null owner.");
}
private:
// 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;
};
imgRequestProxyStatic::imgRequestProxyStatic(mozilla::image::Image* aImage,
nsIPrincipal* aPrincipal)
: mPrincipal(aPrincipal)
{
mBehaviour = new StaticBehaviour(aImage);
}
NS_IMETHODIMP imgRequestProxyStatic::GetImagePrincipal(nsIPrincipal **aPrincipal) NS_IMETHODIMP imgRequestProxyStatic::GetImagePrincipal(nsIPrincipal **aPrincipal)
{ {
if (!mPrincipal) if (!mPrincipal)
@ -889,18 +985,6 @@ NS_IMETHODIMP imgRequestProxyStatic::GetImagePrincipal(nsIPrincipal **aPrincipal
return NS_OK; return NS_OK;
} }
mozilla::image::Image*
imgRequestProxyStatic::GetImage() const
{
return mImage;
}
imgStatusTracker&
imgRequestProxyStatic::GetStatusTracker() const
{
return mImage->GetStatusTracker();
}
NS_IMETHODIMP NS_IMETHODIMP
imgRequestProxyStatic::Clone(imgINotificationObserver* aObserver, imgRequestProxyStatic::Clone(imgINotificationObserver* aObserver,
imgIRequest** aClone) imgIRequest** aClone)

Просмотреть файл

@ -32,6 +32,7 @@
class imgRequestNotifyRunnable; class imgRequestNotifyRunnable;
class imgStatusNotifyRunnable; class imgStatusNotifyRunnable;
class ProxyBehaviour;
namespace mozilla { namespace mozilla {
namespace image { namespace image {
@ -161,16 +162,17 @@ protected:
// live either on mOwner or mImage, depending on whether // live either on mOwner or mImage, depending on whether
// (a) we have an mOwner at all // (a) we have an mOwner at all
// (b) whether mOwner has instantiated its image yet // (b) whether mOwner has instantiated its image yet
virtual imgStatusTracker& GetStatusTracker() const; imgStatusTracker& GetStatusTracker() const;
nsITimedChannel* TimedChannel() nsITimedChannel* TimedChannel()
{ {
if (!mOwner) if (!GetOwner())
return nullptr; return nullptr;
return mOwner->mTimedChannel; return GetOwner()->mTimedChannel;
} }
virtual mozilla::image::Image* GetImage() const; mozilla::image::Image* GetImage() const;
imgRequest* GetOwner() const;
nsresult PerformClone(imgINotificationObserver* aObserver, nsresult PerformClone(imgINotificationObserver* aObserver,
imgRequestProxy* (aAllocFn)(imgRequestProxy*), imgRequestProxy* (aAllocFn)(imgRequestProxy*),
@ -179,16 +181,12 @@ protected:
public: public:
NS_FORWARD_SAFE_NSITIMEDCHANNEL(TimedChannel()) NS_FORWARD_SAFE_NSITIMEDCHANNEL(TimedChannel())
protected:
nsAutoPtr<ProxyBehaviour> mBehaviour;
private: private:
friend class imgCacheValidator; friend class imgCacheValidator;
friend imgRequestProxy* NewStaticProxy(imgRequestProxy* aThis);
// We maintain the following invariant:
// The proxy is registered at most with a single imgRequest as an observer,
// and whenever it is, mOwner points to that object. This helps ensure that
// imgRequestProxy::~imgRequestProxy unregisters the proxy as an observer
// from whatever request it was registered with (if any). This, in turn,
// means that imgRequest::mObservers will not have any stale pointers in it.
nsRefPtr<imgRequest> mOwner;
// The URI of our request. // The URI of our request.
nsCOMPtr<nsIURI> mURI; nsCOMPtr<nsIURI> mURI;
@ -214,9 +212,6 @@ private:
// We only want to send OnStartContainer once for each proxy, but we might // We only want to send OnStartContainer once for each proxy, but we might
// get multiple OnStartContainer calls. // get multiple OnStartContainer calls.
bool mSentStartContainer; bool mSentStartContainer;
protected:
bool mOwnerHasImage;
}; };
// Used for static image proxies for which no requests are available, so // Used for static image proxies for which no requests are available, so
@ -226,15 +221,9 @@ class imgRequestProxyStatic : public imgRequestProxy
public: public:
imgRequestProxyStatic(mozilla::image::Image* aImage, imgRequestProxyStatic(mozilla::image::Image* aImage,
nsIPrincipal* aPrincipal) nsIPrincipal* aPrincipal);
: mImage(aImage)
, mPrincipal(aPrincipal)
{
mOwnerHasImage = true;
};
NS_IMETHOD GetImagePrincipal(nsIPrincipal** aPrincipal) MOZ_OVERRIDE; NS_IMETHOD GetImagePrincipal(nsIPrincipal** aPrincipal) MOZ_OVERRIDE;
virtual imgStatusTracker& GetStatusTracker() const MOZ_OVERRIDE;
NS_IMETHOD Clone(imgINotificationObserver* aObserver, NS_IMETHOD Clone(imgINotificationObserver* aObserver,
imgIRequest** aClone) MOZ_OVERRIDE; imgIRequest** aClone) MOZ_OVERRIDE;
@ -242,16 +231,9 @@ public:
protected: protected:
friend imgRequestProxy* NewStaticProxy(imgRequestProxy*); friend imgRequestProxy* NewStaticProxy(imgRequestProxy*);
// 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 // Our principal. We have to cache it, rather than accessing the underlying
// request on-demand, because static proxies don't have an underlying request. // request on-demand, because static proxies don't have an underlying request.
nsCOMPtr<nsIPrincipal> mPrincipal; nsCOMPtr<nsIPrincipal> mPrincipal;
mozilla::image::Image* GetImage() const MOZ_OVERRIDE;
using imgRequestProxy::GetImage;
}; };
#endif // imgRequestProxy_h__ #endif // imgRequestProxy_h__