Bug 572520: step 5, remove imgContainerRequest because it duplicates the body of NotifyProxyListener. Put its required abilities into imgRequestProxy and imgContainer. r=jrmuizel

This commit is contained in:
Joe Drew 2010-05-10 23:27:41 -04:00
Родитель 0c58465024
Коммит f6335ecb84
8 изменённых файлов: 235 добавлений и 516 удалений

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

@ -57,7 +57,6 @@ CPPSRCS = \
imgRequest.cpp \
imgRequestProxy.cpp \
imgTools.cpp \
imgContainerRequest.cpp \
imgDiscardTracker.cpp \
$(NULL)

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

@ -1,280 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Olli Pettay <Olli.Pettay@helsinki.fi> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "imgContainerRequest.h"
#include "ImageErrors.h"
#include "imgRequest.h"
NS_IMPL_ISUPPORTS2(imgContainerRequest, imgIRequest, nsIRequest)
imgContainerRequest::imgContainerRequest(imgIContainer* aImage,
nsIURI* aURI,
PRUint32 aImageStatus,
PRUint32 aState,
nsIPrincipal* aPrincipal)
: mImage(aImage), mURI(aURI), mPrincipal(aPrincipal), mImageStatus(aImageStatus),
mState(aState), mLocksHeld(0)
{
#ifdef DEBUG
PRUint32 numFrames = 0;
if (aImage) {
aImage->GetNumFrames(&numFrames);
}
NS_ABORT_IF_FALSE(!aImage || numFrames == 1,
"Shouldn't have image with more than one frame!");
#endif
}
imgContainerRequest::~imgContainerRequest()
{
if (mImage) {
while (mLocksHeld) {
UnlockImage();
}
}
}
NS_IMETHODIMP
imgContainerRequest::GetName(nsACString& aName)
{
aName.Truncate();
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
imgContainerRequest::IsPending(PRBool* _retval)
{
*_retval = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::GetStatus(nsresult* aStatus)
{
*aStatus = NS_OK;
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::Cancel(nsresult aStatus)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
imgContainerRequest::Suspend()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
imgContainerRequest::Resume()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
imgContainerRequest::GetLoadGroup(nsILoadGroup** aLoadGroup)
{
*aLoadGroup = nsnull;
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
imgContainerRequest::GetLoadFlags(nsLoadFlags* aLoadFlags)
{
*aLoadFlags = LOAD_NORMAL;
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::SetLoadFlags(nsLoadFlags aLoadFlags)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
imgContainerRequest::GetImage(imgIContainer** aImage)
{
NS_IF_ADDREF(*aImage = mImage);
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::GetImageStatus(PRUint32* aImageStatus)
{
*aImageStatus = mImageStatus;
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::GetURI(nsIURI** aURI)
{
NS_IF_ADDREF(*aURI = mURI);
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::GetDecoderObserver(imgIDecoderObserver** aDecoderObserver)
{
NS_IF_ADDREF(*aDecoderObserver = mObserver);
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::GetMimeType(char** aMimeType)
{
*aMimeType = nsnull;
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::Clone(imgIDecoderObserver* aObserver, imgIRequest** _retval)
{
imgContainerRequest* req =
new imgContainerRequest(mImage, mURI, mImageStatus, mState, mPrincipal);
if (!req) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(*_retval = req);
req->mObserver = aObserver;
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(aObserver);
// Keep these notifications in sync with imgRequest::NotifyProxyListener!
// OnStartRequest
if (req->mState & stateRequestStarted)
aObserver->OnStartRequest(req);
// OnStartContainer
if (req->mState & stateHasSize)
aObserver->OnStartContainer(req, req->mImage);
// OnStartDecode
if (req->mState & stateDecodeStarted)
aObserver->OnStartDecode(req);
// Send frame messages (OnStartFrame, OnDataAvailable, OnStopFrame)
PRUint32 nframes = 0;
if (req->mImage)
req->mImage->GetNumFrames(&nframes);
if (nframes > 0) {
PRUint32 frame;
req->mImage->GetCurrentFrameIndex(&frame);
aObserver->OnStartFrame(req, frame);
// OnDataAvailable
// XXX - Should only send partial rects here, but that needs to
// wait until we fix up the observer interface
nsIntRect r;
req->mImage->GetCurrentFrameRect(r);
aObserver->OnDataAvailable(req, frame, &r);
if (req->mState & stateRequestStopped)
aObserver->OnStopFrame(req, frame);
}
// Reseting image animation isn't needed here.
if (req->mState & stateRequestStopped) {
aObserver->OnStopContainer(req, req->mImage);
aObserver->OnStopDecode(req,
imgRequest::GetResultFromImageStatus(req->mImageStatus),
nsnull);
aObserver->OnStopRequest(req, PR_TRUE);
}
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::GetImagePrincipal(nsIPrincipal** aImagePrincipal)
{
NS_IF_ADDREF(*aImagePrincipal = mPrincipal);
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::CancelAndForgetObserver(nsresult aStatus)
{
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::RequestDecode()
{
return mImage ? mImage->RequestDecode() : NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::LockImage()
{
if (mImage) {
++mLocksHeld;
return mImage->LockImage();
}
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::UnlockImage()
{
if (mImage) {
NS_ABORT_IF_FALSE(mLocksHeld > 0, "calling unlock but no locks!");
--mLocksHeld;
return mImage->UnlockImage();
}
return NS_OK;
}
NS_IMETHODIMP
imgContainerRequest::GetStaticRequest(imgIRequest** aReturn)
{
NS_ADDREF(*aReturn = this);
return NS_OK;
}

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

@ -1,71 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Olli Pettay <Olli.Pettay@helsinki.fi> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef imgContainerRequest_h__
#define imgContainerRequest_h__
#include "imgIRequest.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "nsIPrincipal.h"
#include "nsIURI.h"
class imgContainerRequest : public imgIRequest
{
public:
imgContainerRequest(imgIContainer* aImage,
nsIURI* aURI,
PRUint32 aImageStatus,
PRUint32 aState,
nsIPrincipal* aPrincipal);
virtual ~imgContainerRequest();
NS_DECL_ISUPPORTS
NS_DECL_IMGIREQUEST
NS_DECL_NSIREQUEST
protected:
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<imgIDecoderObserver> mObserver;
PRUint32 mImageStatus;
PRUint32 mState;
PRUint32 mLocksHeld;
};
#endif

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

@ -667,8 +667,11 @@ nsresult imgLoader::CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup
*/
proxyRequest->SetLoadFlags(aLoadFlags);
nsCOMPtr<nsIURI> uri;
aRequest->GetURI(getter_AddRefs(uri));
// init adds itself to imgRequest's list of observers
nsresult rv = proxyRequest->Init(aRequest, aLoadGroup, aObserver);
nsresult rv = proxyRequest->Init(aRequest, aLoadGroup, uri, aObserver);
if (NS_FAILED(rv)) {
NS_RELEASE(proxyRequest);
return rv;
@ -1670,11 +1673,11 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI,
}
// Note that it's OK to add here even if the request is done. If it is,
// it'll send a OnStopRequest() to the proxy in NotifyProxyListener and the
// proxy will be removed from the loadgroup.
// it'll send a OnStopRequest() to the proxy in imgRequestProxy::Notify and
// the proxy will be removed from the loadgroup.
proxy->AddToLoadGroup();
request->NotifyProxyListener(proxy);
proxy->NotifyListener();
return rv;
}
@ -1793,7 +1796,7 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb
rv = CreateNewProxyForRequest(request, loadGroup, aObserver,
requestFlags, nsnull, _retval);
request->NotifyProxyListener(static_cast<imgRequestProxy*>(*_retval));
static_cast<imgRequestProxy*>(*_retval)->NotifyListener();
return rv;
}
@ -2013,7 +2016,7 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport
PRUint32 count = mProxies.Count();
for (PRInt32 i = count-1; i>=0; i--) {
imgRequestProxy *proxy = static_cast<imgRequestProxy *>(mProxies[i]);
mRequest->NotifyProxyListener(proxy);
proxy->NotifyListener();
}
mRequest->SetLoadId(mContext);
@ -2073,7 +2076,7 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport
for (PRInt32 i = count-1; i>=0; i--) {
imgRequestProxy *proxy = static_cast<imgRequestProxy *>(mProxies[i]);
proxy->ChangeOwner(request);
request->NotifyProxyListener(proxy);
proxy->NotifyListener();
}
NS_RELEASE(request);

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

@ -170,7 +170,7 @@ imgRequest::imgRequest() :
mValidator(nsnull), mImageSniffers("image-sniffing-services"),
mDeferredLocks(0), mDecodeRequested(PR_FALSE),
mIsMultiPartChannel(PR_FALSE), mLoading(PR_FALSE),
mHadLastPart(PR_FALSE), mGotData(PR_FALSE), mIsInCache(PR_FALSE)
mGotData(PR_FALSE), mIsInCache(PR_FALSE)
{
/* member initializers and constructor code */
}
@ -205,7 +205,6 @@ nsresult imgRequest::Init(nsIURI *aURI,
if (!mProperties)
return NS_ERROR_OUT_OF_MEMORY;
mURI = aURI;
mKeyURI = aKeyURI;
mRequest = aRequest;
@ -279,6 +278,9 @@ nsresult imgRequest::AddProxy(imgRequestProxy *proxy)
mImage->ResetAnimation();
}
proxy->SetImage(mImage);
proxy->SetPrincipal(mPrincipal);
return mObservers.AppendElementUnlessExists(proxy) ?
NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
@ -360,57 +362,6 @@ nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus, PRBoo
return NS_OK;
}
nsresult imgRequest::NotifyProxyListener(imgRequestProxy *proxy)
{
nsCOMPtr<imgIRequest> kungFuDeathGrip(proxy);
// Keep these notifications in sync with imgContainerRequest::Clone!
// OnStartRequest
if (mState & stateRequestStarted)
proxy->OnStartRequest();
// OnStartContainer
if (mState & stateHasSize)
proxy->OnStartContainer(mImage);
// OnStartDecode
if (mState & stateDecodeStarted)
proxy->OnStartDecode();
// Send frame messages (OnStartFrame, OnDataAvailable, OnStopFrame)
PRUint32 nframes = 0;
if (mImage)
mImage->GetNumFrames(&nframes);
if (nframes > 0) {
PRUint32 frame;
mImage->GetCurrentFrameIndex(&frame);
proxy->OnStartFrame(frame);
// OnDataAvailable
// XXX - Should only send partial rects here, but that needs to
// wait until we fix up the observer interface
nsIntRect r;
mImage->GetCurrentFrameRect(r);
proxy->OnDataAvailable(frame, &r);
if (mState & stateRequestStopped)
proxy->OnStopFrame(frame);
}
// The "real" OnStopDecode - Fix this with bug 505385.
if (mState & stateDecodeStopped)
proxy->OnStopContainer(mImage);
if (mState & stateRequestStopped) {
proxy->OnStopDecode(GetResultFromImageStatus(mImageStatus), nsnull);
proxy->OnStopRequest(mHadLastPart);
}
return NS_OK;
}
void imgRequest::Cancel(nsresult aStatus)
{
/* The Cancel() method here should only be called by this class. */
@ -473,18 +424,6 @@ nsresult imgRequest::GetKeyURI(nsIURI **aKeyURI)
return NS_ERROR_FAILURE;
}
nsresult imgRequest::GetPrincipal(nsIPrincipal **aPrincipal)
{
LOG_FUNC(gImgLog, "imgRequest::GetPrincipal");
if (mPrincipal) {
NS_ADDREF(*aPrincipal = mPrincipal);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
nsresult imgRequest::GetSecurityInfo(nsISupports **aSecurityInfo)
{
LOG_FUNC(gImgLog, "imgRequest::GetSecurityInfo");
@ -577,16 +516,6 @@ void imgRequest::UpdateCacheEntrySize()
}
nsresult
imgRequest::GetImage(imgIContainer **aImage)
{
LOG_FUNC(gImgLog, "imgRequest::GetImage");
*aImage = mImage;
NS_IF_ADDREF(*aImage);
return NS_OK;
}
nsresult
imgRequest::LockImage()
{
@ -908,6 +837,12 @@ NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt
if (NS_FAILED(rv)) {
return rv;
}
// Tell all of our proxies that we have a principal.
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
while (iter.HasMore()) {
iter.GetNext()->SetPrincipal(mPrincipal);
}
}
}
@ -979,14 +914,10 @@ NS_IMETHODIMP imgRequest::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt,
/* set our loading flag to false */
mLoading = PR_FALSE;
mHadLastPart = PR_TRUE;
PRBool lastPart = PR_TRUE;
nsCOMPtr<nsIMultiPartChannel> mpchan(do_QueryInterface(aRequest));
if (mpchan) {
PRBool lastPart;
nsresult rv = mpchan->GetIsLastPart(&lastPart);
if (NS_SUCCEEDED(rv))
mHadLastPart = lastPart;
}
if (mpchan)
mpchan->GetIsLastPart(&lastPart);
// XXXldb What if this is a non-last part of a multipart request?
// xxx before we release our reference to mRequest, lets
@ -1042,7 +973,7 @@ NS_IMETHODIMP imgRequest::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt,
nsTObserverArray<imgRequestProxy*>::ForwardIterator srIter(mObservers);
while (srIter.HasMore()) {
srIter.GetNext()->OnStopRequest(mHadLastPart);
srIter.GetNext()->OnStopRequest(lastPart);
}
return NS_OK;
@ -1214,6 +1145,12 @@ NS_IMETHODIMP imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctx
mImage->LockImage();
mDeferredLocks--;
}
// Tell all of our proxies that we have an image.
nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
while (iter.HasMore()) {
iter.GetNext()->SetImage(mImage);
}
}
// WriteToContainer always consumes everything it gets

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

@ -96,12 +96,11 @@ public:
void *aCacheId,
void *aLoadId);
// Callers must call NotifyProxyListener later.
// Callers must call imgRequestProxy::Notify later.
nsresult AddProxy(imgRequestProxy *proxy);
// aNotify==PR_FALSE still sends OnStopRequest.
nsresult RemoveProxy(imgRequestProxy *proxy, nsresult aStatus, PRBool aNotify);
nsresult NotifyProxyListener(imgRequestProxy *proxy);
void SniffMimeType(const char *buf, PRUint32 len);
@ -115,8 +114,6 @@ public:
// won't be sufficient.
void CancelAndAbort(nsresult aStatus);
nsresult GetImage(imgIContainer **aImage);
// Methods that get forwarded to the imgContainer, or deferred until it's
// instantiated.
nsresult LockImage();
@ -146,7 +143,6 @@ private:
void Cancel(nsresult aStatus);
nsresult GetURI(nsIURI **aURI);
nsresult GetKeyURI(nsIURI **aURI);
nsresult GetPrincipal(nsIPrincipal **aPrincipal);
nsresult GetSecurityInfo(nsISupports **aSecurityInfo);
void RemoveFromCache();
inline const char *GetMimeType() const {
@ -233,7 +229,6 @@ private:
PRPackedBool mIsMultiPartChannel : 1;
PRPackedBool mLoading : 1;
PRPackedBool mHadLastPart : 1;
PRPackedBool mGotData : 1;
PRPackedBool mIsInCache : 1;
};

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

@ -53,20 +53,25 @@
#include "ImageLogging.h"
#include "nspr.h"
#include "imgContainerRequest.h"
NS_IMPL_ISUPPORTS4(imgRequestProxy, imgIRequest, nsIRequest,
nsISupportsPriority, nsISecurityInfoProvider)
imgRequestProxy::imgRequestProxy() :
mOwner(nsnull),
mURI(nsnull),
mImage(nsnull),
mPrincipal(nsnull),
mImageStatus(0),
mState(0),
mListener(nsnull),
mLoadFlags(nsIRequest::LOAD_NORMAL),
mLocksHeld(0),
mCanceled(PR_FALSE),
mIsInLoadGroup(PR_FALSE),
mListenerIsStrongRef(PR_FALSE),
mDecodeRequested(PR_FALSE)
mDecodeRequested(PR_FALSE),
mHadLastPart(PR_FALSE)
{
/* member initializers and constructor code */
@ -107,7 +112,8 @@ imgRequestProxy::~imgRequestProxy()
}
}
nsresult imgRequestProxy::Init(imgRequest *request, nsILoadGroup *aLoadGroup, imgIDecoderObserver *aObserver)
nsresult imgRequestProxy::Init(imgRequest* request, nsILoadGroup* aLoadGroup, nsIURI* aURI,
imgIDecoderObserver* aObserver)
{
NS_PRECONDITION(!mOwner && !mListener, "imgRequestProxy is already initialized");
NS_PRECONDITION(request, "no request");
@ -126,6 +132,7 @@ nsresult imgRequestProxy::Init(imgRequest *request, nsILoadGroup *aLoadGroup, im
NS_ADDREF(mListener);
}
mLoadGroup = aLoadGroup;
mURI = aURI;
// Note: AddProxy won't send all the On* notifications immediately
request->AddProxy(this);
@ -135,6 +142,8 @@ nsresult imgRequestProxy::Init(imgRequest *request, nsILoadGroup *aLoadGroup, im
nsresult imgRequestProxy::ChangeOwner(imgRequest *aNewOwner)
{
NS_PRECONDITION(mOwner, "Cannot ChangeOwner on a proxy without an owner!");
if (mCanceled)
return NS_OK;
@ -207,12 +216,10 @@ void imgRequestProxy::RemoveFromLoadGroup(PRBool releaseLoadGroup)
NS_IMETHODIMP imgRequestProxy::GetName(nsACString &aName)
{
aName.Truncate();
if (mOwner) {
nsCOMPtr<nsIURI> uri;
mOwner->GetURI(getter_AddRefs(uri));
if (uri)
uri->GetSpec(aName);
}
if (mURI)
mURI->GetSpec(aName);
return NS_OK;
}
@ -301,29 +308,25 @@ imgRequestProxy::RequestDecode()
NS_IMETHODIMP
imgRequestProxy::LockImage()
{
if (!mOwner)
if (!mImage)
return NS_ERROR_FAILURE;
// Increment our lock count
mLocksHeld++;
// Forward the request
return mOwner->LockImage();
return mImage->LockImage();
}
/* void unlockImage (); */
NS_IMETHODIMP
imgRequestProxy::UnlockImage()
{
if (!mOwner)
if (!mImage)
return NS_ERROR_FAILURE;
// Decrement our lock count
NS_ABORT_IF_FALSE(mLocksHeld > 0, "calling unlock but no locks!");
mLocksHeld--;
// Forward the request
return mOwner->UnlockImage();
return mImage->UnlockImage();
}
/* void suspend (); */
@ -367,32 +370,42 @@ NS_IMETHODIMP imgRequestProxy::SetLoadFlags(nsLoadFlags flags)
/* attribute imgIContainer image; */
NS_IMETHODIMP imgRequestProxy::GetImage(imgIContainer * *aImage)
{
if (!mOwner)
if (!mImage)
return NS_ERROR_FAILURE;
mOwner->GetImage(aImage);
NS_ADDREF(*aImage = mImage);
return NS_OK;
}
/* readonly attribute unsigned long imageStatus; */
NS_IMETHODIMP imgRequestProxy::GetImageStatus(PRUint32 *aStatus)
{
if (!mOwner) {
if (!mOwner && !mImage) {
*aStatus = imgIRequest::STATUS_ERROR;
return NS_ERROR_FAILURE;
}
*aStatus = mOwner->GetImageStatus();
if (mOwner) {
*aStatus = mOwner->GetImageStatus();
return NS_OK;
}
// If we don't have an owner, we have an image, and have cached the image's
// status.
*aStatus = mImageStatus;
return NS_OK;
}
/* readonly attribute nsIURI URI; */
NS_IMETHODIMP imgRequestProxy::GetURI(nsIURI **aURI)
{
if (!mOwner)
if (!mURI)
return NS_ERROR_FAILURE;
return mOwner->GetURI(aURI);
NS_ADDREF(*aURI = mURI);
return NS_OK;
}
/* readonly attribute imgIDecoderObserver decoderObserver; */
@ -423,11 +436,7 @@ NS_IMETHODIMP imgRequestProxy::Clone(imgIDecoderObserver* aObserver,
{
NS_PRECONDITION(aClone, "Null out param");
*aClone = nsnull;
imgRequestProxy* clone = new imgRequestProxy();
if (!clone) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_ADDREF(clone);
nsRefPtr<imgRequestProxy> clone = new imgRequestProxy();
// It is important to call |SetLoadFlags()| before calling |Init()| because
// |Init()| adds the request to the loadgroup.
@ -436,19 +445,32 @@ NS_IMETHODIMP imgRequestProxy::Clone(imgIDecoderObserver* aObserver,
// XXXldb That's not true anymore. Stuff from imgLoader adds the
// request to the loadgroup.
clone->SetLoadFlags(mLoadFlags);
nsresult rv = clone->Init(mOwner, mLoadGroup, aObserver);
if (NS_FAILED(rv)) {
NS_RELEASE(clone);
nsresult rv = clone->Init(mOwner, mLoadGroup, mURI, aObserver);
if (NS_FAILED(rv))
return rv;
}
// Assign to *aClone before calling NotifyProxyListener so that if
// the caller expects to only be notified for requests it's already
// holding pointers to it won't be surprised.
*aClone = clone;
clone->mHadLastPart = mHadLastPart;
clone->SetImage(mImage);
clone->SetPrincipal(mPrincipal);
// Temporary hack - must be removed in patch to centralize image state tracking.
PRUint32 imageStatus = 0;
GetImageStatus(&imageStatus);
PRUint32 state = 0;
GetState(&state);
clone->mImageStatus = imageStatus;
clone->mState = state;
if (NS_FAILED(rv))
return rv;
// 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.
*aClone = clone.forget().get();
// Send the notifications to the clone's observer
mOwner->NotifyProxyListener(clone);
static_cast<imgRequestProxy*>(*aClone)->NotifyListener();
return NS_OK;
}
@ -456,10 +478,12 @@ NS_IMETHODIMP imgRequestProxy::Clone(imgIDecoderObserver* aObserver,
/* readonly attribute nsIPrincipal imagePrincipal; */
NS_IMETHODIMP imgRequestProxy::GetImagePrincipal(nsIPrincipal **aPrincipal)
{
if (!mOwner)
if (!mPrincipal)
return NS_ERROR_FAILURE;
return mOwner->GetPrincipal(aPrincipal);
NS_ADDREF(*aPrincipal = mPrincipal);
return NS_OK;
}
/** nsISupportsPriority methods **/
@ -610,9 +634,6 @@ void imgRequestProxy::OnDiscard()
}
}
void imgRequestProxy::OnStartRequest()
{
#ifdef PR_LOGGING
@ -642,6 +663,8 @@ void imgRequestProxy::OnStopRequest(PRBool lastPart)
// listener, etc). Don't let them do it.
nsCOMPtr<imgIRequest> kungFuDeathGrip(this);
mHadLastPart = lastPart;
if (mListener) {
// Hold a ref to the listener while we call it, just in case.
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener);
@ -685,20 +708,40 @@ void imgRequestProxy::NullOutListener()
}
}
nsresult imgRequestProxy::GetState(PRUint32 *aState)
{
if (!mOwner && !mImage) {
*aState = 0;
return NS_ERROR_FAILURE;
}
if (mOwner) {
*aState = mOwner->GetState();
return NS_OK;
}
// If we don't have an owner, we have an image, and have cached the image's
// state.
*aState = mState;
return NS_OK;
}
NS_IMETHODIMP
imgRequestProxy::GetStaticRequest(imgIRequest** aReturn)
{
*aReturn = nsnull;
nsCOMPtr<imgIContainer> img, currentFrame;
GetImage(getter_AddRefs(img));
if (img) {
PRBool animated = PR_FALSE;
nsresult rv = img->GetAnimated(&animated);
if (NS_SUCCEEDED(rv) && !animated) {
NS_ADDREF(*aReturn = this);
return NS_OK;
}
nsCOMPtr<imgIContainer> img;
nsCOMPtr<imgIContainer> currentFrame;
GetImage(getter_AddRefs(img));
PRBool animated;
if (img && NS_SUCCEEDED(img->GetAnimated(&animated)) && !animated) {
// Early exit - we're not animated, so we don't have to do anything.
NS_ADDREF(*aReturn = this);
return NS_OK;
} else if (img) {
// We are animated. We need to extract the current frame from this image.
PRInt32 w = 0;
PRInt32 h = 0;
img->GetWidth(&w);
@ -709,22 +752,90 @@ imgRequestProxy::GetStaticRequest(imgIRequest** aReturn)
getter_AddRefs(currentFrame));
}
nsCOMPtr<nsIURI> uri;
GetURI(getter_AddRefs(uri));
// Now, we're creating a static imgRequestProxy, so we have to extract this
// image's status and other ancillary information.
PRUint32 imageStatus = 0;
GetImageStatus(&imageStatus);
nsCOMPtr<nsIPrincipal> principal;
GetImagePrincipal(getter_AddRefs(principal));
PRUint32 state = 0;
GetState(&state);
imgContainerRequest* req =
new imgContainerRequest(currentFrame, uri, imageStatus,
mOwner ? mOwner->GetState() : 0,
principal);
if (!req) {
return NS_ERROR_OUT_OF_MEMORY;
}
imgRequestProxy* req = new imgRequestProxy();
req->Init(nsnull, nsnull, mURI, nsnull);
req->SetImage(currentFrame);
req->SetPrincipal(mPrincipal);
// Temporary hack - must be removed in patch to centralize image state tracking.
req->mImageStatus = imageStatus;
req->mState = state;
NS_ADDREF(*aReturn = req);
return NS_OK;
}
void imgRequestProxy::SetPrincipal(nsIPrincipal *aPrincipal)
{
mPrincipal = aPrincipal;
}
void imgRequestProxy::SetImage(imgIContainer *aImage)
{
mImage = aImage;
}
nsresult imgRequestProxy::NotifyListener()
{
nsCOMPtr<imgIRequest> kungFuDeathGrip(this);
PRUint32 imageStatus = 0;
GetImageStatus(&imageStatus);
PRUint32 state = 0;
GetState(&state);
nsCOMPtr<imgIContainer> image;
GetImage(getter_AddRefs(image));
// OnStartRequest
if (state & stateRequestStarted)
OnStartRequest();
// OnStartContainer
if (state & stateHasSize)
OnStartContainer(image);
// OnStartDecode
if (state & stateDecodeStarted)
OnStartDecode();
// Send frame messages (OnStartFrame, OnDataAvailable, OnStopFrame)
PRUint32 nframes = 0;
if (image)
image->GetNumFrames(&nframes);
if (nframes > 0) {
PRUint32 frame;
image->GetCurrentFrameIndex(&frame);
OnStartFrame(frame);
// OnDataAvailable
// XXX - Should only send partial rects here, but that needs to
// wait until we fix up the observer interface
nsIntRect r;
image->GetCurrentFrameRect(r);
OnDataAvailable(frame, &r);
if (state & stateRequestStopped)
OnStopFrame(frame);
}
// The "real" OnStopDecode - Fix this with bug 505385.
if (state & stateDecodeStopped)
OnStopContainer(image);
if (state & stateRequestStopped) {
OnStopDecode(imgRequest::GetResultFromImageStatus(imageStatus), nsnull);
OnStopRequest(mHadLastPart);
}
return NS_OK;
}

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

@ -73,19 +73,25 @@ public:
imgRequestProxy();
virtual ~imgRequestProxy();
// Callers to Init or ChangeOwner are required to call
// NotifyProxyListener on the request after (although not immediately
// after) doing so.
nsresult Init(imgRequest *request, nsILoadGroup *aLoadGroup, imgIDecoderObserver *aObserver);
// Callers to Init or ChangeOwner are required to call NotifyListener after
// (although not immediately after) doing so.
nsresult Init(imgRequest *request, nsILoadGroup *aLoadGroup, nsIURI* aURI, imgIDecoderObserver *aObserver);
nsresult ChangeOwner(imgRequest *aNewOwner); // this will change mOwner. Do not call this if the previous
// owner has already sent notifications out!
void AddToLoadGroup();
void RemoveFromLoadGroup(PRBool releaseLoadGroup);
// Notify this proxy's listener of the current state of the request.
nsresult NotifyListener();
protected:
friend class imgRequest;
void SetPrincipal(nsIPrincipal *aPrincipal);
void SetImage(imgIContainer *aImage);
class imgCancelRunnable;
friend class imgCancelRunnable;
@ -106,8 +112,6 @@ protected:
nsresult mStatus;
};
/* non-virtual imgIDecoderObserver methods */
void OnStartDecode ();
void OnStartContainer(imgIContainer *aContainer);
@ -138,6 +142,9 @@ protected:
void DoRemoveFromLoadGroup() {
RemoveFromLoadGroup(PR_TRUE);
}
nsresult GetState(PRUint32 *aState);
private:
friend class imgCacheValidator;
@ -149,6 +156,20 @@ private:
// means that imgRequest::mObservers will not have any stale pointers in it.
nsRefPtr<imgRequest> mOwner;
// 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.
nsCOMPtr<imgIContainer> mImage;
// Our principal. Is null until data has been received from the channel, and
// is then set by imgRequest.
nsCOMPtr<nsIPrincipal> mPrincipal;
PRUint32 mImageStatus;
PRUint32 mState;
// 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.
@ -161,4 +182,8 @@ private:
PRPackedBool mIsInLoadGroup;
PRPackedBool mListenerIsStrongRef;
PRPackedBool mDecodeRequested;
// Whether we've seen the last part of the load. For normal,
// non-multipart/x-mixed-replace loads, this is true once OnStopRequest has
// been received.
PRPackedBool mHadLastPart;
};