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) {