From 2fa16f5738310b10a9c18a694ea042451d3caa9c Mon Sep 17 00:00:00 2001 From: "pavlov%netscape.com" Date: Fri, 13 Apr 2001 02:42:56 +0000 Subject: [PATCH] fix for at least bugs 6074,72087,74506,75190,75180,74165,69857,75576,75326,75417,75474 r=waterson, sr=brendan git-svn-id: svn://10.0.0.236/trunk@92152 18797224-902f-48f8-a5cc-f745e15eee43 --- .../libpr0n/decoders/jpeg/nsJPEGDecoder.cpp | 81 +++- mozilla/modules/libpr0n/public/MANIFEST_IDL | 1 + mozilla/modules/libpr0n/public/Makefile.in | 3 +- mozilla/modules/libpr0n/public/makefile.win | 1 + mozilla/modules/libpr0n/src/DummyChannel.cpp | 116 ------ mozilla/modules/libpr0n/src/DummyChannel.h | 51 --- mozilla/modules/libpr0n/src/ImageFactory.cpp | 10 +- mozilla/modules/libpr0n/src/Makefile.in | 3 +- .../src/{ImageCache.cpp => imgCache.cpp} | 140 +++++-- .../libpr0n/src/{ImageCache.h => imgCache.h} | 44 +- mozilla/modules/libpr0n/src/imgLoader.cpp | 201 +++++++-- mozilla/modules/libpr0n/src/imgLoader.h | 32 ++ mozilla/modules/libpr0n/src/imgRequest.cpp | 386 ++++++++---------- mozilla/modules/libpr0n/src/imgRequest.h | 23 +- .../modules/libpr0n/src/imgRequestProxy.cpp | 148 ++++--- mozilla/modules/libpr0n/src/imgRequestProxy.h | 5 +- mozilla/modules/libpr0n/src/makefile.win | 3 +- 17 files changed, 679 insertions(+), 569 deletions(-) delete mode 100644 mozilla/modules/libpr0n/src/DummyChannel.cpp delete mode 100644 mozilla/modules/libpr0n/src/DummyChannel.h rename mozilla/modules/libpr0n/src/{ImageCache.cpp => imgCache.cpp} (52%) rename mozilla/modules/libpr0n/src/{ImageCache.h => imgCache.h} (70%) diff --git a/mozilla/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp b/mozilla/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp index 389c693ae31..23d947ff6c1 100644 --- a/mozilla/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp +++ b/mozilla/modules/libpr0n/decoders/jpeg/nsJPEGDecoder.cpp @@ -122,9 +122,6 @@ NS_IMETHODIMP nsJPEGDecoder::Init(imgIRequest *aRequest) mRequest = aRequest; mObserver = do_QueryInterface(mRequest); - mImage = do_CreateInstance("@mozilla.org/image/container;1"); - aRequest->SetImage(mImage); - /* We set up the normal JPEG error routines, then override error_exit. */ mInfo.err = jpeg_std_error(&mErr.pub); /* mInfo.err = jpeg_std_error(&mErr.pub); */ @@ -161,8 +158,6 @@ NS_IMETHODIMP nsJPEGDecoder::Init(imgIRequest *aRequest) src->decoder = this; - - return NS_OK; } @@ -279,20 +274,68 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR mObserver->OnStartDecode(nsnull, nsnull); - mImage->Init(mInfo.image_width, mInfo.image_height, mObserver); + + /* Check if the request already has an image container. + this is the case when multipart/x-mixed-replace is being downloaded + if we already have one and it has the same width and height, reuse it. + */ + mRequest->GetImage(getter_AddRefs(mImage)); + if (mImage) { + PRInt32 width, height; + mImage->GetWidth(&width); + mImage->GetHeight(&height); + if ((width != (PRInt32)mInfo.image_width) || + (height != (PRInt32)mInfo.image_height)) { + mImage = nsnull; + } + } + + if (!mImage) { + mImage = do_CreateInstance("@mozilla.org/image/container;1"); + if (!mImage) { + mState = JPEG_ERROR; + return NS_ERROR_OUT_OF_MEMORY; + } + mRequest->SetImage(mImage); + mImage->Init(mInfo.image_width, mInfo.image_height, mObserver); + } + mObserver->OnStartContainer(nsnull, nsnull, mImage); - mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2"); - gfx_format format; -#ifdef XP_PC - format = gfxIFormats::BGR; -#else - format = gfxIFormats::RGB; -#endif - mFrame->Init(0, 0, mInfo.image_width, mInfo.image_height, format); - mImage->AppendFrame(mFrame); - mObserver->OnStartFrame(nsnull, nsnull, mFrame); + mImage->GetFrameAt(0, getter_AddRefs(mFrame)); + PRBool createNewFrame = PR_TRUE; + + if (mFrame) { + PRInt32 width, height; + mFrame->GetWidth(&width); + mFrame->GetHeight(&height); + + if ((width == (PRInt32)mInfo.image_width) && + (height == (PRInt32)mInfo.image_height)) { + createNewFrame = PR_FALSE; + } else { + mImage->Clear(); + } + } + + if (createNewFrame) { + mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2"); + if (!mFrame) { + mState = JPEG_ERROR; + return NS_ERROR_OUT_OF_MEMORY; + } + + gfx_format format = gfxIFormats::RGB; +#ifdef XP_PC + format = gfxIFormats::BGR; +#endif + + mFrame->Init(0, 0, mInfo.image_width, mInfo.image_height, format); + mImage->AppendFrame(mFrame); + } + + mObserver->OnStartFrame(nsnull, nsnull, mFrame); /* * Make a one-row-high sample array that will go away @@ -439,6 +482,12 @@ NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PR ("[this=%p] nsJPEGDecoder::WriteFrom -- entering JPEG_SINK_NON_JPEG_TRAILER case\n", this)); break; + + case JPEG_ERROR: + PR_LOG(gJPEGlog, PR_LOG_DEBUG, + ("[this=%p] nsJPEGDecoder::WriteFrom -- entering JPEG_ERROR case\n", this)); + + break; } return NS_OK; diff --git a/mozilla/modules/libpr0n/public/MANIFEST_IDL b/mozilla/modules/libpr0n/public/MANIFEST_IDL index d47fc51ab2d..ee3fc6bf9db 100644 --- a/mozilla/modules/libpr0n/public/MANIFEST_IDL +++ b/mozilla/modules/libpr0n/public/MANIFEST_IDL @@ -1,3 +1,4 @@ +imgICache.idl imgIContainer.idl imgIContainerObserver.idl imgIDecoder.idl diff --git a/mozilla/modules/libpr0n/public/Makefile.in b/mozilla/modules/libpr0n/public/Makefile.in index a85f559636d..8e1685c4285 100644 --- a/mozilla/modules/libpr0n/public/Makefile.in +++ b/mozilla/modules/libpr0n/public/Makefile.in @@ -30,7 +30,8 @@ MODULE = imglib2 EXPORTS = ImageLogging.h -XPIDLSRCS = imgIContainer.idl \ +XPIDLSRCS = imgICache.idl \ + imgIContainer.idl \ imgIContainerObserver.idl \ imgIDecoder.idl \ imgIDecoderObserver.idl \ diff --git a/mozilla/modules/libpr0n/public/makefile.win b/mozilla/modules/libpr0n/public/makefile.win index fdf1e57e7a8..bbbb40809d3 100644 --- a/mozilla/modules/libpr0n/public/makefile.win +++ b/mozilla/modules/libpr0n/public/makefile.win @@ -30,6 +30,7 @@ XPIDL_MODULE = imglib2 EXPORTS = ImageLogging.h XPIDLSRCS = \ + .\imgICache.idl \ .\imgIContainer.idl \ .\imgIContainerObserver.idl \ .\imgIDecoder.idl \ diff --git a/mozilla/modules/libpr0n/src/DummyChannel.cpp b/mozilla/modules/libpr0n/src/DummyChannel.cpp deleted file mode 100644 index cdcf2f00cba..00000000000 --- a/mozilla/modules/libpr0n/src/DummyChannel.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * 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 Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 2001 Netscape Communications Corporation. - * All Rights Reserved. - * - * Contributor(s): - * Stuart Parmenter - */ - -#include "DummyChannel.h" - -#include "nsCOMPtr.h" -#include "nsIServiceManager.h" - - -NS_IMPL_ISUPPORTS1(DummyChannel, nsIChannel) - -DummyChannel::DummyChannel(imgIRequest *aRequest, nsILoadGroup *aLoadGroup) : - mRequest(aRequest) -{ - NS_INIT_ISUPPORTS(); - /* member initializers and constructor code */ -} - -DummyChannel::~DummyChannel() -{ - /* destructor code */ -} - -/* attribute nsIURI originalURI; */ -NS_IMETHODIMP DummyChannel::GetOriginalURI(nsIURI * *aOriginalURI) -{ - return mRequest->GetURI(aOriginalURI); -} -NS_IMETHODIMP DummyChannel::SetOriginalURI(nsIURI * aOriginalURI) -{ - return NS_ERROR_FAILURE; -} - -/* attribute nsIURI URI; */ -NS_IMETHODIMP DummyChannel::GetURI(nsIURI * *aURI) -{ - return mRequest->GetURI(aURI); -} - -/* attribute nsISupports owner; */ -NS_IMETHODIMP DummyChannel::GetOwner(nsISupports * *aOwner) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} -NS_IMETHODIMP DummyChannel::SetOwner(nsISupports * aOwner) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -/* attribute nsIInterfaceRequestor notificationCallbacks; */ -NS_IMETHODIMP DummyChannel::GetNotificationCallbacks(nsIInterfaceRequestor * *aNotificationCallbacks) -{ - return NS_OK; -} -NS_IMETHODIMP DummyChannel::SetNotificationCallbacks(nsIInterfaceRequestor * aNotificationCallbacks) -{ - return NS_OK; -} - -/* readonly attribute nsISupports securityInfo; */ -NS_IMETHODIMP DummyChannel::GetSecurityInfo(nsISupports * *aSecurityInfo) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -/* attribute string contentType; */ -NS_IMETHODIMP DummyChannel::GetContentType(char * *aContentType) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} -NS_IMETHODIMP DummyChannel::SetContentType(const char * aContentType) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -/* attribute long contentLength; */ -NS_IMETHODIMP DummyChannel::GetContentLength(PRInt32 *aContentLength) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} -NS_IMETHODIMP DummyChannel::SetContentLength(PRInt32 aContentLength) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -/* nsIInputStream open (); */ -NS_IMETHODIMP DummyChannel::Open(nsIInputStream **_retval) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -/* void asyncOpen (in nsIStreamListener listener, in nsISupports ctxt); */ -NS_IMETHODIMP DummyChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} diff --git a/mozilla/modules/libpr0n/src/DummyChannel.h b/mozilla/modules/libpr0n/src/DummyChannel.h deleted file mode 100644 index 67eb05c7d93..00000000000 --- a/mozilla/modules/libpr0n/src/DummyChannel.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * 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 Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 2001 Netscape Communications Corporation. - * All Rights Reserved. - * - * Contributor(s): - * Stuart Parmenter - */ - -#ifndef DummyChannel_h__ -#define DummyChannel_h__ - -#include "nsIChannel.h" -#include "nsIRequest.h" -#include "nsILoadGroup.h" - -#include "imgIRequest.h" - -#include "nsCOMPtr.h" - -class DummyChannel : public nsIChannel -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSICHANNEL - NS_FORWARD_NSIREQUEST(mRequest->) - - DummyChannel(imgIRequest *aRequest, nsILoadGroup *aLoadGroup); - ~DummyChannel(); - -private: - /* additional members */ - nsCOMPtr mRequest; -}; - -#endif - diff --git a/mozilla/modules/libpr0n/src/ImageFactory.cpp b/mozilla/modules/libpr0n/src/ImageFactory.cpp index 564f980ce3d..fe904499b65 100644 --- a/mozilla/modules/libpr0n/src/ImageFactory.cpp +++ b/mozilla/modules/libpr0n/src/ImageFactory.cpp @@ -24,15 +24,15 @@ #include "nsIGenericFactory.h" #include "nsIModule.h" +#include "imgCache.h" #include "imgContainer.h" #include "imgLoader.h" #include "imgRequest.h" #include "imgRequestProxy.h" -#include "ImageCache.h" - // objects that just require generic constructors +NS_GENERIC_FACTORY_CONSTRUCTOR(imgCache) NS_GENERIC_FACTORY_CONSTRUCTOR(imgContainer) NS_GENERIC_FACTORY_CONSTRUCTOR(imgLoader) NS_GENERIC_FACTORY_CONSTRUCTOR(imgRequest) @@ -40,6 +40,10 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(imgRequestProxy) static nsModuleComponentInfo components[] = { + { "image cache", + NS_IMGCACHE_CID, + "@mozilla.org/image/cache;1", + imgCacheConstructor, }, { "image container", NS_IMGCONTAINER_CID, "@mozilla.org/image/container;1", @@ -61,7 +65,7 @@ static nsModuleComponentInfo components[] = PR_STATIC_CALLBACK(void) ImageModuleDestructor(nsIModule *self) { - ImageCache::Shutdown(); + imgCache::Shutdown(); } NS_IMPL_NSGETMODULE_WITH_DTOR("nsImageLib2Module", components, ImageModuleDestructor) diff --git a/mozilla/modules/libpr0n/src/Makefile.in b/mozilla/modules/libpr0n/src/Makefile.in index bd1f1a51f34..fe6455a2d91 100644 --- a/mozilla/modules/libpr0n/src/Makefile.in +++ b/mozilla/modules/libpr0n/src/Makefile.in @@ -33,9 +33,8 @@ IS_COMPONENT = 1 REQUIRES = xpcom string necko nkcache layout timer gfx2 CPPSRCS = \ - DummyChannel.cpp \ - ImageCache.cpp \ ImageFactory.cpp \ + imgCache.cpp \ imgContainer.cpp \ imgLoader.cpp \ imgRequest.cpp \ diff --git a/mozilla/modules/libpr0n/src/ImageCache.cpp b/mozilla/modules/libpr0n/src/imgCache.cpp similarity index 52% rename from mozilla/modules/libpr0n/src/ImageCache.cpp rename to mozilla/modules/libpr0n/src/imgCache.cpp index 3fb3a71a769..86302f77b60 100644 --- a/mozilla/modules/libpr0n/src/ImageCache.cpp +++ b/mozilla/modules/libpr0n/src/imgCache.cpp @@ -21,18 +21,19 @@ * Stuart Parmenter */ -#include "ImageCache.h" +#include "imgCache.h" #ifdef MOZ_NEW_CACHE #include "prlog.h" - #if defined(PR_LOGGING) extern PRLogModuleInfo *gImgLog; #else #define gImgLog #endif +#include "imgRequest.h" + #include "nsXPIDLString.h" #include "nsCOMPtr.h" #include "nsIServiceManager.h" @@ -42,56 +43,113 @@ extern PRLogModuleInfo *gImgLog; #include "nsICacheSession.h" #include "nsICacheEntryDescriptor.h" -static nsCOMPtr gSession = nsnull; +#endif /* MOZ_NEW_CACHE */ -ImageCache::ImageCache() +NS_IMPL_ISUPPORTS1(imgCache, imgICache) + +imgCache::imgCache() { + NS_INIT_ISUPPORTS(); /* member initializers and constructor code */ } -ImageCache::~ImageCache() +imgCache::~imgCache() { /* destructor code */ } -void GetCacheSession(nsICacheSession **_retval) +/* void clearCache (in boolean chrome); */ +NS_IMETHODIMP imgCache::ClearCache(PRBool chrome) { - if (!gSession) { - nsCOMPtr cacheService(do_GetService("@mozilla.org/network/cache-service;1")); - if (!cacheService) { - NS_WARNING("Unable to get the cache service"); - return; - } + if (chrome) + return imgCache::ClearChromeImageCache(); + else + return imgCache::ClearImageCache(); +} - cacheService->CreateSession("images", nsICache::NOT_STREAM_BASED, PR_FALSE, getter_AddRefs(gSession)); - if (!gSession) { - NS_WARNING("Unable to create a cache session"); - return; - } +#ifdef MOZ_NEW_CACHE + +static nsCOMPtr gSession = nsnull; +static nsCOMPtr gChromeSession = nsnull; + +void GetCacheSession(nsIURI *aURI, nsICacheSession **_retval) +{ + NS_ASSERTION(aURI, "Null URI!"); + + PRBool isChrome = PR_FALSE; + aURI->SchemeIs("chrome", &isChrome); + + if (gSession && !isChrome) { + *_retval = gSession; + NS_ADDREF(*_retval); + return; } - *_retval = gSession; - NS_IF_ADDREF(*_retval); + if (gChromeSession && isChrome) { + *_retval = gChromeSession; + NS_ADDREF(*_retval); + return; + } + + nsCOMPtr cacheService(do_GetService("@mozilla.org/network/cache-service;1")); + if (!cacheService) { + NS_WARNING("Unable to get the cache service"); + return; + } + + nsCOMPtr newSession; + cacheService->CreateSession(isChrome ? "image-chrome" : "image", + nsICache::NOT_STREAM_BASED, + PR_FALSE, getter_AddRefs(newSession)); + + if (!newSession) { + NS_WARNING("Unable to create a cache session"); + return; + } + + if (isChrome) + gChromeSession = newSession; + else + gSession = newSession; + + *_retval = newSession; + NS_ADDREF(*_retval); } -void ImageCache::Shutdown() +void imgCache::Shutdown() { gSession = nsnull; + gChromeSession = nsnull; } -PRBool ImageCache::Put(nsIURI *aKey, imgRequest *request, nsICacheEntryDescriptor **aEntry) + +nsresult imgCache::ClearChromeImageCache() +{ + if (!gChromeSession) + return NS_OK; + + return gChromeSession->EvictEntries(); +} + +nsresult imgCache::ClearImageCache() +{ + if (!gSession) + return NS_OK; + + return gSession->EvictEntries(); +} + +PRBool imgCache::Put(nsIURI *aKey, imgRequest *request, nsICacheEntryDescriptor **aEntry) { PR_LOG(gImgLog, PR_LOG_DEBUG, - ("ImageCache::Put\n")); + ("imgCache::Put\n")); nsresult rv; nsCOMPtr ses; - GetCacheSession(getter_AddRefs(ses)); - - if (!ses) - return PR_FALSE; + GetCacheSession(aKey, getter_AddRefs(ses)); + if (!ses) return PR_FALSE; nsXPIDLCString spec; aKey->GetSpec(getter_Copies(spec)); @@ -100,10 +158,11 @@ PRBool ImageCache::Put(nsIURI *aKey, imgRequest *request, nsICacheEntryDescripto rv = ses->OpenCacheEntry(spec, nsICache::ACCESS_WRITE, getter_AddRefs(entry)); - if (!entry || NS_FAILED(rv)) + if (NS_FAILED(rv) || !entry) return PR_FALSE; - entry->SetCacheElement(NS_STATIC_CAST(nsISupports *, NS_STATIC_CAST(imgIRequest*, request))); + nsCOMPtr sup(do_QueryInterface(NS_STATIC_CAST(imgIRequest*, request))); + entry->SetCacheElement(sup); entry->MarkValid(); @@ -113,18 +172,16 @@ PRBool ImageCache::Put(nsIURI *aKey, imgRequest *request, nsICacheEntryDescripto return PR_TRUE; } -PRBool ImageCache::Get(nsIURI *aKey, imgRequest **aRequest, nsICacheEntryDescriptor **aEntry) +PRBool imgCache::Get(nsIURI *aKey, imgRequest **aRequest, nsICacheEntryDescriptor **aEntry) { PR_LOG(gImgLog, PR_LOG_DEBUG, - ("ImageCache::Get\n")); + ("imgCache::Get\n")); nsresult rv; nsCOMPtr ses; - GetCacheSession(getter_AddRefs(ses)); - - if (!ses) - return PR_FALSE; + GetCacheSession(aKey, getter_AddRefs(ses)); + if (!ses) return PR_FALSE; nsXPIDLCString spec; aKey->GetSpec(getter_Copies(spec)); @@ -133,7 +190,7 @@ PRBool ImageCache::Get(nsIURI *aKey, imgRequest **aRequest, nsICacheEntryDescrip rv = ses->OpenCacheEntry(spec, nsICache::ACCESS_READ, getter_AddRefs(entry)); - if (!entry || NS_FAILED(rv)) + if (NS_FAILED(rv) || !entry) return PR_FALSE; nsCOMPtr sup; @@ -150,18 +207,16 @@ PRBool ImageCache::Get(nsIURI *aKey, imgRequest **aRequest, nsICacheEntryDescrip } -PRBool ImageCache::Remove(nsIURI *aKey) +PRBool imgCache::Remove(nsIURI *aKey) { PR_LOG(gImgLog, PR_LOG_DEBUG, - ("ImageCache::Remove\n")); + ("imgCache::Remove\n")); nsresult rv; nsCOMPtr ses; - GetCacheSession(getter_AddRefs(ses)); - - if (!ses) - return PR_FALSE; + GetCacheSession(aKey, getter_AddRefs(ses)); + if (!ses) return PR_FALSE; nsXPIDLCString spec; aKey->GetSpec(getter_Copies(spec)); @@ -170,7 +225,7 @@ PRBool ImageCache::Remove(nsIURI *aKey) rv = ses->OpenCacheEntry(spec, nsICache::ACCESS_READ, getter_AddRefs(entry)); - if (!entry || NS_FAILED(rv)) + if (NS_FAILED(rv) || !entry) return PR_FALSE; entry->Doom(); @@ -179,3 +234,4 @@ PRBool ImageCache::Remove(nsIURI *aKey) } #endif /* MOZ_NEW_CACHE */ + diff --git a/mozilla/modules/libpr0n/src/ImageCache.h b/mozilla/modules/libpr0n/src/imgCache.h similarity index 70% rename from mozilla/modules/libpr0n/src/ImageCache.h rename to mozilla/modules/libpr0n/src/imgCache.h index 27f2d8e25ea..fd23ed3ecbb 100644 --- a/mozilla/modules/libpr0n/src/ImageCache.h +++ b/mozilla/modules/libpr0n/src/imgCache.h @@ -21,27 +21,32 @@ * Stuart Parmenter */ -#ifndef ImageCache_h__ -#define ImageCache_h__ +#include "imgICache.h" -#include "nsIURI.h" -#include "imgRequest.h" #include "prtypes.h" -#ifdef MOZ_NEW_CACHE -#include "nsICacheEntryDescriptor.h" -#else +class imgRequest; +class nsIURI; class nsICacheEntryDescriptor; -#endif +#define NS_IMGCACHE_CID \ +{ /* fb4fd28a-1dd1-11b2-8391-e14242c59a41 */ \ + 0xfb4fd28a, \ + 0x1dd1, \ + 0x11b2, \ + {0x83, 0x91, 0xe1, 0x42, 0x42, 0xc5, 0x9a, 0x41} \ +} -class ImageCache +class imgCache : public imgICache { public: -#ifdef MOZ_NEW_CACHE - ImageCache(); - ~ImageCache(); + NS_DECL_ISUPPORTS + NS_DECL_IMGICACHE + imgCache(); + virtual ~imgCache(); + +#ifdef MOZ_NEW_CACHE static void Shutdown(); // for use by the factory /* additional members */ @@ -49,11 +54,10 @@ public: static PRBool Get(nsIURI *aKey, imgRequest **aRequest, nsICacheEntryDescriptor **aEntry); static PRBool Remove(nsIURI *aKey); + static nsresult ClearChromeImageCache(); + static nsresult ClearImageCache(); + #else - - ImageCache() { } - ~ImageCache() { } - static void Shutdown() { } /* additional members */ @@ -66,7 +70,13 @@ public: static PRBool Remove(nsIURI *aKey) { return PR_FALSE; } + static nsresult ClearChromeImageCache() { + return NS_ERROR_FAILURE; + } + static nsresult ClearImageCache() { + return NS_ERROR_FAILURE; + } + #endif /* MOZ_NEW_CACHE */ }; -#endif diff --git a/mozilla/modules/libpr0n/src/imgLoader.cpp b/mozilla/modules/libpr0n/src/imgLoader.cpp index bf358aa3e97..93a8c08fe6a 100644 --- a/mozilla/modules/libpr0n/src/imgLoader.cpp +++ b/mozilla/modules/libpr0n/src/imgLoader.cpp @@ -36,7 +36,7 @@ #include "imgRequest.h" #include "imgRequestProxy.h" -#include "ImageCache.h" +#include "imgCache.h" #include "nsXPIDLString.h" @@ -75,7 +75,7 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, nsILoadGroup *aLoadGroup, imgID #ifdef MOZ_NEW_CACHE nsCOMPtr entry; - ImageCache::Get(aURI, &request, getter_AddRefs(entry)); // addrefs request + imgCache::Get(aURI, &request, getter_AddRefs(entry)); // addrefs request if (request && entry && aLoadGroup) { /* this isn't exactly what I want here. This code will re-doom every cache hit in a document while @@ -132,10 +132,8 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, nsILoadGroup *aLoadGroup, imgID ("[this=%p] imgLoader::LoadImage -- Created new imgRequest [request=%p]\n", this, request)); #ifdef MOZ_NEW_CACHE - ImageCache::Put(aURI, request, getter_AddRefs(entry)); -#endif + imgCache::Put(aURI, request, getter_AddRefs(entry)); -#ifdef MOZ_NEW_CACHE request->Init(newChannel, entry); #else request->Init(newChannel, nsnull); @@ -144,8 +142,39 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, nsILoadGroup *aLoadGroup, imgID PR_LOG(gImgLog, PR_LOG_DEBUG, ("[this=%p] imgLoader::LoadImage -- Calling channel->AsyncOpen()\n", this)); - // XXX are we calling this too early? - newChannel->AsyncOpen(NS_STATIC_CAST(nsIStreamListener *, request), nsnull); + // create the proxy listener + ProxyListener *pl = new ProxyListener(NS_STATIC_CAST(nsIStreamListener *, request)); + if (!pl) { + NS_RELEASE(request); + return NS_ERROR_OUT_OF_MEMORY; + } + + NS_ADDREF(pl); + + /* XXX Are we calling AsyncOpen() too early? Is it possible for AsyncOpen to result + in an OnStartRequest to the channel before we call CreateNewProxyForRequest() ? + */ + nsresult asyncOpenResult = newChannel->AsyncOpen(NS_STATIC_CAST(nsIStreamListener *, pl), nsnull); + + NS_RELEASE(pl); + + if (NS_FAILED(asyncOpenResult)) { + /* If AsyncOpen fails, then we want to hand back a request proxy object that + has a canceled load. + */ + PR_LOG(gImgLog, PR_LOG_DEBUG, + ("[this=%p] imgLoader::LoadImage -- async open failed.\n", this)); + + nsresult rv = CreateNewProxyForRequest(request, aLoadGroup, aObserver, cx, _retval); + if (NS_SUCCEEDED(rv)) { + request->OnStartRequest(newChannel, nsnull); + request->OnStopRequest(newChannel, nsnull, NS_BINDING_ABORTED); + } + + NS_RELEASE(request); + + return asyncOpenResult; + } } else { /* request found in cache. use it */ @@ -157,23 +186,11 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, nsILoadGroup *aLoadGroup, imgID PR_LOG(gImgLog, PR_LOG_DEBUG, ("[this=%p] imgLoader::LoadImage -- creating proxy request.\n", this)); - imgRequestProxy *proxyRequest; - NS_NEWXPCOM(proxyRequest, imgRequestProxy); - if (!proxyRequest) return NS_ERROR_OUT_OF_MEMORY; - - NS_ADDREF(proxyRequest); - - // init adds itself to imgRequest's list of observers - proxyRequest->Init(request, aLoadGroup, aObserver, cx); + nsresult rv = CreateNewProxyForRequest(request, aLoadGroup, aObserver, cx, _retval); NS_RELEASE(request); - *_retval = NS_STATIC_CAST(imgIRequest*, proxyRequest); - NS_ADDREF(*_retval); - - NS_RELEASE(proxyRequest); - - return NS_OK; + return rv; } /* imgIRequest loadImageWithChannel(in nsIChannel, in imgIDecoderObserver aObserver, in nsISupports cx, out nsIStreamListener); */ @@ -188,14 +205,14 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb #ifdef MOZ_NEW_CACHE nsCOMPtr entry; - ImageCache::Get(uri, &request, getter_AddRefs(entry)); // addrefs request + imgCache::Get(uri, &request, getter_AddRefs(entry)); // addrefs request #endif if (request) { // we have this in our cache already.. cancel the current (document) load - // XXX - // if *listener is null when we return here, the caller should probably cancel - // the channel instead of us doing it here. + /* XXX If |*listener| is null when we return here, the caller should + probably cancel the channel instead of us doing it here. + */ channel->Cancel(NS_BINDING_ABORTED); // this should fire an OnStopRequest *listener = nsnull; // give them back a null nsIStreamListener @@ -206,19 +223,50 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb NS_ADDREF(request); #ifdef MOZ_NEW_CACHE - ImageCache::Put(uri, request, getter_AddRefs(entry)); -#endif + imgCache::Put(uri, request, getter_AddRefs(entry)); -#ifdef MOZ_NEW_CACHE request->Init(channel, entry); #else request->Init(channel, nsnull); #endif - *listener = NS_STATIC_CAST(nsIStreamListener*, request); - NS_IF_ADDREF(*listener); + ProxyListener *pl = new ProxyListener(NS_STATIC_CAST(nsIStreamListener *, request)); + if (!pl) { + NS_RELEASE(request); + return NS_ERROR_OUT_OF_MEMORY; + } + + NS_ADDREF(pl); + + *listener = NS_STATIC_CAST(nsIStreamListener*, pl); + NS_ADDREF(*listener); + + NS_RELEASE(pl); } + nsCOMPtr loadGroup; + channel->GetLoadGroup(getter_AddRefs(loadGroup)); + + nsresult rv = CreateNewProxyForRequest(request, loadGroup, aObserver, cx, _retval); + + NS_RELEASE(request); + + return rv; +} + + + +nsresult +imgLoader::CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup *aLoadGroup, + imgIDecoderObserver *aObserver, nsISupports *cx, + imgIRequest **_retval) +{ + LOG_SCOPE_WITH_PARAM(gImgLog, "imgLoader::CreateNewProxyForRequest", "imgRequest", aRequest); + + /* XXX If we move decoding onto seperate threads, we should save off the calling thread here + and pass it off to |proxyRequest| so that it call proxy calls to |aObserver|. + */ + imgRequestProxy *proxyRequest; NS_NEWXPCOM(proxyRequest, imgRequestProxy); if (!proxyRequest) return NS_ERROR_OUT_OF_MEMORY; @@ -226,9 +274,11 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb NS_ADDREF(proxyRequest); // init adds itself to imgRequest's list of observers - proxyRequest->Init(request, nsnull, aObserver, cx); - - NS_RELEASE(request); + nsresult rv = proxyRequest->Init(aRequest, aLoadGroup, aObserver, cx); + if (NS_FAILED(rv)) { + NS_RELEASE(proxyRequest); + return rv; + } *_retval = NS_STATIC_CAST(imgIRequest*, proxyRequest); NS_ADDREF(*_retval); @@ -237,3 +287,88 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb return NS_OK; } + + + +/** + * proxy stream listener class used to handle multipart/x-mixed-replace + */ + +#include "nsIRequest.h" +#include "nsIStreamConverterService.h" +#include "nsXPIDLString.h" + +NS_IMPL_ISUPPORTS2(ProxyListener, nsIStreamListener, nsIRequestObserver) + +ProxyListener::ProxyListener(nsIStreamListener *dest) : + mDestListener(dest) +{ + NS_INIT_ISUPPORTS(); + /* member initializers and constructor code */ +} + +ProxyListener::~ProxyListener() +{ + /* destructor code */ +} + + +/** nsIRequestObserver methods **/ + +/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */ +NS_IMETHODIMP ProxyListener::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt) +{ + if (!mDestListener) + return NS_ERROR_FAILURE; + + nsCOMPtr channel(do_QueryInterface(aRequest)); + if (channel) { + nsXPIDLCString contentType; + nsresult rv = channel->GetContentType(getter_Copies(contentType)); + + if (contentType.get()) { + /* If multipart/x-mixed-replace content, we'll insert a MIME decoder + in the pipeline to handle the content and pass it along to our + original listener. + */ + if (NS_LITERAL_CSTRING("multipart/x-mixed-replace").Equals(contentType)) { + + nsCOMPtr convServ(do_GetService("@mozilla.org/streamConverters;1", &rv)); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr toListener(mDestListener); + nsCOMPtr fromListener; + + rv = convServ->AsyncConvertData(NS_LITERAL_STRING("multipart/x-mixed-replace").get(), + NS_LITERAL_STRING("*/*").get(), + toListener, + nsnull, + getter_AddRefs(fromListener)); + if (NS_SUCCEEDED(rv)) + mDestListener = fromListener; + } + } + } + } + + return mDestListener->OnStartRequest(aRequest, ctxt); +} + +/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status); */ +NS_IMETHODIMP ProxyListener::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt, nsresult status) +{ + if (!mDestListener) + return NS_ERROR_FAILURE; + + return mDestListener->OnStopRequest(aRequest, ctxt, status); +} + +/** nsIStreamListener methods **/ + +/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long sourceOffset, in unsigned long count); */ +NS_IMETHODIMP ProxyListener::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count) +{ + if (!mDestListener) + return NS_ERROR_FAILURE; + + return mDestListener->OnDataAvailable(aRequest, ctxt, inStr, sourceOffset, count); +} diff --git a/mozilla/modules/libpr0n/src/imgLoader.h b/mozilla/modules/libpr0n/src/imgLoader.h index 24685bff84a..69ca516a041 100644 --- a/mozilla/modules/libpr0n/src/imgLoader.h +++ b/mozilla/modules/libpr0n/src/imgLoader.h @@ -27,6 +27,11 @@ #include "prlock.h" #endif +class imgRequest; +class imgIRequest; +class imgIDecoderObserver; +class nsILoadGroup; + #define NS_IMGLOADER_CID \ { /* 9f6a0d2e-1dd1-11b2-a5b8-951f13c846f7 */ \ 0x9f6a0d2e, \ @@ -45,4 +50,31 @@ public: virtual ~imgLoader(); private: + nsresult CreateNewProxyForRequest(imgRequest *aRequest, nsILoadGroup *aLoadGroup, + imgIDecoderObserver *aObserver, nsISupports *cx, + imgIRequest **_retval); +}; + + + +/** + * proxy stream listener class used to handle multipart/x-mixed-replace + */ + +#include "nsCOMPtr.h" +#include "nsIStreamListener.h" + +class ProxyListener : public nsIStreamListener +{ +public: + ProxyListener(nsIStreamListener *dest); + virtual ~ProxyListener(); + + /* additional members */ + NS_DECL_ISUPPORTS + NS_DECL_NSISTREAMLISTENER + NS_DECL_NSIREQUESTOBSERVER + +private: + nsCOMPtr mDestListener; }; diff --git a/mozilla/modules/libpr0n/src/imgRequest.cpp b/mozilla/modules/libpr0n/src/imgRequest.cpp index 944a5ec9474..1ed69351b72 100644 --- a/mozilla/modules/libpr0n/src/imgRequest.cpp +++ b/mozilla/modules/libpr0n/src/imgRequest.cpp @@ -23,10 +23,10 @@ #include "imgRequest.h" -#include "nsIAtom.h" +#include "imgRequestProxy.h" + #include "nsIChannel.h" #include "nsILoadGroup.h" -#include "nsIHTTPChannel.h" #include "nsIInputStream.h" #include "imgILoader.h" @@ -43,7 +43,7 @@ #ifdef MOZ_NEW_CACHE #include "nsICachingChannel.h" #endif -#include "ImageCache.h" +#include "imgCache.h" #include "ImageLogging.h" @@ -71,8 +71,6 @@ imgRequest::~imgRequest() nsresult imgRequest::Init(nsIChannel *aChannel, nsICacheEntryDescriptor *aCacheEntry) { - // XXX we should save off the thread we are getting called on here so that we can proxy all calls to mDecoder to it. - PR_LOG(gImgLog, PR_LOG_DEBUG, ("[this=%p] imgRequest::Init\n", this)); @@ -81,6 +79,13 @@ nsresult imgRequest::Init(nsIChannel *aChannel, nsICacheEntryDescriptor *aCacheE mChannel = aChannel; + /* set our loading flag to true here. + Setting it here lets checks to see if the load is in progress + before OnStartRequest gets called, letting 'this' properly get removed + from the cache in certain cases. + */ + mLoading = PR_TRUE; + #ifdef MOZ_NEW_CACHE mCacheEntry = aCacheEntry; #endif @@ -88,19 +93,19 @@ nsresult imgRequest::Init(nsIChannel *aChannel, nsICacheEntryDescriptor *aCacheE return NS_OK; } -nsresult imgRequest::AddObserver(imgIDecoderObserver *observer) +nsresult imgRequest::AddProxy(imgRequestProxy *proxy) { - LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::AddObserver", "observer", observer); + LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::AddProxy", "proxy", proxy); - mObservers.AppendElement(NS_STATIC_CAST(void*, observer)); + mObservers.AppendElement(NS_STATIC_CAST(void*, proxy)); // OnStartDecode if (mState & onStartDecode) - observer->OnStartDecode(nsnull, nsnull); + proxy->OnStartDecode(nsnull, nsnull); // OnStartContainer if (mState & onStartContainer) - observer->OnStartContainer(nsnull, nsnull, mImage); + proxy->OnStartContainer(nsnull, nsnull, mImage); // Send frame messages (OnStartFrame, OnDataAvailable, OnStopFrame) PRUint32 nframes = 0; @@ -109,54 +114,39 @@ nsresult imgRequest::AddObserver(imgIDecoderObserver *observer) if (nframes > 0) { nsCOMPtr frame; - - // Is this a single frame image? - if (nframes == 1) { - // Get the first frame - mImage->GetFrameAt(0, getter_AddRefs(frame)); - NS_ASSERTION(frame, "GetFrameAt gave back a null frame!"); - } else if (nframes > 1) { - /* multiple frames, we'll use the current one */ - mImage->GetCurrentFrame(getter_AddRefs(frame)); - NS_ASSERTION(frame, "GetCurrentFrame gave back a null frame!"); - } - + + // get the current frame or only frame + mImage->GetCurrentFrame(getter_AddRefs(frame)); + NS_ASSERTION(frame, "GetCurrentFrame gave back a null frame!"); + // OnStartFrame - observer->OnStartFrame(nsnull, nsnull, frame); - + proxy->OnStartFrame(nsnull, nsnull, frame); + if (!(mState & onStopContainer)) { // OnDataAvailable nsRect r; - frame->GetRect(r); // XXX we shouldn't send the whole rect here - observer->OnDataAvailable(nsnull, nsnull, frame, &r); + frame->GetRect(r); // XXX we should only send the currently decoded rectangle here. + proxy->OnDataAvailable(nsnull, nsnull, frame, &r); } else { // OnDataAvailable nsRect r; frame->GetRect(r); // We're done loading this image, send the the whole rect - observer->OnDataAvailable(nsnull, nsnull, frame, &r); - + proxy->OnDataAvailable(nsnull, nsnull, frame, &r); + // OnStopFrame - observer->OnStopFrame(nsnull, nsnull, frame); + proxy->OnStopFrame(nsnull, nsnull, frame); } } // OnStopContainer if (mState & onStopContainer) - observer->OnStopContainer(nsnull, nsnull, mImage); - - nsresult status; - if (mStatus & imgIRequest::STATUS_LOAD_COMPLETE) - status = NS_IMAGELIB_SUCCESS_LOAD_FINISHED; - else if (mStatus & imgIRequest::STATUS_ERROR) - status = NS_IMAGELIB_ERROR_FAILURE; + proxy->OnStopContainer(nsnull, nsnull, mImage); // OnStopDecode if (mState & onStopDecode) - observer->OnStopDecode(nsnull, nsnull, status, nsnull); + proxy->OnStopDecode(nsnull, nsnull, GetResultFromStatus(), nsnull); if (mImage && (mObservers.Count() == 1)) { - PRUint32 nframes; - mImage->GetNumFrames(&nframes); PR_LOG(gImgLog, PR_LOG_DEBUG, ("[this=%p] imgRequest::AddObserver -- starting animation\n", this)); @@ -164,57 +154,58 @@ nsresult imgRequest::AddObserver(imgIDecoderObserver *observer) } if (mState & onStopRequest) { - nsCOMPtr ob(do_QueryInterface(observer)); - PR_ASSERT(observer); - ob->OnStopRequest(nsnull, nsnull, status); + proxy->OnStopRequest(nsnull, nsnull, GetResultFromStatus()); } return NS_OK; } -nsresult imgRequest::RemoveObserver(imgIDecoderObserver *observer, nsresult status) +nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus) { - LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::RemoveObserver", "observer", observer); + LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::RemoveProxy", "proxy", proxy); - mObservers.RemoveElement(NS_STATIC_CAST(void*, observer)); + mObservers.RemoveElement(NS_STATIC_CAST(void*, proxy)); if (mObservers.Count() == 0) { if (mImage) { - PRUint32 nframes; - mImage->GetNumFrames(&nframes); - if (nframes > 1) { - PR_LOG(gImgLog, PR_LOG_DEBUG, - ("[this=%p] imgRequest::RemoveObserver -- stopping animation\n", this)); + PR_LOG(gImgLog, PR_LOG_DEBUG, + ("[this=%p] imgRequest::RemoveObserver -- stopping animation\n", this)); - mImage->StopAnimation(); - } + mImage->StopAnimation(); } - if (mChannel && mLoading) { + /* If |aStatus| is a failure code, then cancel the load if it is still in progress. + Otherwise, let the load continue, keeping 'this' in the cache with no observers. + This way, if a proxy is destroyed without calling cancel on it, it won't leak + and won't leave a bad pointer in mObservers. + */ + if (mChannel && mLoading && NS_FAILED(aStatus)) { PR_LOG(gImgLog, PR_LOG_DEBUG, ("[this=%p] imgRequest::RemoveObserver -- load in progress. canceling\n", this)); - this->RemoveFromCache(); this->Cancel(NS_BINDING_ABORTED); - - if (!(mState & onStopDecode)) { - // make sure that observer gets an onStopRequest message sent to it - observer->OnStopDecode(nsnull, nsnull, NS_IMAGELIB_ERROR_FAILURE, nsnull); - } - - if (!(mState & onStopRequest)) { - // make sure that observer gets an onStopRequest message sent to it - nsCOMPtr ob(do_QueryInterface(observer)); - PR_ASSERT(ob); - ob->OnStopRequest(nsnull, nsnull, NS_BINDING_ABORTED); - } } + +#ifdef MOZ_NEW_CACHE + /* break the cycle from the cache entry. */ + mCacheEntry = nsnull; +#endif + } + + if (!(mState & onStopDecode)) { + // make sure that observer gets an OnStopDecode message sent to it + proxy->OnStopDecode(nsnull, nsnull, NS_IMAGELIB_ERROR_FAILURE, nsnull); + } + + if (!(mState & onStopRequest)) { + // make sure that observer gets an OnStopRequest message sent to it + proxy->OnStopRequest(nsnull, nsnull, NS_BINDING_ABORTED); } return NS_OK; } -PRBool imgRequest::RemoveFromCache() +void imgRequest::RemoveFromCache() { LOG_SCOPE(gImgLog, "imgRequest::RemoveFromCache"); @@ -223,13 +214,21 @@ PRBool imgRequest::RemoveFromCache() if (mCacheEntry) { mCacheEntry->Doom(); mCacheEntry = nsnull; - } else { - NS_WARNING("imgRequest::RemoveFromCache -- no entry!"); } #endif +} - return PR_TRUE; +nsresult imgRequest::GetResultFromStatus() +{ + nsresult rv = NS_OK; + + if (mStatus & imgIRequest::STATUS_ERROR) + rv = NS_IMAGELIB_ERROR_FAILURE; + else if (mStatus & imgIRequest::STATUS_LOAD_COMPLETE) + rv = NS_IMAGELIB_SUCCESS_LOAD_FINISHED; + + return rv; } @@ -259,21 +258,23 @@ NS_IMETHODIMP imgRequest::GetStatus(nsresult *aStatus) /* void cancel (in nsresult status); */ NS_IMETHODIMP imgRequest::Cancel(nsresult status) { + /* The Cancel() method here should only be called by this class. */ + LOG_SCOPE(gImgLog, "imgRequest::Cancel"); if (mImage) { - PRUint32 nframes; - mImage->GetNumFrames(&nframes); - if (nframes > 1) { - PR_LOG(gImgLog, PR_LOG_DEBUG, - ("[this=%p] imgRequest::RemoveObserver -- stopping animation\n", this)); + PR_LOG(gImgLog, PR_LOG_DEBUG, + ("[this=%p] imgRequest::Cancel -- stopping animation\n", this)); - mImage->StopAnimation(); - } + mImage->StopAnimation(); } + mStatus |= imgIRequest::STATUS_ERROR; + + RemoveFromCache(); + if (mChannel && mLoading) - mChannel->Cancel(NS_BINDING_ABORTED); // should prolly use status here + mChannel->Cancel(status); return NS_OK; } @@ -328,13 +329,12 @@ NS_IMETHODIMP imgRequest::GetImage(imgIContainer * *aImage) NS_IF_ADDREF(*aImage); return NS_OK; } + NS_IMETHODIMP imgRequest::SetImage(imgIContainer *aImage) { PR_LOG(gImgLog, PR_LOG_DEBUG, ("[this=%p] imgRequest::SetImage\n", this)); - if (mImage) return NS_ERROR_FAILURE; - mImage = aImage; return NS_OK; } @@ -357,7 +357,8 @@ NS_IMETHODIMP imgRequest::GetURI(nsIURI **aURI) if (mChannel) return mChannel->GetOriginalURI(aURI); - else if (mURI) { + + if (mURI) { *aURI = mURI; NS_ADDREF(*aURI); return NS_OK; @@ -369,7 +370,8 @@ NS_IMETHODIMP imgRequest::GetURI(nsIURI **aURI) /* readonly attribute imgIDecoderObserver decoderObserver; */ NS_IMETHODIMP imgRequest::GetDecoderObserver(imgIDecoderObserver **aDecoderObserver) { - return NS_ERROR_FAILURE; + NS_NOTYETIMPLEMENTED("imgRequest::GetDecoderObserver"); + return NS_ERROR_NOT_IMPLEMENTED; } @@ -380,12 +382,10 @@ NS_IMETHODIMP imgRequest::FrameChanged(imgIContainer *container, nsISupports *cx { LOG_SCOPE(gImgLog, "imgRequest::FrameChanged"); - PRInt32 i = -1; PRInt32 count = mObservers.Count(); - - while (++i < count) { - imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]); - if (ob) ob->FrameChanged(container, cx, newframe, dirtyRect); + for (PRInt32 i = 0; i < count; i++) { + imgRequestProxy *proxy = NS_STATIC_CAST(imgRequestProxy*, mObservers[i]); + if (proxy) proxy->FrameChanged(container, cx, newframe, dirtyRect); } return NS_OK; @@ -400,14 +400,22 @@ NS_IMETHODIMP imgRequest::OnStartDecode(imgIRequest *request, nsISupports *cx) mState |= onStartDecode; - PRInt32 i = -1; PRInt32 count = mObservers.Count(); - - while (++i < count) { - imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]); - if (ob) ob->OnStartDecode(request, cx); + for (PRInt32 i = 0; i < count; i++) { + imgRequestProxy *proxy = NS_STATIC_CAST(imgRequestProxy*, mObservers[i]); + if (proxy) proxy->OnStartDecode(request, cx); } +#ifdef MOZ_NEW_CACHE + /* In the case of streaming jpegs, it is possible to get multiple OnStartDecodes which + indicates the beginning of a new decode. + The cache entry's size therefore needs to be reset to 0 here. If we do not do this, + the code in imgRequest::OnStopFrame will continue to increase the data size cumulatively. + */ + if (mCacheEntry) + mCacheEntry->SetDataSize(0); +#endif + return NS_OK; } @@ -420,12 +428,10 @@ NS_IMETHODIMP imgRequest::OnStartContainer(imgIRequest *request, nsISupports *cx mStatus |= imgIRequest::STATUS_SIZE_AVAILABLE; - PRInt32 i = -1; PRInt32 count = mObservers.Count(); - - while (++i < count) { - imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]); - if (ob) ob->OnStartContainer(request, cx, image); + for (PRInt32 i = 0; i < count; i++) { + imgRequestProxy *proxy = NS_STATIC_CAST(imgRequestProxy*, mObservers[i]); + if (proxy) proxy->OnStartContainer(request, cx, image); } return NS_OK; @@ -436,12 +442,10 @@ NS_IMETHODIMP imgRequest::OnStartFrame(imgIRequest *request, nsISupports *cx, gf { LOG_SCOPE(gImgLog, "imgRequest::OnStartFrame"); - PRInt32 i = -1; PRInt32 count = mObservers.Count(); - - while (++i < count) { - imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]); - if (ob) ob->OnStartFrame(request, cx, frame); + for (PRInt32 i = 0; i < count; i++) { + imgRequestProxy *proxy = NS_STATIC_CAST(imgRequestProxy*, mObservers[i]); + if (proxy) proxy->OnStartFrame(request, cx, frame); } return NS_OK; @@ -456,12 +460,10 @@ NS_IMETHODIMP imgRequest::OnDataAvailable(imgIRequest *request, nsISupports *cx, if (container) container->OnDataAvailable(request, cx, frame, rect); - PRInt32 i = -1; PRInt32 count = mObservers.Count(); - - while (++i < count) { - imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]); - if (ob) ob->OnDataAvailable(request, cx, frame, rect); + for (PRInt32 i = 0; i < count; i++) { + imgRequestProxy *proxy = NS_STATIC_CAST(imgRequestProxy*, mObservers[i]); + if (proxy) proxy->OnDataAvailable(request, cx, frame, rect); } return NS_OK; @@ -474,9 +476,6 @@ NS_IMETHODIMP imgRequest::OnStopFrame(imgIRequest *request, nsISupports *cx, gfx LOG_SCOPE(gImgLog, "imgRequest::OnStopFrame"); - PRInt32 i = -1; - PRInt32 count = mObservers.Count(); - #ifdef MOZ_NEW_CACHE if (mCacheEntry) { PRUint32 cacheSize = 0; @@ -493,9 +492,10 @@ NS_IMETHODIMP imgRequest::OnStopFrame(imgIRequest *request, nsISupports *cx, gfx } #endif - while (++i < count) { - imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]); - if (ob) ob->OnStopFrame(request, cx, frame); + PRInt32 count = mObservers.Count(); + for (PRInt32 i = 0; i < count; i++) { + imgRequestProxy *proxy = NS_STATIC_CAST(imgRequestProxy*, mObservers[i]); + if (proxy) proxy->OnStopFrame(request, cx, frame); } return NS_OK; @@ -508,12 +508,10 @@ NS_IMETHODIMP imgRequest::OnStopContainer(imgIRequest *request, nsISupports *cx, mState |= onStopContainer; - PRInt32 i = -1; PRInt32 count = mObservers.Count(); - - while (++i < count) { - imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]); - if (ob) ob->OnStopContainer(request, cx, image); + for (PRInt32 i = 0; i < count; i++) { + imgRequestProxy *proxy = NS_STATIC_CAST(imgRequestProxy*, mObservers[i]); + if (proxy) proxy->OnStopContainer(request, cx, image); } return NS_OK; @@ -524,28 +522,17 @@ NS_IMETHODIMP imgRequest::OnStopDecode(imgIRequest *aRequest, nsISupports *aCX, { LOG_SCOPE(gImgLog, "imgRequest::OnStopDecode"); - if (mState & onStopDecode) { - NS_WARNING("OnStopDecode called multiple times."); - return NS_OK; - } + NS_ASSERTION(!(mState & onStopDecode), "OnStopDecode called multiple times."); mState |= onStopDecode; - if (!(mStatus & imgIRequest::STATUS_ERROR) && NS_FAILED(aStatus)) + if (NS_FAILED(aStatus)) mStatus |= imgIRequest::STATUS_ERROR; - PRInt32 i = -1; PRInt32 count = mObservers.Count(); - - nsresult status; - if (mStatus & imgIRequest::STATUS_LOAD_COMPLETE) - status = NS_IMAGELIB_SUCCESS_LOAD_FINISHED; - else if (mStatus & imgIRequest::STATUS_ERROR) - status = NS_IMAGELIB_ERROR_FAILURE; - - while (++i < count) { - imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]); - if (ob) ob->OnStopDecode(aRequest, aCX, status, aStatusArg); + for (PRInt32 i = 0; i < count; i++) { + imgRequestProxy *proxy = NS_STATIC_CAST(imgRequestProxy*, mObservers[i]); + if (proxy) proxy->OnStopDecode(aRequest, aCX, GetResultFromStatus(), aStatusArg); } return NS_OK; @@ -564,53 +551,26 @@ NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt LOG_SCOPE(gImgLog, "imgRequest::OnStartRequest"); NS_ASSERTION(!mDecoder, "imgRequest::OnStartRequest -- we already have a decoder"); - NS_ASSERTION(!mLoading, "imgRequest::OnStartRequest -- we are loading again?"); + + /* set our state variables to their initial values. */ + mStatus = imgIRequest::STATUS_NONE; + mState = 0; /* set our loading flag to true */ mLoading = PR_TRUE; /* notify our kids */ - PRInt32 i = -1; PRInt32 count = mObservers.Count(); - - while (++i < count) { - imgIDecoderObserver *iob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]); - if (iob) { - nsCOMPtr ob(do_QueryInterface(iob)); - if (ob) ob->OnStartRequest(aRequest, ctxt); - } + for (PRInt32 i = 0; i < count; i++) { + imgRequestProxy *proxy = NS_STATIC_CAST(imgRequestProxy*, mObservers[i]); + if (proxy) proxy->OnStartRequest(aRequest, ctxt); } - /* do our real work */ +#if defined(MOZ_NEW_CACHE) nsCOMPtr chan(do_QueryInterface(aRequest)); - if (!mChannel) { - PR_LOG(gImgLog, PR_LOG_ALWAYS, - (" `-> Channel already stopped or no channel!?.\n")); - - return NS_ERROR_FAILURE; - } - - nsCOMPtr httpChannel(do_QueryInterface(chan)); - if (httpChannel) { - PRUint32 httpStatus; - httpChannel->GetResponseStatus(&httpStatus); - if (httpStatus == 404) { - PR_LOG(gImgLog, PR_LOG_DEBUG, - ("[this=%p] imgRequest::OnStartRequest -- http status = 404. canceling.\n", this)); - - mStatus |= imgIRequest::STATUS_ERROR; - this->Cancel(NS_BINDING_ABORTED); - this->RemoveFromCache(); - - return NS_BINDING_ABORTED; - } - - } - /* get the expires info */ -#if defined(MOZ_NEW_CACHE) - if (mCacheEntry) { + if (mCacheEntry && chan) { nsCOMPtr cacheChannel(do_QueryInterface(chan)); if (cacheChannel) { nsCOMPtr cacheToken; @@ -633,14 +593,12 @@ NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt return NS_OK; } -/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status, in wstring statusArg); */ +/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status); */ NS_IMETHODIMP imgRequest::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt, nsresult status) { PR_LOG(gImgLog, PR_LOG_DEBUG, ("[this=%p] imgRequest::OnStopRequest\n", this)); - NS_ASSERTION(mChannel && mLoading, "imgRequest::OnStopRequest -- received multiple OnStopRequest"); - mState |= onStopRequest; /* set our loading flag to false */ @@ -649,49 +607,36 @@ NS_IMETHODIMP imgRequest::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt, /* set our processing flag to false */ mProcessing = PR_FALSE; -#ifdef MOZ_NEW_CACHE - /* break the cycle from the cache entry. */ - mCacheEntry = nsnull; -#endif + if (mChannel) { + mChannel->GetOriginalURI(getter_AddRefs(mURI)); + mChannel = nsnull; // we no longer need the channel + } if (NS_FAILED(status)) { - mStatus |= imgIRequest::STATUS_ERROR; - this->RemoveFromCache(); - this->Cancel(status); // stops animations + this->Cancel(status); // sets status, stops animations, removes from cache } else { mStatus |= imgIRequest::STATUS_LOAD_COMPLETE; } - mChannel->GetOriginalURI(getter_AddRefs(mURI)); - mChannel = nsnull; // we no longer need the channel - if (mDecoder) { mDecoder->Flush(); mDecoder->Close(); mDecoder = nsnull; // release the decoder so that it can rest peacefully ;) } - - /* notify the kids */ - PRInt32 i = -1; - PRInt32 count = mObservers.Count(); - - while (++i < count) { - void *item = NS_STATIC_CAST(void *, mObservers[i]); - if (item) { - imgIDecoderObserver *iob = NS_STATIC_CAST(imgIDecoderObserver*, item); - if (iob) { - nsCOMPtr ob(do_QueryInterface(iob)); - if (ob) ob->OnStopRequest(aRequest, ctxt, status); - } - } - } - + // if there was an error loading the image, (mState & onStopDecode) won't be true. // Send an onStopDecode message if (!(mState & onStopDecode)) { this->OnStopDecode(nsnull, nsnull, status, nsnull); } + /* notify the kids */ + PRInt32 count = mObservers.Count(); + for (PRInt32 i = 0; i < count; i++) { + imgRequestProxy *proxy = NS_STATIC_CAST(imgRequestProxy*, mObservers[i]); + if (proxy) proxy->OnStopRequest(aRequest, ctxt, status); + } + return NS_OK; } @@ -708,13 +653,13 @@ static NS_METHOD sniff_mimetype_callback(nsIInputStream* in, void* closure, cons /* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long sourceOffset, in unsigned long count); */ NS_IMETHODIMP imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count) { - PR_LOG(gImgLog, PR_LOG_DEBUG, - ("[this=%p] imgRequest::OnDataAvailable\n", this)); - - NS_ASSERTION(mChannel, "imgRequest::OnDataAvailable -- no channel!"); + LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable"); + NS_ASSERTION(aRequest, "imgRequest::OnDataAvailable -- no request!"); if (!mProcessing) { + LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable |First time through... finding mimetype|"); + /* set our processing flag to true if this is the first OnDataAvailable() */ mProcessing = PR_TRUE; @@ -728,26 +673,37 @@ NS_IMETHODIMP imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctx /* NS_WARNING if the content type from the channel isn't the same if the sniffing */ #endif - if (!mContentType.get()) { + if (mContentType.IsEmpty()) { + LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable |sniffing of mimetype failed|"); + nsXPIDLCString contentType; - nsresult rv = mChannel->GetContentType(getter_Copies(contentType)); + nsCOMPtr chan(do_QueryInterface(aRequest)); + + nsresult rv = NS_ERROR_FAILURE; + if (chan) { + rv = chan->GetContentType(getter_Copies(contentType)); + } if (NS_FAILED(rv)) { PR_LOG(gImgLog, PR_LOG_ERROR, - ("[this=%p] imgRequest::OnStartRequest -- Content type unavailable from the channel\n", + ("[this=%p] imgRequest::OnDataAvailable -- Content type unavailable from the channel\n", this)); - this->RemoveFromCache(); + this->Cancel(NS_BINDING_ABORTED); - return NS_BINDING_ABORTED; //NS_BASE_STREAM_CLOSED; + return NS_BINDING_ABORTED; } + PR_LOG(gImgLog, PR_LOG_DEBUG, + ("[this=%p] imgRequest::OnDataAvailable -- Got content type from the channel\n", + this)); + mContentType = contentType; } #if defined(PR_LOGGING) PR_LOG(gImgLog, PR_LOG_DEBUG, - ("[this=%p] imgRequest::OnStartRequest -- Content type is %s\n", this, mContentType.get())); + ("[this=%p] imgRequest::OnDataAvailable -- Content type is %s\n", this, mContentType.get())); #endif nsCAutoString conid("@mozilla.org/image/decoder;2?type="); @@ -757,29 +713,31 @@ NS_IMETHODIMP imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctx if (!mDecoder) { PR_LOG(gImgLog, PR_LOG_WARNING, - ("[this=%p] imgRequest::OnStartRequest -- Decoder not available\n", this)); + ("[this=%p] imgRequest::OnDataAvailable -- Decoder not available\n", this)); // no image decoder for this mimetype :( this->Cancel(NS_BINDING_ABORTED); - this->RemoveFromCache(); - // XXX notify the person that owns us now that wants the imgIContainer off of us? return NS_IMAGELIB_ERROR_NO_DECODER; } mDecoder->Init(NS_STATIC_CAST(imgIRequest*, this)); - } if (!mDecoder) { PR_LOG(gImgLog, PR_LOG_WARNING, ("[this=%p] imgRequest::OnDataAvailable -- no decoder\n", this)); - return NS_BASE_STREAM_CLOSED; + this->Cancel(NS_BINDING_ABORTED); + + return NS_BINDING_ABORTED; } PRUint32 wrote; nsresult rv = mDecoder->WriteFrom(inStr, count, &wrote); +#ifdef DEBUG_pavlov + NS_ASSERTION(NS_SUCCEEDED(rv), "mDecoder->WriteFrom failed"); +#endif return NS_OK; } diff --git a/mozilla/modules/libpr0n/src/imgRequest.h b/mozilla/modules/libpr0n/src/imgRequest.h index 3e97837432e..6aab8fac773 100644 --- a/mozilla/modules/libpr0n/src/imgRequest.h +++ b/mozilla/modules/libpr0n/src/imgRequest.h @@ -26,8 +26,6 @@ #include "imgIRequest.h" -#include "nsIRunnable.h" - #include "nsIChannel.h" #include "nsIURI.h" #include "imgIContainer.h" @@ -47,6 +45,8 @@ class nsICacheEntryDescriptor; #endif +class imgRequestProxy; + #define NS_IMGREQUEST_CID \ { /* 9f733dd6-1dd1-11b2-8cdf-effb70d1ea71 */ \ 0x9f733dd6, \ @@ -56,10 +56,10 @@ class nsICacheEntryDescriptor; } enum { - onStartDecode = 0x1, - onStartContainer = 0x2, - onStopContainer = 0x4, - onStopDecode = 0x8, + onStartDecode = 0x01, + onStartContainer = 0x02, + onStopContainer = 0x04, + onStopDecode = 0x08, onStopRequest = 0x16 }; @@ -74,13 +74,16 @@ public: /* additional members */ nsresult Init(nsIChannel *aChannel, nsICacheEntryDescriptor *aCacheEntry); - nsresult AddObserver(imgIDecoderObserver *observer); - nsresult RemoveObserver(imgIDecoderObserver *observer, nsresult status); - - PRBool RemoveFromCache(); + nsresult AddProxy(imgRequestProxy *proxy); + nsresult RemoveProxy(imgRequestProxy *proxy, nsresult aStatus); void SniffMimeType(const char *buf, PRUint32 len); +protected: + void RemoveFromCache(); + nsresult GetResultFromStatus(); + +public: NS_DECL_ISUPPORTS NS_DECL_IMGIREQUEST NS_DECL_NSIREQUEST diff --git a/mozilla/modules/libpr0n/src/imgRequestProxy.cpp b/mozilla/modules/libpr0n/src/imgRequestProxy.cpp index d06c5d2dec5..7e14a56b1db 100644 --- a/mozilla/modules/libpr0n/src/imgRequestProxy.cpp +++ b/mozilla/modules/libpr0n/src/imgRequestProxy.cpp @@ -36,8 +36,6 @@ #include "nsString.h" -#include "DummyChannel.h" - #include "nspr.h" #include "ImageLogging.h" @@ -55,44 +53,44 @@ imgRequestProxy::~imgRequestProxy() { /* destructor code */ - // XXX pav - // it isn't the job of the request proxy to cancel itself. - // if your object goes away and you want to cancel the load, then do it yourself. + if (!mCanceled) { + mCanceled = PR_TRUE; - // cancel here for now until i make this work right like the above comment - Cancel(NS_ERROR_FAILURE); + /* set mListener to null so that we don't forward any callbacks that RemoveObserver might generate */ + mListener = nsnull; + + /* Call RemoveObserver 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. + */ + NS_REINTERPRET_CAST(imgRequest*, mOwner.get())->RemoveProxy(this, NS_OK); + + mOwner = nsnull; + } } nsresult imgRequestProxy::Init(imgRequest *request, nsILoadGroup *aLoadGroup, imgIDecoderObserver *aObserver, nsISupports *cx) { - PR_ASSERT(request); + NS_PRECONDITION(aLoadGroup, "no loadgroup"); + if (!aLoadGroup) + return NS_ERROR_NULL_POINTER; + + NS_PRECONDITION(request, "no request"); + if (!request) + return NS_ERROR_NULL_POINTER; LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequestProxy::Init", "request", request); mOwner = NS_STATIC_CAST(imgIRequest*, request); - - mObserver = aObserver; - // XXX we should save off the thread we are getting called on here so that we can proxy all calls to mDecoder to it. - + mListener = aObserver; mContext = cx; - // XXX we should only create a channel, etc if the image isn't finished loading already. + aLoadGroup->AddRequest(this, cx); + mLoadGroup = aLoadGroup; - nsISupports *inst = nsnull; - inst = new DummyChannel(this, aLoadGroup); - NS_ADDREF(inst); - nsresult res = inst->QueryInterface(NS_GET_IID(nsIChannel), getter_AddRefs(mDummyChannel)); - NS_RELEASE(inst); - - nsCOMPtr loadGroup; - mDummyChannel->GetLoadGroup(getter_AddRefs(loadGroup)); - if (loadGroup) { - loadGroup->AddRequest(mDummyChannel, cx); - } - - request->AddObserver(this); + request->AddProxy(this); return NS_OK; } @@ -102,7 +100,23 @@ nsresult imgRequestProxy::Init(imgRequest *request, nsILoadGroup *aLoadGroup, im /* readonly attribute wstring name; */ NS_IMETHODIMP imgRequestProxy::GetName(PRUnichar * *aName) { - return NS_ERROR_NOT_IMPLEMENTED; + nsAutoString name(NS_LITERAL_STRING("imgRequestProxy[")); + if (mOwner) { + nsCOMPtr uri; + mOwner->GetURI(getter_AddRefs(uri)); + if (uri) { + nsXPIDLCString spec; + uri->GetSpec(getter_Copies(spec)); + if (spec) + name.Append(NS_ConvertUTF8toUCS2(spec)); + } + } else { + name.Append(NS_LITERAL_STRING("(null)")); + } + name.Append(PRUnichar(']')); + + *aName = nsCRT::strdup(name.get()); + return NS_OK; } /* boolean isPending (); */ @@ -127,12 +141,12 @@ NS_IMETHODIMP imgRequestProxy::Cancel(nsresult status) mCanceled = PR_TRUE; - NS_ASSERTION(mOwner, "canceling request proxy twice"); - - nsresult rv = NS_REINTERPRET_CAST(imgRequest*, mOwner.get())->RemoveObserver(this, status); + nsresult rv = NS_REINTERPRET_CAST(imgRequest*, mOwner.get())->RemoveProxy(this, status); mOwner = nsnull; + mListener = nsnull; + return rv; } @@ -151,20 +165,20 @@ NS_IMETHODIMP imgRequestProxy::Resume() /* attribute nsILoadGroup loadGroup */ NS_IMETHODIMP imgRequestProxy::GetLoadGroup(nsILoadGroup **loadGroup) { - *loadGroup = nsnull; - return NS_OK; + NS_IF_ADDREF(*loadGroup = mLoadGroup.get()); + return NS_OK; } NS_IMETHODIMP imgRequestProxy::SetLoadGroup(nsILoadGroup *loadGroup) { - NS_NOTYETIMPLEMENTED("imgRequestProxy::SetLoadGroup"); - return NS_ERROR_NOT_IMPLEMENTED; + mLoadGroup = loadGroup; + return NS_OK; } /* attribute nsLoadFlags loadFlags */ NS_IMETHODIMP imgRequestProxy::GetLoadFlags(nsLoadFlags *flags) { - *flags = nsIRequest::LOAD_NORMAL; - return NS_OK; + *flags = nsIRequest::LOAD_NORMAL; + return NS_OK; } NS_IMETHODIMP imgRequestProxy::SetLoadFlags(nsLoadFlags flags) { @@ -210,7 +224,7 @@ NS_IMETHODIMP imgRequestProxy::GetURI(nsIURI **aURI) /* readonly attribute imgIDecoderObserver decoderObserver; */ NS_IMETHODIMP imgRequestProxy::GetDecoderObserver(imgIDecoderObserver **aDecoderObserver) { - *aDecoderObserver = mObserver; + *aDecoderObserver = mListener; NS_IF_ADDREF(*aDecoderObserver); return NS_OK; } @@ -224,8 +238,8 @@ NS_IMETHODIMP imgRequestProxy::FrameChanged(imgIContainer *container, nsISupport PR_LOG(gImgLog, PR_LOG_DEBUG, ("[this=%p] imgRequestProxy::FrameChanged\n", this)); - if (mObserver) - mObserver->FrameChanged(container, mContext, newframe, dirtyRect); + if (mListener) + mListener->FrameChanged(container, mContext, newframe, dirtyRect); return NS_OK; } @@ -238,8 +252,8 @@ NS_IMETHODIMP imgRequestProxy::OnStartDecode(imgIRequest *request, nsISupports * PR_LOG(gImgLog, PR_LOG_DEBUG, ("[this=%p] imgRequestProxy::OnStartDecode\n", this)); - if (mObserver) - mObserver->OnStartDecode(this, mContext); + if (mListener) + mListener->OnStartDecode(this, mContext); return NS_OK; } @@ -250,8 +264,8 @@ NS_IMETHODIMP imgRequestProxy::OnStartContainer(imgIRequest *request, nsISupport PR_LOG(gImgLog, PR_LOG_DEBUG, ("[this=%p] imgRequestProxy::OnStartContainer\n", this)); - if (mObserver) - mObserver->OnStartContainer(this, mContext, image); + if (mListener) + mListener->OnStartContainer(this, mContext, image); return NS_OK; } @@ -262,8 +276,8 @@ NS_IMETHODIMP imgRequestProxy::OnStartFrame(imgIRequest *request, nsISupports *c PR_LOG(gImgLog, PR_LOG_DEBUG, ("[this=%p] imgRequestProxy::OnStartFrame\n", this)); - if (mObserver) - mObserver->OnStartFrame(this, mContext, frame); + if (mListener) + mListener->OnStartFrame(this, mContext, frame); return NS_OK; } @@ -274,8 +288,8 @@ NS_IMETHODIMP imgRequestProxy::OnDataAvailable(imgIRequest *request, nsISupports PR_LOG(gImgLog, PR_LOG_DEBUG, ("[this=%p] imgRequestProxy::OnDataAvailable\n", this)); - if (mObserver) - mObserver->OnDataAvailable(this, mContext, frame, rect); + if (mListener) + mListener->OnDataAvailable(this, mContext, frame, rect); return NS_OK; } @@ -286,8 +300,8 @@ NS_IMETHODIMP imgRequestProxy::OnStopFrame(imgIRequest *request, nsISupports *cx PR_LOG(gImgLog, PR_LOG_DEBUG, ("[this=%p] imgRequestProxy::OnStopFrame\n", this)); - if (mObserver) - mObserver->OnStopFrame(this, mContext, frame); + if (mListener) + mListener->OnStopFrame(this, mContext, frame); return NS_OK; } @@ -298,8 +312,8 @@ NS_IMETHODIMP imgRequestProxy::OnStopContainer(imgIRequest *request, nsISupports PR_LOG(gImgLog, PR_LOG_DEBUG, ("[this=%p] imgRequestProxy::OnStopContainer\n", this)); - if (mObserver) - mObserver->OnStopContainer(this, mContext, image); + if (mListener) + mListener->OnStopContainer(this, mContext, image); return NS_OK; } @@ -310,8 +324,8 @@ NS_IMETHODIMP imgRequestProxy::OnStopDecode(imgIRequest *request, nsISupports *c PR_LOG(gImgLog, PR_LOG_DEBUG, ("[this=%p] imgRequestProxy::OnStopDecode\n", this)); - if (mObserver) - mObserver->OnStopDecode(this, mContext, status, statusArg); + if (mListener) + mListener->OnStopDecode(this, mContext, status, statusArg); return NS_OK; } @@ -323,22 +337,38 @@ NS_IMETHODIMP imgRequestProxy::OnStopDecode(imgIRequest *request, nsISupports *c /* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */ NS_IMETHODIMP imgRequestProxy::OnStartRequest(nsIRequest *request, nsISupports *ctxt) { +#ifdef PR_LOGGING + if (PR_LOG_TEST(gImgLog, PR_LOG_DEBUG)) { + nsXPIDLString name; + GetName(getter_Copies(name)); + PR_LOG(gImgLog, PR_LOG_DEBUG, + ("[this=%p] imgRequestProxy::OnStartRequest(%s)", + this, NS_ConvertUCS2toUTF8(name).get())); + } +#endif + return NS_OK; } /* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult statusCode, in wstring statusText); */ NS_IMETHODIMP imgRequestProxy::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult statusCode) { - if (!mDummyChannel) + /* it is ok to get multiple OnStopRequest messages */ + if (!mLoadGroup) return NS_OK; - nsCOMPtr loadGroup; - mDummyChannel->GetLoadGroup(getter_AddRefs(loadGroup)); - if (loadGroup) { - loadGroup->RemoveRequest(mDummyChannel, mContext, statusCode); +#ifdef PR_LOGGING + if (PR_LOG_TEST(gImgLog, PR_LOG_DEBUG)) { + nsXPIDLString name; + GetName(getter_Copies(name)); + PR_LOG(gImgLog, PR_LOG_DEBUG, + ("[this=%p] imgRequestProxy::OnStopRequest(%s)", + this, NS_ConvertUCS2toUTF8(name).get())); } - mDummyChannel = nsnull; +#endif + mLoadGroup->RemoveRequest(this, mContext, statusCode); + mLoadGroup = nsnull; return NS_OK; } diff --git a/mozilla/modules/libpr0n/src/imgRequestProxy.h b/mozilla/modules/libpr0n/src/imgRequestProxy.h index ae6e846227f..8dc6a41b835 100644 --- a/mozilla/modules/libpr0n/src/imgRequestProxy.h +++ b/mozilla/modules/libpr0n/src/imgRequestProxy.h @@ -58,13 +58,12 @@ public: nsresult Init(imgRequest *request, nsILoadGroup *aLoadGroup, imgIDecoderObserver *aObserver, nsISupports *cx); private: - nsCOMPtr mObserver; + nsCOMPtr mListener; nsCOMPtr mContext; - nsCOMPtr mOwner; - nsCOMPtr mDummyChannel; + nsCOMPtr mLoadGroup; PRBool mCanceled; }; diff --git a/mozilla/modules/libpr0n/src/makefile.win b/mozilla/modules/libpr0n/src/makefile.win index c019d02b53f..5bbedef244f 100644 --- a/mozilla/modules/libpr0n/src/makefile.win +++ b/mozilla/modules/libpr0n/src/makefile.win @@ -30,9 +30,8 @@ DLL = $(OBJDIR)\$(LIBRARY_NAME).dll MAKE_OBJ_TYPE = DLL OBJS = \ - .\$(OBJDIR)\DummyChannel.obj \ - .\$(OBJDIR)\ImageCache.obj \ .\$(OBJDIR)\ImageFactory.obj \ + .\$(OBJDIR)\imgCache.obj \ .\$(OBJDIR)\imgContainer.obj \ .\$(OBJDIR)\imgLoader.obj \ .\$(OBJDIR)\imgRequest.obj \