зеркало из https://github.com/mozilla/gecko-dev.git
Bug 803121 - Avoid using virtual functions in imgRequestProxy's destructor. r=joe
This commit is contained in:
Родитель
1da45a12a7
Коммит
3c46b167b3
|
@ -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__
|
||||||
|
|
Загрузка…
Ссылка в новой задаче