зеркало из https://github.com/mozilla/pjs.git
Fix GC hazards associated with event handlers on images only reachable from their current network loads, some of which are regressions from 241518. b=321054 r=darin sr=bzbarsky
This commit is contained in:
Родитель
cb1ced946d
Коммит
61dd5c50db
|
@ -67,7 +67,7 @@ public:
|
|||
virtual PRInt32 IntrinsicState() const;
|
||||
|
||||
private:
|
||||
~nsGenConImageContent() {}
|
||||
virtual ~nsGenConImageContent();
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -91,6 +91,11 @@ NS_NewGenConImageContent(nsIContent** aResult, nsINodeInfo* aNodeInfo,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsGenConImageContent::~nsGenConImageContent()
|
||||
{
|
||||
DestroyImageLoadingContent();
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsGenConImageContent::IntrinsicState() const
|
||||
{
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
*/
|
||||
|
||||
#include "nsImageLoadingContent.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsContentErrors.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
|
@ -75,6 +76,7 @@
|
|||
#include "nsIContentPolicy.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
|
||||
#ifdef DEBUG_chb
|
||||
static void PrintReqURL(imgIRequest* req) {
|
||||
|
@ -100,6 +102,7 @@ static void PrintReqURL(imgIRequest* req) {
|
|||
nsImageLoadingContent::nsImageLoadingContent()
|
||||
: mObserverList(nsnull),
|
||||
mImageBlockingStatus(nsIContentPolicy::ACCEPT),
|
||||
mRootRefCount(0),
|
||||
mLoadingEnabled(PR_TRUE),
|
||||
mStartingLoad(PR_FALSE),
|
||||
mLoading(PR_FALSE),
|
||||
|
@ -113,15 +116,37 @@ nsImageLoadingContent::nsImageLoadingContent()
|
|||
}
|
||||
}
|
||||
|
||||
nsImageLoadingContent::~nsImageLoadingContent()
|
||||
void
|
||||
nsImageLoadingContent::DestroyImageLoadingContent()
|
||||
{
|
||||
// Cancel our requests so they won't hold stale refs to us
|
||||
if (mCurrentRequest) {
|
||||
mCurrentRequest->Cancel(NS_ERROR_FAILURE);
|
||||
mCurrentRequest = nsnull;
|
||||
}
|
||||
if (mPendingRequest) {
|
||||
mPendingRequest->Cancel(NS_ERROR_FAILURE);
|
||||
mPendingRequest = nsnull;
|
||||
}
|
||||
|
||||
// This can actually fire for multipart/x-mixed-replace, since if the
|
||||
// load is canceled between parts (e.g., by cancelling the load
|
||||
// group), we won't get any notification. See bug 321054 comment 31
|
||||
// and bug 339610. *If* that multipart/x-mixed-replace image has
|
||||
// event handlers, we won't even get to this warning; we'll leak
|
||||
// instead.
|
||||
NS_WARN_IF_FALSE(mRootRefCount == 0,
|
||||
"unbalanced handler preservation refcount");
|
||||
if (mRootRefCount != 0) {
|
||||
mRootRefCount = 1;
|
||||
UnpreserveLoadHandlers();
|
||||
}
|
||||
}
|
||||
|
||||
nsImageLoadingContent::~nsImageLoadingContent()
|
||||
{
|
||||
NS_ASSERTION(!mCurrentRequest && !mPendingRequest,
|
||||
"DestroyImageLoadingContent not called");
|
||||
NS_ASSERTION(!mObserverList.mObserver && !mObserverList.mNext,
|
||||
"Observers still registered?");
|
||||
}
|
||||
|
@ -155,6 +180,13 @@ nsImageLoadingContent::FrameChanged(imgIContainer* aContainer,
|
|||
/*
|
||||
* imgIDecoderObserver impl
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsImageLoadingContent::OnStartRequest(imgIRequest* aRequest)
|
||||
{
|
||||
LOOP_OVER_OBSERVERS(OnStartRequest(aRequest));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageLoadingContent::OnStartDecode(imgIRequest* aRequest)
|
||||
{
|
||||
|
@ -218,10 +250,14 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest,
|
|||
|
||||
if (aRequest == mPendingRequest) {
|
||||
mCurrentRequest->Cancel(NS_ERROR_IMAGE_SRC_CHANGED);
|
||||
mCurrentRequest = mPendingRequest;
|
||||
mPendingRequest.swap(mCurrentRequest);
|
||||
mPendingRequest = nsnull;
|
||||
}
|
||||
|
||||
// XXXldb What's the difference between when OnStopDecode and OnStopRequest
|
||||
// fire? Should we do this work there instead? Should they just be the
|
||||
// same?
|
||||
|
||||
if (NS_SUCCEEDED(aStatus)) {
|
||||
FireEvent(NS_LITERAL_STRING("load"));
|
||||
} else {
|
||||
|
@ -238,6 +274,17 @@ nsImageLoadingContent::OnStopDecode(imgIRequest* aRequest,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageLoadingContent::OnStopRequest(imgIRequest* aRequest, PRBool aLastPart)
|
||||
{
|
||||
LOOP_OVER_OBSERVERS(OnStopRequest(aRequest, aLastPart));
|
||||
|
||||
if (aLastPart)
|
||||
UnpreserveLoadHandlers();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* nsIImageLoadingContent impl
|
||||
*/
|
||||
|
@ -406,6 +453,8 @@ nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PreserveLoadHandlers();
|
||||
|
||||
// Null out our mCurrentURI, in case we have no image requests right now.
|
||||
mCurrentURI = nsnull;
|
||||
|
||||
|
@ -420,6 +469,9 @@ nsImageLoadingContent::LoadImageWithChannel(nsIChannel* aChannel,
|
|||
// Make sure our state is up to date
|
||||
UpdateImageState(PR_TRUE);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
UnpreserveLoadHandlers();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -432,11 +484,6 @@ nsImageLoadingContent::LoadImage(const nsAString& aNewURI,
|
|||
PRBool aForce,
|
||||
PRBool aNotify)
|
||||
{
|
||||
if (!mLoadingEnabled) {
|
||||
FireEvent(NS_LITERAL_STRING("error"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// First, get a document (needed for security checks and the like)
|
||||
nsIDocument* doc = GetOurDocument();
|
||||
if (!doc) {
|
||||
|
@ -461,6 +508,7 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
|
|||
nsIDocument* aDocument)
|
||||
{
|
||||
if (!mLoadingEnabled) {
|
||||
FireEvent(NS_LITERAL_STRING("error"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -529,6 +577,8 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PreserveLoadHandlers();
|
||||
|
||||
nsCOMPtr<imgIRequest> & req = mCurrentRequest ? mPendingRequest : mCurrentRequest;
|
||||
|
||||
rv = nsContentUtils::LoadImage(aNewURI, aDocument,
|
||||
|
@ -537,6 +587,7 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
|
|||
getter_AddRefs(req));
|
||||
if (NS_FAILED(rv)) {
|
||||
FireEvent(NS_LITERAL_STRING("error"));
|
||||
UnpreserveLoadHandlers();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -677,6 +728,7 @@ nsImageLoadingContent::UseAsPrimaryRequest(imgIRequest* aRequest,
|
|||
NS_PRECONDITION(aRequest, "Must have a request here!");
|
||||
AutoStateChanger changer(this, aNotify);
|
||||
mCurrentURI = nsnull;
|
||||
PreserveLoadHandlers();
|
||||
CancelImageRequests(NS_BINDING_ABORTED, PR_TRUE, nsIContentPolicy::ACCEPT);
|
||||
|
||||
NS_ASSERTION(!mCurrentRequest, "We should not have a current request now");
|
||||
|
@ -722,10 +774,10 @@ nsImageLoadingContent::StringToURI(const nsAString& aSpec,
|
|||
* Class used to dispatch events
|
||||
*/
|
||||
|
||||
class ImageEvent : public nsRunnable
|
||||
class nsImageLoadingContent::Event : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ImageEvent(nsPresContext* aPresContext, nsIContent* aContent,
|
||||
Event(nsPresContext* aPresContext, nsImageLoadingContent* aContent,
|
||||
const nsAString& aMessage, nsIDocument* aDocument)
|
||||
: mPresContext(aPresContext),
|
||||
mContent(aContent),
|
||||
|
@ -733,15 +785,16 @@ public:
|
|||
mDocument(aDocument)
|
||||
{
|
||||
}
|
||||
~ImageEvent()
|
||||
~Event()
|
||||
{
|
||||
mDocument->UnblockOnload(PR_TRUE);
|
||||
mContent->UnpreserveLoadHandlers();
|
||||
}
|
||||
|
||||
NS_IMETHOD Run();
|
||||
|
||||
nsCOMPtr<nsPresContext> mPresContext;
|
||||
nsCOMPtr<nsIContent> mContent;
|
||||
nsRefPtr<nsImageLoadingContent> mContent;
|
||||
nsString mMessage;
|
||||
// Need to hold on to the document in case our event outlives document
|
||||
// teardown... Wantto be able to get back to the document even if the
|
||||
|
@ -750,7 +803,7 @@ public:
|
|||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
ImageEvent::Run()
|
||||
nsImageLoadingContent::Event::Run()
|
||||
{
|
||||
PRUint32 eventMsg;
|
||||
|
||||
|
@ -760,9 +813,11 @@ ImageEvent::Run()
|
|||
eventMsg = NS_IMAGE_ERROR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> ourContent = do_QueryInterface(mContent);
|
||||
|
||||
nsEvent event(PR_TRUE, eventMsg);
|
||||
event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
|
||||
nsEventDispatcher::Dispatch(mContent, mPresContext, &event);
|
||||
nsEventDispatcher::Dispatch(ourContent, mPresContext, &event);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -789,15 +844,46 @@ nsImageLoadingContent::FireEvent(const nsAString& aEventType)
|
|||
nsPresContext *presContext = shell->GetPresContext();
|
||||
NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIContent> ourContent = do_QueryInterface(this);
|
||||
|
||||
nsCOMPtr<nsIRunnable> evt =
|
||||
new ImageEvent(presContext, ourContent, aEventType, document);
|
||||
new nsImageLoadingContent::Event(presContext, this, aEventType, document);
|
||||
NS_ENSURE_TRUE(evt, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Block onload for our event. Since we unblock in the event destructor, we
|
||||
// want to block now, even if posting will fail.
|
||||
document->BlockOnload();
|
||||
PreserveLoadHandlers();
|
||||
|
||||
return NS_DispatchToCurrentThread(evt);
|
||||
}
|
||||
|
||||
void
|
||||
nsImageLoadingContent::PreserveLoadHandlers()
|
||||
{
|
||||
++mRootRefCount;
|
||||
NS_LOG_ADDREF(&mRootRefCount, mRootRefCount,
|
||||
"nsImageLoadingContent::mRootRefCount", sizeof(mRootRefCount));
|
||||
if (mRootRefCount == 1) {
|
||||
nsCOMPtr<nsIDOMGCParticipant> part = do_QueryInterface(this);
|
||||
nsresult rv = nsDOMClassInfo::SetExternallyReferenced(part);
|
||||
// The worst that will happen if we ignore this failure is that
|
||||
// onload or onerror will fail to fire. I suppose we could fire
|
||||
// onerror now as a result of that, but the only reason it would
|
||||
// actually fail is out-of-memory, and it seems silly to bother and
|
||||
// unlikely to work in that case.
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "ignoring failure to root participant");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsImageLoadingContent::UnpreserveLoadHandlers()
|
||||
{
|
||||
NS_ASSERTION(mRootRefCount != 0,
|
||||
"load handler preservation refcount underflow");
|
||||
--mRootRefCount;
|
||||
NS_LOG_RELEASE(&mRootRefCount, mRootRefCount,
|
||||
"nsImageLoadingContent::mRootRefCount");
|
||||
if (mRootRefCount == 0) {
|
||||
nsCOMPtr<nsIDOMGCParticipant> part = do_QueryInterface(this);
|
||||
nsDOMClassInfo::UnsetExternallyReferenced(part);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,6 +136,16 @@ protected:
|
|||
*/
|
||||
nsresult UseAsPrimaryRequest(imgIRequest* aRequest, PRBool aNotify);
|
||||
|
||||
/**
|
||||
* Derived classes of nsImageLoadingContent MUST call
|
||||
* DestroyImageLoadingContent from their destructor, or earlier. It
|
||||
* does things that cannot be done in ~nsImageLoadingContent because
|
||||
* they rely on being able to QueryInterface to other derived classes,
|
||||
* which cannot happen once the derived class destructor has started
|
||||
* calling the base class destructors.
|
||||
*/
|
||||
void DestroyImageLoadingContent();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Struct used to manage the image observers.
|
||||
|
@ -222,6 +232,17 @@ private:
|
|||
* @param aEventType "load" or "error" depending on how things went
|
||||
*/
|
||||
nsresult FireEvent(const nsAString& aEventType);
|
||||
class Event;
|
||||
friend class Event;
|
||||
|
||||
/**
|
||||
* Manage the rooting and un-rooting in nsDOMClassInfo of the content
|
||||
* node, so that things reachable from the node are protected from
|
||||
* garbage collection while the onload or onerror handlers (which can
|
||||
* make it reachable again) could fire.
|
||||
*/
|
||||
void PreserveLoadHandlers();
|
||||
void UnpreserveLoadHandlers();
|
||||
|
||||
/* MEMBERS */
|
||||
protected:
|
||||
|
@ -241,6 +262,12 @@ private:
|
|||
ImageObserver mObserverList;
|
||||
|
||||
PRInt16 mImageBlockingStatus;
|
||||
// This counts the number of operations that we're currently doing
|
||||
// that require us to root in nsDOMClassInfo to say that there is
|
||||
// currently network or other activity that could trigger onload or
|
||||
// onerror handlers. The number of things a single node can do at
|
||||
// once is quite limited, so a PRUint8 should be quite sufficient.
|
||||
PRUint8 mRootRefCount;
|
||||
PRPackedBool mLoadingEnabled : 1;
|
||||
PRPackedBool mStartingLoad : 1;
|
||||
|
||||
|
|
|
@ -289,6 +289,7 @@ nsObjectLoadingContent::nsObjectLoadingContent()
|
|||
|
||||
nsObjectLoadingContent::~nsObjectLoadingContent()
|
||||
{
|
||||
DestroyImageLoadingContent();
|
||||
if (mFrameLoader) {
|
||||
mFrameLoader->Destroy();
|
||||
}
|
||||
|
|
|
@ -184,6 +184,7 @@ nsHTMLImageElement::nsHTMLImageElement(nsINodeInfo *aNodeInfo)
|
|||
|
||||
nsHTMLImageElement::~nsHTMLImageElement()
|
||||
{
|
||||
DestroyImageLoadingContent();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -361,6 +361,7 @@ nsHTMLInputElement::nsHTMLInputElement(nsINodeInfo *aNodeInfo,
|
|||
|
||||
nsHTMLInputElement::~nsHTMLInputElement()
|
||||
{
|
||||
DestroyImageLoadingContent();
|
||||
if (mValue) {
|
||||
nsMemory::Free(mValue);
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ class nsHTMLObjectElement : public nsGenericHTMLFormElement,
|
|||
{
|
||||
public:
|
||||
nsHTMLObjectElement(nsINodeInfo *aNodeInfo, PRBool aFromParser = PR_FALSE);
|
||||
virtual ~nsHTMLObjectElement();
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -126,6 +127,11 @@ nsHTMLObjectElement::nsHTMLObjectElement(nsINodeInfo *aNodeInfo,
|
|||
{
|
||||
}
|
||||
|
||||
nsHTMLObjectElement::~nsHTMLObjectElement()
|
||||
{
|
||||
DestroyImageLoadingContent();
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLObjectElement::IsDoneAddingChildren()
|
||||
{
|
||||
|
|
|
@ -67,6 +67,7 @@ class nsHTMLSharedObjectElement : public nsGenericHTMLElement,
|
|||
public:
|
||||
nsHTMLSharedObjectElement(nsINodeInfo *aNodeInfo,
|
||||
PRBool aFromParser = PR_FALSE);
|
||||
virtual ~nsHTMLSharedObjectElement();
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -165,6 +166,11 @@ nsHTMLSharedObjectElement::nsHTMLSharedObjectElement(nsINodeInfo *aNodeInfo,
|
|||
{
|
||||
}
|
||||
|
||||
nsHTMLSharedObjectElement::~nsHTMLSharedObjectElement()
|
||||
{
|
||||
DestroyImageLoadingContent();
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLSharedObjectElement::IsDoneAddingChildren()
|
||||
{
|
||||
|
|
|
@ -484,6 +484,12 @@ nsImageDocument::ToggleImageSize()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageDocument::OnStartRequest(imgIRequest* aRequest)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageDocument::OnStartDecode(imgIRequest* aRequest)
|
||||
{
|
||||
|
@ -537,6 +543,13 @@ nsImageDocument::OnStopDecode(imgIRequest* aRequest,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageDocument::OnStopRequest(imgIRequest* aRequest,
|
||||
PRBool aLastPart)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageDocument::FrameChanged(imgIContainer* aContainer,
|
||||
gfxIImageFrame* aFrame,
|
||||
|
|
|
@ -68,6 +68,7 @@ protected:
|
|||
friend nsresult NS_NewSVGImageElement(nsIContent **aResult,
|
||||
nsINodeInfo *aNodeInfo);
|
||||
nsSVGImageElement(nsINodeInfo *aNodeInfo);
|
||||
virtual ~nsSVGImageElement();
|
||||
nsresult Init();
|
||||
|
||||
public:
|
||||
|
@ -140,6 +141,11 @@ nsSVGImageElement::nsSVGImageElement(nsINodeInfo *aNodeInfo)
|
|||
{
|
||||
}
|
||||
|
||||
nsSVGImageElement::~nsSVGImageElement()
|
||||
{
|
||||
DestroyImageLoadingContent();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSVGImageElement::Init()
|
||||
{
|
||||
|
|
|
@ -5095,17 +5095,17 @@ nsDOMClassInfo::PreserveWrapper(void *aKey,
|
|||
NS_ASSERTION(!entry->key ||
|
||||
(entry->key == aKey &&
|
||||
entry->keyToWrapperFunc == aKeyToWrapperFunc &&
|
||||
entry->participant == aParticipant &&
|
||||
!entry->rootWhenExternallyReferenced &&
|
||||
!aRootWhenExternallyReferenced),
|
||||
entry->participant == aParticipant),
|
||||
"preservation key already used");
|
||||
|
||||
PRBool wasExternallyReferenced = entry->rootWhenExternallyReferenced;
|
||||
entry->key = aKey;
|
||||
entry->keyToWrapperFunc = aKeyToWrapperFunc;
|
||||
entry->participant = aParticipant;
|
||||
entry->rootWhenExternallyReferenced = aRootWhenExternallyReferenced;
|
||||
entry->rootWhenExternallyReferenced =
|
||||
aRootWhenExternallyReferenced || wasExternallyReferenced;
|
||||
|
||||
if (aRootWhenExternallyReferenced) {
|
||||
if (aRootWhenExternallyReferenced && !wasExternallyReferenced) {
|
||||
if (!sRootWhenExternallyReferencedTable.ops &&
|
||||
!PL_DHashTableInit(&sRootWhenExternallyReferencedTable,
|
||||
PL_DHashGetStubOps(), nsnull,
|
||||
|
@ -5139,7 +5139,8 @@ static nsIXPConnectJSObjectHolder* IdentityKeyToWrapperFunc(void* aKey)
|
|||
|
||||
// static
|
||||
nsresult
|
||||
nsDOMClassInfo::PreserveNodeWrapper(nsIXPConnectWrappedNative *aWrapper)
|
||||
nsDOMClassInfo::PreserveNodeWrapper(nsIXPConnectWrappedNative *aWrapper,
|
||||
PRBool aRootWhenExternallyReferenced)
|
||||
{
|
||||
nsCOMPtr<nsIDOMGCParticipant> participant =
|
||||
do_QueryInterface(aWrapper->Native());
|
||||
|
@ -5148,7 +5149,8 @@ nsDOMClassInfo::PreserveNodeWrapper(nsIXPConnectWrappedNative *aWrapper)
|
|||
return NS_OK;
|
||||
|
||||
return nsDOMClassInfo::PreserveWrapper(aWrapper, IdentityKeyToWrapperFunc,
|
||||
participant, PR_FALSE);
|
||||
participant,
|
||||
aRootWhenExternallyReferenced);
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -6891,6 +6893,14 @@ nsEventReceiverSH::NewResolve(nsIXPConnectWrappedNative *wrapper,
|
|||
JSContext *cx, JSObject *obj, jsval id,
|
||||
PRUint32 flags, JSObject **objp, PRBool *_retval)
|
||||
{
|
||||
if (id == sOnload_id || id == sOnerror_id) {
|
||||
// Pass true for aRootWhenExternallyReferenced, so we make sure that
|
||||
// this node can't go away while waiting for a network load that
|
||||
// could fire an event handler.
|
||||
nsresult rv = nsDOMClassInfo::PreserveNodeWrapper(wrapper, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// If we're assigning to an on* property, we'll register the handler
|
||||
// in our ::SetProperty() hook, so no need to do it here too.
|
||||
if (!JSVAL_IS_STRING(id) || (flags & JSRESOLVE_ASSIGNING)) {
|
||||
|
|
|
@ -203,7 +203,9 @@ public:
|
|||
* The caller need not call |ReleaseWrapper| since the node's
|
||||
* wrapper's scriptable helper does so in its finalize callback.
|
||||
*/
|
||||
static nsresult PreserveNodeWrapper(nsIXPConnectWrappedNative *aWrapper);
|
||||
static nsresult PreserveNodeWrapper(nsIXPConnectWrappedNative *aWrapper,
|
||||
PRBool aRootWhenExternallyReferenced =
|
||||
PR_FALSE);
|
||||
|
||||
/**
|
||||
* Undoes the effects of any prior |PreserveWrapper| calls made with
|
||||
|
|
|
@ -137,6 +137,11 @@ nsImageLoader::Load(imgIRequest *aImage)
|
|||
|
||||
|
||||
|
||||
NS_IMETHODIMP nsImageLoader::OnStartRequest(imgIRequest *aRequest)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageLoader::OnStartDecode(imgIRequest *aRequest)
|
||||
{
|
||||
return NS_OK;
|
||||
|
@ -216,6 +221,12 @@ NS_IMETHODIMP nsImageLoader::OnStopDecode(imgIRequest *aRequest,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageLoader::OnStopRequest(imgIRequest *aRequest,
|
||||
PRBool aLastPart)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageLoader::FrameChanged(imgIContainer *aContainer,
|
||||
gfxIImageFrame *newframe,
|
||||
nsRect * dirtyRect)
|
||||
|
|
|
@ -1775,6 +1775,11 @@ nsBulletListener::~nsBulletListener()
|
|||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsBulletListener::OnStartRequest(imgIRequest *aRequest)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsBulletListener::OnStartDecode(imgIRequest *aRequest)
|
||||
{
|
||||
return NS_OK;
|
||||
|
@ -1827,6 +1832,12 @@ NS_IMETHODIMP nsBulletListener::OnStopDecode(imgIRequest *aRequest,
|
|||
return mFrame->OnStopDecode(aRequest, status, statusArg);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsBulletListener::OnStopRequest(imgIRequest *aRequest,
|
||||
PRBool aLastPart)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsBulletListener::FrameChanged(imgIContainer *aContainer,
|
||||
gfxIImageFrame *newframe,
|
||||
nsRect * dirtyRect)
|
||||
|
|
|
@ -2033,6 +2033,11 @@ nsImageListener::~nsImageListener()
|
|||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageListener::OnStartRequest(imgIRequest *aRequest)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageListener::OnStartDecode(imgIRequest *aRequest)
|
||||
{
|
||||
// Not useful to us yet.
|
||||
|
@ -2089,6 +2094,12 @@ NS_IMETHODIMP nsImageListener::OnStopDecode(imgIRequest *aRequest,
|
|||
return mFrame->OnStopDecode(aRequest, status, statusArg);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageListener::OnStopRequest(imgIRequest *aRequest,
|
||||
PRBool aLastPart)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageListener::FrameChanged(imgIContainer *aContainer,
|
||||
gfxIImageFrame *newframe,
|
||||
nsRect * dirtyRect)
|
||||
|
|
|
@ -531,6 +531,11 @@ nsSVGImageListener::~nsSVGImageListener()
|
|||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSVGImageListener::OnStartRequest(imgIRequest *aRequest)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSVGImageListener::OnStartDecode(imgIRequest *aRequest)
|
||||
{
|
||||
return NS_OK;
|
||||
|
@ -579,6 +584,12 @@ NS_IMETHODIMP nsSVGImageListener::OnStopDecode(imgIRequest *aRequest,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSVGImageListener::OnStopRequest(imgIRequest *aRequest,
|
||||
PRBool aLastPart)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsSVGImageListener::FrameChanged(imgIContainer *aContainer,
|
||||
gfxIImageFrame *newframe,
|
||||
nsRect * dirtyRect)
|
||||
|
|
|
@ -593,6 +593,11 @@ nsImageBoxListener::~nsImageBoxListener()
|
|||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageBoxListener::OnStartRequest(imgIRequest *request)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageBoxListener::OnStartDecode(imgIRequest *request)
|
||||
{
|
||||
return NS_OK;
|
||||
|
@ -645,6 +650,12 @@ NS_IMETHODIMP nsImageBoxListener::OnStopDecode(imgIRequest *request,
|
|||
return mFrame->OnStopDecode(request, status, statusArg);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageBoxListener::OnStopRequest(imgIRequest *request,
|
||||
PRBool lastPart)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsImageBoxListener::FrameChanged(imgIContainer *container,
|
||||
gfxIImageFrame *newframe,
|
||||
nsRect * dirtyRect)
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
class nsImageBoxFrame;
|
||||
|
||||
class nsImageBoxListener : imgIDecoderObserver
|
||||
class nsImageBoxListener : public imgIDecoderObserver
|
||||
{
|
||||
public:
|
||||
nsImageBoxListener();
|
||||
|
|
|
@ -55,6 +55,11 @@ nsTreeImageListener::~nsTreeImageListener()
|
|||
delete mInvalidationArea;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTreeImageListener::OnStartRequest(imgIRequest *aRequest)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTreeImageListener::OnStartDecode(imgIRequest *aRequest)
|
||||
{
|
||||
return NS_OK;
|
||||
|
@ -101,6 +106,12 @@ NS_IMETHODIMP nsTreeImageListener::OnStopDecode(imgIRequest *aRequest,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTreeImageListener::OnStopRequest(imgIRequest *aRequest,
|
||||
PRBool aLastPart)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsTreeImageListener::FrameChanged(imgIContainer *aContainer,
|
||||
gfxIImageFrame *newframe,
|
||||
nsRect * dirtyRect)
|
||||
|
|
|
@ -50,13 +50,28 @@ interface gfxIImageFrame;
|
|||
/**
|
||||
* imgIDecoderObserver interface
|
||||
*
|
||||
* This interface is used both for observing imgIDecoder objects and for
|
||||
* observing imgIRequest objects. In the former case, aRequest is
|
||||
* always null.
|
||||
* XXXldb The two functions should probably be split.
|
||||
*
|
||||
* @author Stuart Parmenter <pavlov@netscape.com>
|
||||
* @version 0.1
|
||||
* @see imagelib2
|
||||
*/
|
||||
[scriptable, uuid(cce7152e-4395-4231-a781-c347c5446cc2)]
|
||||
[scriptable, uuid(876f14ee-f27c-41cd-b6fb-9efda3ebc7b5)]
|
||||
interface imgIDecoderObserver : imgIContainerObserver
|
||||
{
|
||||
/**
|
||||
* called at the same time that nsIRequestObserver::onStartRequest would be
|
||||
* (used only for observers of imgIRequest objects, which are nsIRequests,
|
||||
* not imgIDecoder objects)
|
||||
*
|
||||
* Unlike nsIRequestObserver::onStartRequest, this can be called
|
||||
* synchronously.
|
||||
*/
|
||||
void onStartRequest(in imgIRequest aRequest);
|
||||
|
||||
/**
|
||||
* called as soon as the image begins getting decoded
|
||||
*/
|
||||
|
@ -93,4 +108,14 @@ interface imgIDecoderObserver : imgIContainerObserver
|
|||
void onStopDecode(in imgIRequest aRequest, in nsresult status,
|
||||
in wstring statusArg);
|
||||
|
||||
/**
|
||||
* called at the same time that nsIRequestObserver::onStopRequest would be
|
||||
* (used only for observers of imgIRequest objects, which are nsIRequests,
|
||||
* not imgIDecoder objects)
|
||||
*
|
||||
* Unlike nsIRequestObserver::onStartRequest, this can be called
|
||||
* synchronously.
|
||||
*/
|
||||
void onStopRequest(in imgIRequest aRequest, in boolean aIsLastPart);
|
||||
|
||||
};
|
||||
|
|
|
@ -702,10 +702,8 @@ imgLoader::CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup *aLoadGro
|
|||
(*_retval)->Cancel(NS_IMAGELIB_ERROR_LOAD_ABORTED);
|
||||
NS_RELEASE(*_retval);
|
||||
}
|
||||
// transfer reference to caller
|
||||
*_retval = NS_STATIC_CAST(imgIRequest*, proxyRequest);
|
||||
NS_ADDREF(*_retval);
|
||||
|
||||
NS_RELEASE(proxyRequest);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ NS_IMPL_ISUPPORTS6(imgRequest, imgILoad,
|
|||
|
||||
imgRequest::imgRequest() :
|
||||
mObservers(0),
|
||||
mLoading(PR_FALSE), mProcessing(PR_FALSE),
|
||||
mLoading(PR_FALSE), mProcessing(PR_FALSE), mHadLastPart(PR_FALSE),
|
||||
mImageStatus(imgIRequest::STATUS_NONE), mState(0),
|
||||
mCacheId(0), mValidator(nsnull), mIsMultiPartChannel(PR_FALSE)
|
||||
{
|
||||
|
@ -159,7 +159,7 @@ nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus, PRBoo
|
|||
|
||||
// make sure that observer gets an OnStopRequest message sent to it
|
||||
if (!(mState & onStopRequest)) {
|
||||
proxy->OnStopRequest(nsnull, nsnull, NS_BINDING_ABORTED);
|
||||
proxy->OnStopRequest(nsnull, nsnull, NS_BINDING_ABORTED, PR_TRUE);
|
||||
}
|
||||
|
||||
if (mImage && !HaveProxyWithObserver(nsnull)) {
|
||||
|
@ -198,6 +198,10 @@ nsresult imgRequest::NotifyProxyListener(imgRequestProxy *proxy)
|
|||
{
|
||||
nsCOMPtr<imgIRequest> kungFuDeathGrip(proxy);
|
||||
|
||||
// OnStartRequest
|
||||
if (mState & onStartRequest)
|
||||
proxy->OnStartRequest(nsnull, nsnull);
|
||||
|
||||
// OnStartDecode
|
||||
if (mState & onStartDecode)
|
||||
proxy->OnStartDecode();
|
||||
|
@ -252,7 +256,9 @@ nsresult imgRequest::NotifyProxyListener(imgRequestProxy *proxy)
|
|||
}
|
||||
|
||||
if (mState & onStopRequest) {
|
||||
proxy->OnStopRequest(nsnull, nsnull, GetResultFromImageStatus(mImageStatus));
|
||||
proxy->OnStopRequest(nsnull, nsnull,
|
||||
GetResultFromImageStatus(mImageStatus),
|
||||
mHadLastPart);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -439,6 +445,12 @@ NS_IMETHODIMP imgRequest::OnStartDecode(imgIRequest *request)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP imgRequest::OnStartRequest(imgIRequest *aRequest)
|
||||
{
|
||||
NS_NOTREACHED("imgRequest(imgIDecoderObserver)::OnStartRequest");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* void onStartContainer (in imgIRequest request, in imgIContainer image); */
|
||||
NS_IMETHODIMP imgRequest::OnStartContainer(imgIRequest *request, imgIContainer *image)
|
||||
{
|
||||
|
@ -597,6 +609,12 @@ NS_IMETHODIMP imgRequest::OnStopDecode(imgIRequest *aRequest,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP imgRequest::OnStopRequest(imgIRequest *aRequest,
|
||||
PRBool aLastPart)
|
||||
{
|
||||
NS_NOTREACHED("imgRequest(imgIDecoderObserver)::OnStopRequest");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** nsIRequestObserver methods **/
|
||||
|
||||
|
@ -613,9 +631,10 @@ NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt
|
|||
if (mpchan)
|
||||
mIsMultiPartChannel = PR_TRUE;
|
||||
|
||||
/* set our state variables to their initial values. */
|
||||
/* set our state variables to their initial values, but advance mState
|
||||
to onStartRequest. */
|
||||
mImageStatus = imgIRequest::STATUS_NONE;
|
||||
mState = 0;
|
||||
mState = onStartRequest;
|
||||
|
||||
/* set our loading flag to true */
|
||||
mLoading = PR_TRUE;
|
||||
|
@ -707,6 +726,16 @@ NS_IMETHODIMP imgRequest::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt,
|
|||
/* set our processing flag to false */
|
||||
mProcessing = PR_FALSE;
|
||||
|
||||
mHadLastPart = PR_TRUE;
|
||||
nsCOMPtr<nsIMultiPartChannel> mpchan(do_QueryInterface(aRequest));
|
||||
if (mpchan) {
|
||||
PRBool lastPart;
|
||||
nsresult rv = mpchan->GetIsLastPart(&lastPart);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
mHadLastPart = lastPart;
|
||||
}
|
||||
|
||||
// XXXldb What if this is a non-last part of a multipart request?
|
||||
mRequest = nsnull; // we no longer need the request
|
||||
|
||||
// If mImage is still null, we didn't properly load the image.
|
||||
|
@ -735,7 +764,7 @@ NS_IMETHODIMP imgRequest::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt,
|
|||
/* calling OnStopRequest may result in the death of |proxy| so don't use the
|
||||
pointer after this call.
|
||||
*/
|
||||
if (proxy) proxy->OnStopRequest(aRequest, ctxt, status);
|
||||
if (proxy) proxy->OnStopRequest(aRequest, ctxt, status, mHadLastPart);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -62,11 +62,12 @@ class imgCacheValidator;
|
|||
class imgRequestProxy;
|
||||
|
||||
enum {
|
||||
onStartDecode = PR_BIT(0),
|
||||
onStartContainer = PR_BIT(1),
|
||||
onStopContainer = PR_BIT(2),
|
||||
onStopDecode = PR_BIT(3),
|
||||
onStopRequest = PR_BIT(4)
|
||||
onStartRequest = PR_BIT(0),
|
||||
onStartDecode = PR_BIT(1),
|
||||
onStartContainer = PR_BIT(2),
|
||||
onStopContainer = PR_BIT(3),
|
||||
onStopDecode = PR_BIT(4),
|
||||
onStopRequest = PR_BIT(5)
|
||||
};
|
||||
|
||||
class imgRequest : public imgILoad,
|
||||
|
@ -86,7 +87,11 @@ public:
|
|||
void *aCacheId,
|
||||
void *aLoadId);
|
||||
|
||||
// Callers that pass aNotify==PR_FALSE must call NotifyProxyListener
|
||||
// later.
|
||||
nsresult AddProxy (imgRequestProxy *proxy, PRBool aNotify);
|
||||
|
||||
// aNotify==PR_FALSE still sends OnStopRequest.
|
||||
nsresult RemoveProxy(imgRequestProxy *proxy, nsresult aStatus, PRBool aNotify);
|
||||
nsresult NotifyProxyListener(imgRequestProxy *proxy);
|
||||
|
||||
|
@ -149,6 +154,7 @@ private:
|
|||
|
||||
PRPackedBool mLoading;
|
||||
PRPackedBool mProcessing;
|
||||
PRPackedBool mHadLastPart;
|
||||
|
||||
PRUint32 mImageStatus;
|
||||
PRUint32 mState;
|
||||
|
|
|
@ -73,21 +73,22 @@ imgRequestProxy::~imgRequestProxy()
|
|||
{
|
||||
/* destructor code */
|
||||
NS_PRECONDITION(!mListener, "Someone forgot to properly cancel this request!");
|
||||
// Explicitly set mListener to null to ensure that the RemoveProxy
|
||||
// call below can't send |this| to an arbitrary listener while |this|
|
||||
// is being destroyed.
|
||||
mListener = nsnull;
|
||||
|
||||
if (mOwner) {
|
||||
if (!mCanceled) {
|
||||
mCanceled = PR_TRUE;
|
||||
|
||||
/* set mListener to null so that we don't forward any callbacks that
|
||||
RemoveProxy might generate
|
||||
*/
|
||||
mListener = nsnull;
|
||||
|
||||
|
||||
/* Call RemoveProxy with a successful status. This will keep the
|
||||
channel, if still downloading data, from being canceled if 'this' is
|
||||
the last observer. This allows the image to continue to download and
|
||||
be cached even if no one is using it currently.
|
||||
|
||||
Passing false to aNotify means that we will still get
|
||||
OnStopRequest, if needed.
|
||||
*/
|
||||
mOwner->RemoveProxy(this, NS_OK, PR_FALSE);
|
||||
}
|
||||
|
@ -123,6 +124,8 @@ nsresult imgRequestProxy::ChangeOwner(imgRequest *aNewOwner)
|
|||
if (mCanceled)
|
||||
return NS_OK;
|
||||
|
||||
// Passing false to aNotify means that mListener will still get
|
||||
// OnStopRequest, if needed.
|
||||
mOwner->RemoveProxy(this, NS_IMAGELIB_CHANGING_OWNER, PR_FALSE);
|
||||
NS_RELEASE(mOwner);
|
||||
|
||||
|
@ -202,10 +205,13 @@ NS_IMETHODIMP imgRequestProxy::Cancel(nsresult status)
|
|||
LOG_SCOPE(gImgLog, "imgRequestProxy::Cancel");
|
||||
|
||||
mCanceled = PR_TRUE;
|
||||
mListener = nsnull;
|
||||
|
||||
// Passing false to aNotify means that mListener will still get
|
||||
// OnStopRequest, if needed.
|
||||
mOwner->RemoveProxy(this, status, PR_FALSE);
|
||||
|
||||
mListener = nsnull;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -314,6 +320,10 @@ NS_IMETHODIMP imgRequestProxy::Clone(imgIDecoderObserver* aObserver,
|
|||
|
||||
// It is important to call |SetLoadFlags()| before calling |Init()| because
|
||||
// |Init()| adds the request to the loadgroup.
|
||||
// When a request is added to a loadgroup, its load flags are merged
|
||||
// with the load flags of the loadgroup.
|
||||
// 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)) {
|
||||
|
@ -456,9 +466,16 @@ void imgRequestProxy::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
|
|||
GetName(name);
|
||||
LOG_FUNC_WITH_PARAM(gImgLog, "imgRequestProxy::OnStartRequest", "name", name.get());
|
||||
#endif
|
||||
|
||||
if (mListener) {
|
||||
// Hold a ref to the listener while we call it, just in case.
|
||||
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener);
|
||||
mListener->OnStartRequest(this);
|
||||
}
|
||||
}
|
||||
|
||||
void imgRequestProxy::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult statusCode)
|
||||
void imgRequestProxy::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
|
||||
nsresult statusCode, PRBool lastPart)
|
||||
{
|
||||
#ifdef PR_LOGGING
|
||||
nsCAutoString name;
|
||||
|
@ -466,16 +483,14 @@ void imgRequestProxy::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsre
|
|||
LOG_FUNC_WITH_PARAM(gImgLog, "imgRequestProxy::OnStopRequest", "name", name.get());
|
||||
#endif
|
||||
|
||||
// If we're expecting more data from a multipart channel, re-add ourself
|
||||
// to the loadgroup so that the document doesn't lose track of the load.
|
||||
PRBool lastPart = PR_TRUE;
|
||||
if (mOwner->mIsMultiPartChannel) {
|
||||
nsCOMPtr<nsIMultiPartChannel> mpc = do_QueryInterface(request);
|
||||
if (mpc) {
|
||||
mpc->GetIsLastPart(&lastPart);
|
||||
}
|
||||
if (mListener) {
|
||||
// Hold a ref to the listener while we call it, just in case.
|
||||
nsCOMPtr<imgIDecoderObserver> kungFuDeathGrip(mListener);
|
||||
mListener->OnStopRequest(this, lastPart);
|
||||
}
|
||||
|
||||
// If we're expecting more data from a multipart channel, re-add ourself
|
||||
// to the loadgroup so that the document doesn't lose track of the load.
|
||||
// If the request is already a background request and there's more data
|
||||
// coming, we can just leave the request in the loadgroup as-is.
|
||||
if (lastPart || (mLoadFlags & nsIRequest::LOAD_BACKGROUND) == 0) {
|
||||
|
|
|
@ -69,7 +69,9 @@ public:
|
|||
imgRequestProxy();
|
||||
virtual ~imgRequestProxy();
|
||||
|
||||
/* additional members */
|
||||
// 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);
|
||||
nsresult ChangeOwner(imgRequest *aNewOwner); // this will change mOwner. Do not call this if the previous
|
||||
// owner has already sent notifications out!
|
||||
|
@ -81,7 +83,7 @@ protected:
|
|||
friend class imgRequest;
|
||||
|
||||
/* non-virtual imgIDecoderObserver methods */
|
||||
void OnStartDecode (void);
|
||||
void OnStartDecode ();
|
||||
void OnStartContainer(imgIContainer *aContainer);
|
||||
void OnStartFrame (gfxIImageFrame *aFrame);
|
||||
void OnDataAvailable (gfxIImageFrame *aFrame, const nsIntRect * aRect);
|
||||
|
@ -92,9 +94,9 @@ protected:
|
|||
/* non-virtual imgIContainerObserver methods */
|
||||
void FrameChanged(imgIContainer *aContainer, gfxIImageFrame *aFrame, nsIntRect * aDirtyRect);
|
||||
|
||||
/* non-virtual nsIRequestObserver methods */
|
||||
/* non-virtual nsIRequestObserver (plus some) methods */
|
||||
void OnStartRequest(nsIRequest *request, nsISupports *ctxt);
|
||||
void OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult statusCode);
|
||||
void OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult statusCode, PRBool aLastPart);
|
||||
|
||||
inline PRBool HasObserver() const {
|
||||
return mListener != nsnull;
|
||||
|
|
Загрузка…
Ссылка в новой задаче