diff --git a/docshell/test/chrome/89419.html b/docshell/test/chrome/89419.html deleted file mode 100644 index b36b8d788cf..00000000000 --- a/docshell/test/chrome/89419.html +++ /dev/null @@ -1,7 +0,0 @@ - - -Bug 89419 - - - - diff --git a/docshell/test/chrome/Makefile.in b/docshell/test/chrome/Makefile.in index 825e6598ad9..8888d772aa9 100644 --- a/docshell/test/chrome/Makefile.in +++ b/docshell/test/chrome/Makefile.in @@ -44,9 +44,6 @@ include $(DEPTH)/config/autoconf.mk include $(topsrcdir)/config/rules.mk _HTTP_FILES = \ - bug89419.sjs \ - blue.png \ - red.png \ 92598_nostore.html \ 92598_nostore.html^headers^ \ 112564_nocache.html \ @@ -61,9 +58,6 @@ _HTTP_FILES = \ $(NULL) _TEST_FILES = \ - test_bug89419.xul \ - bug89419_window.xul \ - 89419.html \ test_bug92598.xul \ bug92598_window.xul \ 92598_nostore.html \ diff --git a/docshell/test/chrome/blue.png b/docshell/test/chrome/blue.png deleted file mode 100644 index 8df58f3a5fc..00000000000 Binary files a/docshell/test/chrome/blue.png and /dev/null differ diff --git a/docshell/test/chrome/bug89419.sjs b/docshell/test/chrome/bug89419.sjs deleted file mode 100644 index c075b1e504e..00000000000 --- a/docshell/test/chrome/bug89419.sjs +++ /dev/null @@ -1,13 +0,0 @@ -function handleRequest(request, response) -{ - var redirectstate = "/docshell/test/chrome/bug89419.sjs"; - response.setStatusLine("1.1", 302, "Found"); - if (getState(redirectstate) == "") { - response.setHeader("Location", "red.png", false); - setState(redirectstate, "red"); - } else { - response.setHeader("Location", "blue.png", false); - setState(redirectstate, ""); - } - response.setHeader("Cache-Control", "no-cache", false); -} diff --git a/docshell/test/chrome/bug89419_window.xul b/docshell/test/chrome/bug89419_window.xul deleted file mode 100644 index 11aa622d0bc..00000000000 --- a/docshell/test/chrome/bug89419_window.xul +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - diff --git a/docshell/test/chrome/red.png b/docshell/test/chrome/red.png deleted file mode 100644 index aa9ce252631..00000000000 Binary files a/docshell/test/chrome/red.png and /dev/null differ diff --git a/docshell/test/chrome/test_bug89419.xul b/docshell/test/chrome/test_bug89419.xul deleted file mode 100644 index ecd2ab382ca..00000000000 --- a/docshell/test/chrome/test_bug89419.xul +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - Test for Bug 89419 - - - - - - Mozilla Bug 89419 -

- -
-
- - - - -
diff --git a/modules/libpr0n/src/imgFrame.cpp b/modules/libpr0n/src/imgFrame.cpp index 6677a382984..d2c0eee0e84 100644 --- a/modules/libpr0n/src/imgFrame.cpp +++ b/modules/libpr0n/src/imgFrame.cpp @@ -69,6 +69,9 @@ static PRUint32 gTotalDDBSize = 0; // Returns true if an image of aWidth x aHeight is allowed and legal. static PRBool AllowedImageSize(PRInt32 aWidth, PRInt32 aHeight) { + NS_ASSERTION(aWidth > 0, "invalid image width"); + NS_ASSERTION(aHeight > 0, "invalid image height"); + // reject over-wide or over-tall images const PRInt32 k64KLimit = 0x0000FFFF; if (NS_UNLIKELY(aWidth > k64KLimit || aHeight > k64KLimit )) { @@ -76,8 +79,9 @@ static PRBool AllowedImageSize(PRInt32 aWidth, PRInt32 aHeight) return PR_FALSE; } - // protect against invalid sizes - if (NS_UNLIKELY(aHeight <= 0 || aWidth <= 0)) { + // protect against division by zero - this really shouldn't happen + // if our consumers were well behaved, but they aren't (bug 368427) + if (NS_UNLIKELY(aHeight == 0)) { return PR_FALSE; } diff --git a/modules/libpr0n/src/imgLoader.cpp b/modules/libpr0n/src/imgLoader.cpp index bbc9d13c281..4546ee13229 100644 --- a/modules/libpr0n/src/imgLoader.cpp +++ b/modules/libpr0n/src/imgLoader.cpp @@ -276,6 +276,35 @@ public: NS_IMPL_ISUPPORTS1(imgMemoryReporter, nsIMemoryReporter) + +/** + * A class that implements nsIProgressEventSink and forwards all calls to it to + * the original notification callbacks of the channel. Also implements + * nsIInterfaceRequestor and gives out itself for nsIProgressEventSink calls, + * and forwards everything else to the channel's notification callbacks. + */ +class nsProgressNotificationProxy : public nsIProgressEventSink + , public nsIChannelEventSink + , public nsIInterfaceRequestor +{ + public: + nsProgressNotificationProxy(nsIChannel* channel, + imgIRequest* proxy) + : mImageRequest(proxy) { + channel->GetNotificationCallbacks(getter_AddRefs(mOriginalCallbacks)); + } + + NS_DECL_ISUPPORTS + NS_DECL_NSIPROGRESSEVENTSINK + NS_DECL_NSICHANNELEVENTSINK + NS_DECL_NSIINTERFACEREQUESTOR + private: + ~nsProgressNotificationProxy() {} + + nsCOMPtr mOriginalCallbacks; + nsCOMPtr mImageRequest; +}; + NS_IMPL_ISUPPORTS3(nsProgressNotificationProxy, nsIProgressEventSink, nsIChannelEventSink, @@ -285,8 +314,7 @@ NS_IMETHODIMP nsProgressNotificationProxy::OnProgress(nsIRequest* request, nsISupports* ctxt, PRUint64 progress, - PRUint64 progressMax) -{ + PRUint64 progressMax) { nsCOMPtr loadGroup; request->GetLoadGroup(getter_AddRefs(loadGroup)); @@ -304,8 +332,7 @@ NS_IMETHODIMP nsProgressNotificationProxy::OnStatus(nsIRequest* request, nsISupports* ctxt, nsresult status, - const PRUnichar* statusArg) -{ + const PRUnichar* statusArg) { nsCOMPtr loadGroup; request->GetLoadGroup(getter_AddRefs(loadGroup)); @@ -323,8 +350,7 @@ NS_IMETHODIMP nsProgressNotificationProxy::AsyncOnChannelRedirect(nsIChannel *oldChannel, nsIChannel *newChannel, PRUint32 flags, - nsIAsyncVerifyRedirectCallback *cb) -{ + nsIAsyncVerifyRedirectCallback *cb) { // Tell the original original callbacks about it too nsCOMPtr loadGroup; newChannel->GetLoadGroup(getter_AddRefs(loadGroup)); @@ -344,8 +370,7 @@ nsProgressNotificationProxy::AsyncOnChannelRedirect(nsIChannel *oldChannel, NS_IMETHODIMP nsProgressNotificationProxy::GetInterface(const nsIID& iid, - void** result) -{ + void** result) { if (iid.Equals(NS_GET_IID(nsIProgressEventSink))) { *result = static_cast(this); NS_ADDREF_THIS(); @@ -361,13 +386,17 @@ nsProgressNotificationProxy::GetInterface(const nsIID& iid, return NS_NOINTERFACE; } -static PRBool NewRequestAndEntry(imgRequest **request, imgCacheEntry **entry) +static PRBool NewRequestAndEntry(nsIURI *uri, imgRequest **request, imgCacheEntry **entry) { + // If file, force revalidation on expiration + PRBool isFile; + uri->SchemeIs("file", &isFile); + *request = new imgRequest(); if (!*request) return PR_FALSE; - *entry = new imgCacheEntry(*request); + *entry = new imgCacheEntry(*request, /* mustValidateIfExpired = */ isFile); if (!*entry) { delete *request; return PR_FALSE; @@ -391,9 +420,6 @@ static PRBool ShouldRevalidateEntry(imgCacheEntry *aEntry, if (aFlags & nsIRequest::VALIDATE_ALWAYS) { bValidateEntry = PR_TRUE; } - else if (aEntry->GetMustValidate()) { - bValidateEntry = PR_TRUE; - } // // The cache entry has expired... Determine whether the stale cache // entry can be used without validation... @@ -407,7 +433,7 @@ static PRBool ShouldRevalidateEntry(imgCacheEntry *aEntry, if (aFlags & (nsIRequest::VALIDATE_NEVER | nsIRequest::VALIDATE_ONCE_PER_SESSION)) { - bValidateEntry = PR_FALSE; + bValidateEntry = aEntry->GetMustValidateIfExpired(); } // // LOAD_FROM_CACHE allows a stale cache entry to be used... Otherwise, @@ -495,15 +521,13 @@ static PRUint32 SecondsFromPRTime(PRTime prTime) return PRUint32(PRInt64(prTime) / PRInt64(PR_USEC_PER_SEC)); } -imgCacheEntry::imgCacheEntry(imgRequest *request) +imgCacheEntry::imgCacheEntry(imgRequest *request, PRBool mustValidateIfExpired /* = PR_FALSE */) : mRequest(request), mDataSize(0), mTouchedTime(SecondsFromPRTime(PR_Now())), mExpiryTime(0), - mMustValidate(PR_FALSE), - // We start off as evicted so we don't try to update the cache. PutIntoCache - // will set this to false. - mEvicted(PR_TRUE), + mMustValidateIfExpired(mustValidateIfExpired), + mEvicted(PR_FALSE), mHasNoProxies(PR_TRUE) {} @@ -1174,9 +1198,6 @@ PRBool imgLoader::ValidateRequestWithNewChannel(imgRequest *request, return NS_SUCCEEDED(rv); } else { - // We will rely on Necko to cache this request when it's possible, and to - // tell imgCacheValidator::OnStartRequest whether the request came from its - // cache. nsCOMPtr newChannel; rv = NewImageChannel(getter_AddRefs(newChannel), aURI, @@ -1190,6 +1211,16 @@ PRBool imgLoader::ValidateRequestWithNewChannel(imgRequest *request, return PR_FALSE; } + nsCOMPtr cacheChan(do_QueryInterface(newChannel)); + + if (cacheChan) { + // since this channel supports nsICachingChannel, we can ask it + // to only stream us data if the data comes off the net. + PRUint32 loadFlags; + if (NS_SUCCEEDED(newChannel->GetLoadFlags(&loadFlags))) + newChannel->SetLoadFlags(loadFlags | nsICachingChannel::LOAD_ONLY_IF_MODIFIED); + } + nsCOMPtr req; rv = CreateNewProxyForRequest(request, aLoadGroup, aObserver, aLoadFlags, aExistingRequest, getter_AddRefs(req)); @@ -1198,18 +1229,18 @@ PRBool imgLoader::ValidateRequestWithNewChannel(imgRequest *request, } // Make sure that OnStatus/OnProgress calls have the right request set... - nsRefPtr progressproxy = - new nsProgressNotificationProxy(newChannel, req); - if (!progressproxy) + nsCOMPtr requestor( + new nsProgressNotificationProxy(newChannel, req)); + if (!requestor) return PR_FALSE; + newChannel->SetNotificationCallbacks(requestor); - nsRefPtr hvc = new imgCacheValidator(progressproxy, request, aCX); + imgCacheValidator *hvc = new imgCacheValidator(request, aCX); if (!hvc) { return PR_FALSE; } - newChannel->SetNotificationCallbacks(hvc); - + NS_ADDREF(hvc); request->mValidator = hvc; imgRequestProxy* proxy = static_cast @@ -1228,6 +1259,8 @@ PRBool imgLoader::ValidateRequestWithNewChannel(imgRequest *request, if (NS_SUCCEEDED(rv)) NS_ADDREF(*aProxyRequest = req.get()); + NS_RELEASE(hvc); + return NS_SUCCEEDED(rv); } } @@ -1600,7 +1633,7 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, if (NS_FAILED(rv)) return NS_ERROR_FAILURE; - if (!NewRequestAndEntry(getter_AddRefs(request), getter_AddRefs(entry))) + if (!NewRequestAndEntry(aURI, getter_AddRefs(request), getter_AddRefs(entry))) return NS_ERROR_OUT_OF_MEMORY; PR_LOG(gImgLog, PR_LOG_DEBUG, @@ -1792,7 +1825,7 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb requestFlags, nsnull, _retval); static_cast(*_retval)->NotifyListener(); } else { - if (!NewRequestAndEntry(getter_AddRefs(request), getter_AddRefs(entry))) + if (!NewRequestAndEntry(uri, getter_AddRefs(request), getter_AddRefs(entry))) return NS_ERROR_OUT_OF_MEMORY; // We use originalURI here to fulfil the imgIRequest contract on GetURI. @@ -1809,7 +1842,7 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb NS_RELEASE(pl); // Try to add the new request into the cache. - PutIntoCache(originalURI, entry); + PutIntoCache(uri, entry); rv = CreateNewProxyForRequest(request, loadGroup, aObserver, requestFlags, nsnull, _retval); @@ -1998,20 +2031,14 @@ NS_IMETHODIMP ProxyListener::OnDataAvailable(nsIRequest *aRequest, nsISupports * * http validate class. check a channel for a 304 */ -NS_IMPL_ISUPPORTS5(imgCacheValidator, nsIStreamListener, nsIRequestObserver, - nsIChannelEventSink, nsIInterfaceRequestor, - nsIAsyncVerifyRedirectCallback) +NS_IMPL_ISUPPORTS2(imgCacheValidator, nsIStreamListener, nsIRequestObserver) imgLoader imgCacheValidator::sImgLoader; -imgCacheValidator::imgCacheValidator(nsProgressNotificationProxy* progress, - imgRequest *request, void *aContext) - : mProgressProxy(progress), - mRequest(request), - mContext(aContext) -{ - NewRequestAndEntry(getter_AddRefs(mNewRequest), getter_AddRefs(mNewEntry)); -} +imgCacheValidator::imgCacheValidator(imgRequest *request, void *aContext) : + mRequest(request), + mContext(aContext) +{} imgCacheValidator::~imgCacheValidator() { @@ -2034,22 +2061,14 @@ void imgCacheValidator::AddProxy(imgRequestProxy *aProxy) /* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt) { - // If this request is coming from cache and has the same URI as our - // imgRequest, the request all our proxies are pointing at is valid, and all - // we have to do is tell them to notify their listeners. + // If this request is coming from cache, the request all our proxies are + // pointing at is valid, and all we have to do is tell them to notify their + // listeners. nsCOMPtr cacheChan(do_QueryInterface(aRequest)); - nsCOMPtr channel(do_QueryInterface(aRequest)); - if (cacheChan && channel) { - PRBool isFromCache = PR_FALSE; - cacheChan->IsFromCache(&isFromCache); + if (cacheChan) { + PRBool isFromCache; + if (NS_SUCCEEDED(cacheChan->IsFromCache(&isFromCache)) && isFromCache) { - nsCOMPtr channelURI; - PRBool sameURI = PR_FALSE; - channel->GetURI(getter_AddRefs(channelURI)); - if (channelURI) - channelURI->Equals(mRequest->mCurrentURI, &sameURI); - - if (isFromCache && sameURI) { PRUint32 count = mProxies.Count(); for (PRInt32 i = count-1; i>=0; i--) { imgRequestProxy *proxy = static_cast(mProxies[i]); @@ -2066,24 +2085,21 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport proxy->SyncNotifyListener(); } - // We don't need to load this any more. - aRequest->Cancel(NS_BINDING_ABORTED); - mRequest->SetLoadId(mContext); mRequest->mValidator = nsnull; mRequest = nsnull; - mNewRequest = nsnull; - mNewEntry = nsnull; - return NS_OK; } } // We can't load out of cache. We have to create a whole new request for the // data that's coming in off the channel. + nsCOMPtr channel(do_QueryInterface(aRequest)); + nsRefPtr entry; nsCOMPtr uri; + mRequest->GetURI(getter_AddRefs(uri)); #if defined(PR_LOGGING) @@ -2098,24 +2114,34 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport mRequest->mValidator = nsnull; mRequest = nsnull; + imgRequest *request; + + if (!NewRequestAndEntry(uri, &request, getter_AddRefs(entry))) + return NS_ERROR_OUT_OF_MEMORY; + // We use originalURI here to fulfil the imgIRequest contract on GetURI. nsCOMPtr originalURI; channel->GetOriginalURI(getter_AddRefs(originalURI)); - mNewRequest->Init(originalURI, uri, channel, channel, mNewEntry, NS_GetCurrentThread(), mContext); + request->Init(originalURI, uri, channel, channel, entry, NS_GetCurrentThread(), mContext); - ProxyListener *pl = new ProxyListener(static_cast(mNewRequest)); + ProxyListener *pl = new ProxyListener(static_cast(request)); + if (!pl) { + request->CancelAndAbort(NS_ERROR_OUT_OF_MEMORY); + NS_RELEASE(request); + return NS_ERROR_OUT_OF_MEMORY; + } mDestListener = static_cast(pl); // Try to add the new request into the cache. Note that the entry must be in // the cache before the proxies' ownership changes, because adding a proxy // changes the caching behaviour for imgRequests. - sImgLoader.PutIntoCache(originalURI, mNewEntry); + sImgLoader.PutIntoCache(uri, entry); PRUint32 count = mProxies.Count(); for (PRInt32 i = count-1; i>=0; i--) { imgRequestProxy *proxy = static_cast(mProxies[i]); - proxy->ChangeOwner(mNewRequest); + proxy->ChangeOwner(request); // Proxies waiting on cache validation should be deferring notifications. // Undefer them. @@ -2129,8 +2155,10 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport proxy->SyncNotifyListener(); } - mNewRequest = nsnull; - mNewEntry = nsnull; + NS_RELEASE(request); + + if (!mDestListener) + return NS_OK; return mDestListener->OnStartRequest(aRequest, ctxt); } @@ -2150,6 +2178,15 @@ NS_IMETHODIMP imgCacheValidator::OnStopRequest(nsIRequest *aRequest, nsISupports /* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long sourceOffset, in unsigned long count); */ NS_IMETHODIMP imgCacheValidator::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count) { +#ifdef DEBUG + nsCOMPtr cacheChan(do_QueryInterface(aRequest)); + if (cacheChan) { + PRBool isFromCache; + if (NS_SUCCEEDED(cacheChan->IsFromCache(&isFromCache)) && isFromCache) + NS_ERROR("OnDataAvailable not suppressed by LOAD_ONLY_IF_MODIFIED load flag"); + } +#endif + if (!mDestListener) { // XXX see bug 113959 PRUint32 _retval; @@ -2159,62 +2196,3 @@ NS_IMETHODIMP imgCacheValidator::OnDataAvailable(nsIRequest *aRequest, nsISuppor return mDestListener->OnDataAvailable(aRequest, ctxt, inStr, sourceOffset, count); } - -/** nsIInterfaceRequestor methods **/ - -NS_IMETHODIMP imgCacheValidator::GetInterface(const nsIID & aIID, void **aResult) -{ - if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) - return QueryInterface(aIID, aResult); - - return mProgressProxy->GetInterface(aIID, aResult); -} - -// These functions are materially the same as the same functions in imgRequest. -// We duplicate them because we're verifying whether cache loads are necessary, -// not unconditionally loading. - -/** nsIChannelEventSink methods **/ -NS_IMETHODIMP imgCacheValidator::AsyncOnChannelRedirect(nsIChannel *oldChannel, - nsIChannel *newChannel, PRUint32 flags, - nsIAsyncVerifyRedirectCallback *callback) -{ - // Note all cache information we get from the old channel. - mNewRequest->SetCacheValidation(mNewEntry, oldChannel); - - // Prepare for callback - mRedirectCallback = callback; - mRedirectChannel = newChannel; - - return mProgressProxy->AsyncOnChannelRedirect(oldChannel, newChannel, flags, this); -} - -NS_IMETHODIMP imgCacheValidator::OnRedirectVerifyCallback(nsresult aResult) -{ - // If we've already been told to abort, just do so. - if (NS_FAILED(aResult)) { - mRedirectCallback->OnRedirectVerifyCallback(aResult); - mRedirectCallback = nsnull; - mRedirectChannel = nsnull; - return NS_OK; - } - - // make sure we have a protocol that returns data rather than opens - // an external application, e.g. mailto: - nsCOMPtr uri; - mRedirectChannel->GetURI(getter_AddRefs(uri)); - PRBool doesNotReturnData = PR_FALSE; - NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, - &doesNotReturnData); - - nsresult result = NS_OK; - - if (doesNotReturnData) { - result = NS_ERROR_ABORT; - } - - mRedirectCallback->OnRedirectVerifyCallback(result); - mRedirectCallback = nsnull; - mRedirectChannel = nsnull; - return NS_OK; -} diff --git a/modules/libpr0n/src/imgLoader.h b/modules/libpr0n/src/imgLoader.h index 0d89c5217e4..16d2bbcb982 100644 --- a/modules/libpr0n/src/imgLoader.h +++ b/modules/libpr0n/src/imgLoader.h @@ -52,8 +52,6 @@ #include "imgRequest.h" #include "nsIObserverService.h" #include "nsIChannelPolicy.h" -#include "nsIProgressEventSink.h" -#include "nsIChannel.h" #ifdef LOADER_THREADSAFE #include "prlock.h" @@ -68,7 +66,7 @@ class nsILoadGroup; class imgCacheEntry { public: - imgCacheEntry(imgRequest *request); + imgCacheEntry(imgRequest *request, PRBool mustValidateIfExpired = PR_FALSE); ~imgCacheEntry(); nsrefcnt AddRef() @@ -125,13 +123,13 @@ public: Touch(); } - PRBool GetMustValidate() const + PRBool GetMustValidateIfExpired() const { - return mMustValidate; + return mMustValidateIfExpired; } - void SetMustValidate(PRBool aValidate) + void SetMustValidateIfExpired(PRBool aValidate) { - mMustValidate = aValidate; + mMustValidateIfExpired = aValidate; Touch(); } @@ -180,7 +178,7 @@ private: // data PRInt32 mTouchedTime; PRInt32 mExpiryTime; nsExpirationState mExpirationState; - PRPackedBool mMustValidate : 1; + PRPackedBool mMustValidateIfExpired : 1; PRPackedBool mEvicted : 1; PRPackedBool mHasNoProxies : 1; }; @@ -376,33 +374,6 @@ private: nsCOMPtr mDestListener; }; -/** - * A class that implements nsIProgressEventSink and forwards all calls to it to - * the original notification callbacks of the channel. Also implements - * nsIInterfaceRequestor and gives out itself for nsIProgressEventSink calls, - * and forwards everything else to the channel's notification callbacks. - */ -class nsProgressNotificationProxy : public nsIProgressEventSink - , public nsIChannelEventSink - , public nsIInterfaceRequestor -{ - public: - nsProgressNotificationProxy(nsIChannel* channel, - imgIRequest* proxy) - : mImageRequest(proxy) { - channel->GetNotificationCallbacks(getter_AddRefs(mOriginalCallbacks)); - } - - NS_DECL_ISUPPORTS - NS_DECL_NSIPROGRESSEVENTSINK - NS_DECL_NSICHANNELEVENTSINK - NS_DECL_NSIINTERFACEREQUESTOR - private: - ~nsProgressNotificationProxy() {} - - nsCOMPtr mOriginalCallbacks; - nsCOMPtr mImageRequest; -}; /** * validate checker @@ -410,36 +381,25 @@ class nsProgressNotificationProxy : public nsIProgressEventSink #include "nsCOMArray.h" -class imgCacheValidator : public nsIStreamListener, - public nsIChannelEventSink, - public nsIInterfaceRequestor, - public nsIAsyncVerifyRedirectCallback +class imgCacheValidator : public nsIStreamListener { public: - imgCacheValidator(nsProgressNotificationProxy* progress, imgRequest *request, void *aContext); + imgCacheValidator(imgRequest *request, void *aContext); virtual ~imgCacheValidator(); void AddProxy(imgRequestProxy *aProxy); + /* additional members */ NS_DECL_ISUPPORTS NS_DECL_NSISTREAMLISTENER NS_DECL_NSIREQUESTOBSERVER - NS_DECL_NSICHANNELEVENTSINK - NS_DECL_NSIINTERFACEREQUESTOR - NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK private: nsCOMPtr mDestListener; - nsRefPtr mProgressProxy; - nsCOMPtr mRedirectCallback; - nsCOMPtr mRedirectChannel; nsRefPtr mRequest; nsCOMArray mProxies; - nsRefPtr mNewRequest; - nsRefPtr mNewEntry; - void *mContext; static imgLoader sImgLoader; diff --git a/modules/libpr0n/src/imgRequest.cpp b/modules/libpr0n/src/imgRequest.cpp index 44d2521b546..ca0553e4560 100644 --- a/modules/libpr0n/src/imgRequest.cpp +++ b/modules/libpr0n/src/imgRequest.cpp @@ -191,16 +191,16 @@ imgRequest::imgRequest() : imgRequest::~imgRequest() { - if (mURI) { + if (mKeyURI) { nsCAutoString spec; - mURI->GetSpec(spec); + mKeyURI->GetSpec(spec); LOG_FUNC_WITH_PARAM(gImgLog, "imgRequest::~imgRequest()", "keyuri", spec.get()); } else LOG_FUNC(gImgLog, "imgRequest::~imgRequest()"); } nsresult imgRequest::Init(nsIURI *aURI, - nsIURI *aCurrentURI, + nsIURI *aKeyURI, nsIRequest *aRequest, nsIChannel *aChannel, imgCacheEntry *aCacheEntry, @@ -211,7 +211,7 @@ nsresult imgRequest::Init(nsIURI *aURI, NS_ABORT_IF_FALSE(!mImage, "Multiple calls to init"); NS_ABORT_IF_FALSE(aURI, "No uri"); - NS_ABORT_IF_FALSE(aCurrentURI, "No current uri"); + NS_ABORT_IF_FALSE(aKeyURI, "No key uri"); NS_ABORT_IF_FALSE(aRequest, "No request"); NS_ABORT_IF_FALSE(aChannel, "No channel"); @@ -220,7 +220,7 @@ nsresult imgRequest::Init(nsIURI *aURI, mStatusTracker = new imgStatusTracker(nsnull); mURI = aURI; - mCurrentURI = aCurrentURI; + mKeyURI = aKeyURI; mRequest = aRequest; mChannel = aChannel; mTimedChannel = do_QueryInterface(mChannel); @@ -281,8 +281,8 @@ nsresult imgRequest::AddProxy(imgRequestProxy *proxy) // If we're empty before adding, we have to tell the loader we now have // proxies. if (mObservers.IsEmpty()) { - NS_ABORT_IF_FALSE(mURI, "Trying to SetHasProxies without key uri."); - imgLoader::SetHasProxies(mURI); + NS_ABORT_IF_FALSE(mKeyURI, "Trying to SetHasProxies without key uri."); + imgLoader::SetHasProxies(mKeyURI); } // If we don't have any current observers, we should restart any animation. @@ -322,14 +322,14 @@ nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus, PRBoo // been cancelled and thus removed from the cache, tell the image loader so // we can be evicted from the cache. if (mCacheEntry) { - NS_ABORT_IF_FALSE(mURI, "Removing last observer without key uri."); + NS_ABORT_IF_FALSE(mKeyURI, "Removing last observer without key uri."); - imgLoader::SetHasNoProxies(mURI, mCacheEntry); + imgLoader::SetHasNoProxies(mKeyURI, mCacheEntry); } #if defined(PR_LOGGING) else { nsCAutoString spec; - mURI->GetSpec(spec); + mKeyURI->GetSpec(spec); LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::RemoveProxy no cache entry", "uri", spec.get()); } #endif @@ -410,8 +410,8 @@ nsresult imgRequest::GetKeyURI(nsIURI **aKeyURI) { LOG_FUNC(gImgLog, "imgRequest::GetKeyURI"); - if (mURI) { - *aKeyURI = mURI; + if (mKeyURI) { + *aKeyURI = mKeyURI; NS_ADDREF(*aKeyURI); return NS_OK; } @@ -438,7 +438,7 @@ void imgRequest::RemoveFromCache() if (mCacheEntry) imgLoader::RemoveFromCache(mCacheEntry); else - imgLoader::RemoveFromCache(mURI); + imgLoader::RemoveFromCache(mKeyURI); } mCacheEntry = nsnull; @@ -507,71 +507,6 @@ void imgRequest::UpdateCacheEntrySize() } } -void imgRequest::SetCacheValidation(imgCacheEntry* aCacheEntry, nsIRequest* aRequest) -{ - /* get the expires info */ - if (aCacheEntry) { - nsCOMPtr cacheChannel(do_QueryInterface(aRequest)); - if (cacheChannel) { - nsCOMPtr cacheToken; - cacheChannel->GetCacheToken(getter_AddRefs(cacheToken)); - if (cacheToken) { - nsCOMPtr entryDesc(do_QueryInterface(cacheToken)); - if (entryDesc) { - PRUint32 expiration; - /* get the expiration time from the caching channel's token */ - entryDesc->GetExpirationTime(&expiration); - - // Expiration time defaults to 0. We set the expiration time on our - // entry if it hasn't been set yet. - if (aCacheEntry->GetExpiryTime() == 0) - aCacheEntry->SetExpiryTime(expiration); - } - } - } - - // Determine whether the cache entry must be revalidated when we try to use it. - // Currently, only HTTP specifies this information... - nsCOMPtr httpChannel(do_QueryInterface(aRequest)); - if (httpChannel) { - PRBool bMustRevalidate = PR_FALSE; - - httpChannel->IsNoStoreResponse(&bMustRevalidate); - - if (!bMustRevalidate) { - httpChannel->IsNoCacheResponse(&bMustRevalidate); - } - - if (!bMustRevalidate) { - nsCAutoString cacheHeader; - - httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Cache-Control"), - cacheHeader); - if (PL_strcasestr(cacheHeader.get(), "must-revalidate")) { - bMustRevalidate = PR_TRUE; - } - } - - // Cache entries default to not needing to validate. We ensure that - // multiple calls to this function don't override an earlier decision to - // validate by making validation a one-way decision. - if (bMustRevalidate) - aCacheEntry->SetMustValidate(bMustRevalidate); - } - - // We always need to validate file URIs. - nsCOMPtr channel = do_QueryInterface(aRequest); - if (channel) { - nsCOMPtr uri; - channel->GetURI(getter_AddRefs(uri)); - PRBool isfile = PR_FALSE; - uri->SchemeIs("file", &isfile); - if (isfile) - aCacheEntry->SetMustValidate(isfile); - } - } -} - nsresult imgRequest::LockImage() { @@ -815,6 +750,8 @@ NS_IMETHODIMP imgRequest::OnDiscard(imgIRequest *aRequest) /* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */ NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt) { + nsresult rv; + LOG_SCOPE(gImgLog, "imgRequest::OnStartRequest"); // Figure out if we're multipart @@ -886,7 +823,55 @@ NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt } } - SetCacheValidation(mCacheEntry, aRequest); + /* get the expires info */ + if (mCacheEntry) { + nsCOMPtr cacheChannel(do_QueryInterface(aRequest)); + if (cacheChannel) { + nsCOMPtr cacheToken; + cacheChannel->GetCacheToken(getter_AddRefs(cacheToken)); + if (cacheToken) { + nsCOMPtr entryDesc(do_QueryInterface(cacheToken)); + if (entryDesc) { + PRUint32 expiration; + /* get the expiration time from the caching channel's token */ + entryDesc->GetExpirationTime(&expiration); + + /* set the expiration time on our entry */ + mCacheEntry->SetExpiryTime(expiration); + } + } + } + // + // Determine whether the cache entry must be revalidated when it expires. + // If so, then the cache entry must *not* be used during HISTORY loads if + // it has expired. + // + // Currently, only HTTP specifies this information... + // + nsCOMPtr httpChannel(do_QueryInterface(aRequest)); + if (httpChannel) { + PRBool bMustRevalidate = PR_FALSE; + + rv = httpChannel->IsNoStoreResponse(&bMustRevalidate); + + if (!bMustRevalidate) { + rv = httpChannel->IsNoCacheResponse(&bMustRevalidate); + } + + if (!bMustRevalidate) { + nsCAutoString cacheHeader; + + rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Cache-Control"), + cacheHeader); + if (PL_strcasestr(cacheHeader.get(), "must-revalidate")) { + bMustRevalidate = PR_TRUE; + } + } + + mCacheEntry->SetMustValidateIfExpired(bMustRevalidate); + } + } + // Shouldn't we be dead already if this gets hit? Probably multipart/x-mixed-replace... if (mObservers.IsEmpty()) { @@ -1254,8 +1239,6 @@ imgRequest::AsyncOnChannelRedirect(nsIChannel *oldChannel, NS_ASSERTION(mChannel == oldChannel, "Got a channel redirect for an unknown channel!"); NS_ASSERTION(newChannel, "Got a redirect to a NULL channel!"); - SetCacheValidation(mCacheEntry, oldChannel); - // Prepare for callback mRedirectCallback = callback; mNewRedirectChannel = newChannel; @@ -1270,7 +1253,7 @@ imgRequest::AsyncOnChannelRedirect(nsIChannel *oldChannel, } return rv; } - + (void) OnRedirectVerifyCallback(NS_OK); return NS_OK; } @@ -1280,7 +1263,7 @@ imgRequest::OnRedirectVerifyCallback(nsresult result) { NS_ASSERTION(mRedirectCallback, "mRedirectCallback not set in callback"); NS_ASSERTION(mNewRedirectChannel, "mNewRedirectChannel not set in callback"); - + if (NS_FAILED(result)) { mRedirectCallback->OnRedirectVerifyCallback(result); mRedirectCallback = nsnull; @@ -1292,19 +1275,21 @@ imgRequest::OnRedirectVerifyCallback(nsresult result) mTimedChannel = do_QueryInterface(mChannel); mNewRedirectChannel = nsnull; -#if defined(PR_LOGGING) + // Don't make any cache changes if we're going to point to the same thing. We + // compare specs and not just URIs here because URIs that compare as + // .Equals() might have different hashes. nsCAutoString oldspec; - if (mCurrentURI) - mCurrentURI->GetSpec(oldspec); + if (mKeyURI) + mKeyURI->GetSpec(oldspec); LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::OnChannelRedirect", "old", oldspec.get()); -#endif // make sure we have a protocol that returns data rather than opens // an external application, e.g. mailto: - mChannel->GetURI(getter_AddRefs(mCurrentURI)); + nsCOMPtr uri; + mChannel->GetURI(getter_AddRefs(uri)); PRBool doesNotReturnData = PR_FALSE; nsresult rv = - NS_URIChainHasFlags(mCurrentURI, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, + NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_DOES_NOT_RETURN_DATA, &doesNotReturnData); if (NS_SUCCEEDED(rv) && doesNotReturnData) @@ -1316,6 +1301,34 @@ imgRequest::OnRedirectVerifyCallback(nsresult result) return NS_OK; } + nsCOMPtr newURI; + mChannel->GetOriginalURI(getter_AddRefs(newURI)); + nsCAutoString newspec; + if (newURI) + newURI->GetSpec(newspec); + LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::OnChannelRedirect", "new", newspec.get()); + + if (oldspec != newspec) { + if (mIsInCache) { + // Remove the cache entry from the cache, but don't null out mCacheEntry + // (as imgRequest::RemoveFromCache() does), because we need it to put + // ourselves back in the cache. + if (mCacheEntry) + imgLoader::RemoveFromCache(mCacheEntry); + else + imgLoader::RemoveFromCache(mKeyURI); + } + + mKeyURI = newURI; + + if (mIsInCache) { + // If we don't still have a URI or cache entry, we don't want to put + // ourselves back into the cache. + if (mKeyURI && mCacheEntry) + imgLoader::PutIntoCache(mKeyURI, mCacheEntry); + } + } + mRedirectCallback->OnRedirectVerifyCallback(NS_OK); mRedirectCallback = nsnull; return NS_OK; diff --git a/modules/libpr0n/src/imgRequest.h b/modules/libpr0n/src/imgRequest.h index 338bcaf6b28..962b470666f 100644 --- a/modules/libpr0n/src/imgRequest.h +++ b/modules/libpr0n/src/imgRequest.h @@ -90,7 +90,7 @@ public: NS_DECL_ISUPPORTS nsresult Init(nsIURI *aURI, - nsIURI *aCurrentURI, + nsIURI *aKeyURI, nsIRequest *aRequest, nsIChannel *aChannel, imgCacheEntry *aCacheEntry, @@ -129,12 +129,6 @@ public: return mWindowId; } - // Set the cache validation information (expiry time, whether we must - // validate, etc) on the cache entry based on the request information. - // If this function is called multiple times, the information set earliest - // wins. - static void SetCacheValidation(imgCacheEntry* aEntry, nsIRequest* aRequest); - private: friend class imgCacheEntry; friend class imgRequestProxy; @@ -211,11 +205,10 @@ private: friend class imgMemoryReporter; nsCOMPtr mRequest; - // The original URI we were loaded with. This is the same as the URI we are - // keyed on in the cache. + // The original URI we were loaded with. nsCOMPtr mURI; - // The URI of the resource we ended up loading after all redirects, etc. - nsCOMPtr mCurrentURI; + // The URI we are keyed on in the cache. + nsCOMPtr mKeyURI; nsCOMPtr mPrincipal; // Status-tracker -- transferred to mImage, when it gets instantiated nsAutoPtr mStatusTracker; diff --git a/modules/libpr0n/test/crashtests/256-height.ico b/modules/libpr0n/test/crashtests/256-height.ico deleted file mode 100644 index 6a3c5c19445..00000000000 Binary files a/modules/libpr0n/test/crashtests/256-height.ico and /dev/null differ diff --git a/modules/libpr0n/test/crashtests/256-width.ico b/modules/libpr0n/test/crashtests/256-width.ico deleted file mode 100644 index a82983ce4f0..00000000000 Binary files a/modules/libpr0n/test/crashtests/256-width.ico and /dev/null differ diff --git a/modules/libpr0n/test/crashtests/crashtests.list b/modules/libpr0n/test/crashtests/crashtests.list index 54220049e59..555524157a1 100644 --- a/modules/libpr0n/test/crashtests/crashtests.list +++ b/modules/libpr0n/test/crashtests/crashtests.list @@ -13,8 +13,3 @@ load delaytest.html?523528-2.gif # this would have exposed the leak discovered in bug 642902 load invalid-icc-profile.jpg - -# maximum (256) width and height icons that we currently (due to bug 668068) -# interpret as 0-width and 0-height. -load 256-width.ico -load 256-height.ico diff --git a/modules/libpr0n/test/mochitest/Makefile.in b/modules/libpr0n/test/mochitest/Makefile.in index 4ed09db18f4..764e15de501 100644 --- a/modules/libpr0n/test/mochitest/Makefile.in +++ b/modules/libpr0n/test/mochitest/Makefile.in @@ -76,13 +76,6 @@ _TEST_FILES = imgutils.js \ test_bug614392.html \ test_bug657191.html \ bug657191.sjs \ - bug89419-iframe.html \ - bug89419.sjs \ - test_bug89419-1.html \ - test_bug89419-2.html \ - test_bug552605-1.html \ - test_bug552605-2.html \ - bug552605.sjs \ $(NULL) # Tests disabled due to intermittent orange diff --git a/modules/libpr0n/test/mochitest/bug552605.sjs b/modules/libpr0n/test/mochitest/bug552605.sjs deleted file mode 100644 index a93ab6dcf53..00000000000 --- a/modules/libpr0n/test/mochitest/bug552605.sjs +++ /dev/null @@ -1,13 +0,0 @@ -function handleRequest(request, response) -{ - var redirectstate = "/modules/libpr0n/test/mochitest/bug89419.sjs"; - response.setStatusLine("1.1", 302, "Found"); - if (getState(redirectstate) == "") { - response.setHeader("Location", "red.png", false); - setState(redirectstate, "red"); - } else { - response.setHeader("Location", "blue.png", false); - setState(redirectstate, ""); - } - response.setHeader("Cache-Control", "no-cache", false); -} diff --git a/modules/libpr0n/test/mochitest/bug89419-iframe.html b/modules/libpr0n/test/mochitest/bug89419-iframe.html deleted file mode 100644 index 1915315633a..00000000000 --- a/modules/libpr0n/test/mochitest/bug89419-iframe.html +++ /dev/null @@ -1,7 +0,0 @@ - - -Bug 89419 iframe - - - - diff --git a/modules/libpr0n/test/mochitest/bug89419.sjs b/modules/libpr0n/test/mochitest/bug89419.sjs deleted file mode 100644 index a93ab6dcf53..00000000000 --- a/modules/libpr0n/test/mochitest/bug89419.sjs +++ /dev/null @@ -1,13 +0,0 @@ -function handleRequest(request, response) -{ - var redirectstate = "/modules/libpr0n/test/mochitest/bug89419.sjs"; - response.setStatusLine("1.1", 302, "Found"); - if (getState(redirectstate) == "") { - response.setHeader("Location", "red.png", false); - setState(redirectstate, "red"); - } else { - response.setHeader("Location", "blue.png", false); - setState(redirectstate, ""); - } - response.setHeader("Cache-Control", "no-cache", false); -} diff --git a/modules/libpr0n/test/mochitest/test_bug552605-1.html b/modules/libpr0n/test/mochitest/test_bug552605-1.html deleted file mode 100644 index 19783711c1b..00000000000 --- a/modules/libpr0n/test/mochitest/test_bug552605-1.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - - Test for Bug 552605 - - - - - - -Mozilla Bug 552605 -

-
-
-
-
- -
- - diff --git a/modules/libpr0n/test/mochitest/test_bug552605-2.html b/modules/libpr0n/test/mochitest/test_bug552605-2.html deleted file mode 100644 index 4ad1c61b292..00000000000 --- a/modules/libpr0n/test/mochitest/test_bug552605-2.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - Test for Bug 552605 - - - - - - -Mozilla Bug 552605 -

-
-
-
-
- - -
- - diff --git a/modules/libpr0n/test/mochitest/test_bug89419-1.html b/modules/libpr0n/test/mochitest/test_bug89419-1.html deleted file mode 100644 index 96140e66dae..00000000000 --- a/modules/libpr0n/test/mochitest/test_bug89419-1.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - Test for Bug 89419 - - - - - - -Mozilla Bug 89419 -

-
-
-
-
- -
- - diff --git a/modules/libpr0n/test/mochitest/test_bug89419-2.html b/modules/libpr0n/test/mochitest/test_bug89419-2.html deleted file mode 100644 index 9251c02538c..00000000000 --- a/modules/libpr0n/test/mochitest/test_bug89419-2.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - Test for Bug 89419 - - - - - - -Mozilla Bug 89419 -

-
-
-
-
- -
- - diff --git a/testing/mochitest/tests/SimpleTest/WindowSnapshot.js b/testing/mochitest/tests/SimpleTest/WindowSnapshot.js index 4e1ee054c73..f0c46b4472e 100644 --- a/testing/mochitest/tests/SimpleTest/WindowSnapshot.js +++ b/testing/mochitest/tests/SimpleTest/WindowSnapshot.js @@ -3,7 +3,7 @@ netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); var gWindowUtils; try { - gWindowUtils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindowUtils); + gWindowUtils = window.QueryInterface(CI.nsIInterfaceRequestor).getInterface(CI.nsIDOMWindowUtils); if (gWindowUtils && !gWindowUtils.compareCanvases) gWindowUtils = null; } catch (e) {