diff --git a/netwerk/protocol/http/public/nsIHttpProtocolHandler.idl b/netwerk/protocol/http/public/nsIHttpProtocolHandler.idl index 13f81d21834..4900e5886fe 100644 --- a/netwerk/protocol/http/public/nsIHttpProtocolHandler.idl +++ b/netwerk/protocol/http/public/nsIHttpProtocolHandler.idl @@ -158,5 +158,12 @@ interface nsIHttpProtocolHandler : nsIProxiedProtocolHandler */ #define NS_HTTP_ON_EXAMINE_MERGED_RESPONSE_TOPIC "http-on-examine-merged-response" +/** + * The observer of this topic is notified before data is read from the cache. + * The notification is sent if and only if there is no network communication + * at all. + */ +#define NS_HTTP_ON_EXAMINE_CACHED_RESPONSE_TOPIC "http-on-examine-cached-response" + %} diff --git a/netwerk/protocol/http/src/nsHttpChannel.cpp b/netwerk/protocol/http/src/nsHttpChannel.cpp index 970abf23771..21ddb816079 100644 --- a/netwerk/protocol/http/src/nsHttpChannel.cpp +++ b/netwerk/protocol/http/src/nsHttpChannel.cpp @@ -255,11 +255,19 @@ nsHttpChannel::Init(nsIURI *uri, //----------------------------------------------------------------------------- nsresult -nsHttpChannel::AsyncCall(nsAsyncCallback funcPtr) +nsHttpChannel::AsyncCall(nsAsyncCallback funcPtr, + nsRunnableMethod **retval) { - nsCOMPtr event = + nsresult rv; + + nsRefPtr > event = new nsRunnableMethod(this, funcPtr); - return NS_DispatchToCurrentThread(event); + rv = NS_DispatchToCurrentThread(event); + if (NS_SUCCEEDED(rv) && retval) { + *retval = event; + } + + return rv; } PRBool @@ -341,7 +349,15 @@ nsHttpChannel::Connect(PRBool firstTime) // read straight from the cache if possible... if (mCachedContentIsValid) { - return ReadFromCache(); + nsRunnableMethod *event = nsnull; + if (!mCachedContentIsPartial) { + AsyncCall(&nsHttpChannel::AsyncOnExamineCachedResponse, &event); + } + rv = ReadFromCache(); + if (NS_FAILED(rv) && event) { + event->Revoke(); + } + return rv; } else if (mLoadFlags & LOAD_ONLY_FROM_CACHE) { // the cache contains the requested resource, but it must be @@ -5591,3 +5607,8 @@ nsHttpChannel::DetermineStoragePolicy() return policy; } +void +nsHttpChannel::AsyncOnExamineCachedResponse() +{ + gHttpHandler->OnExamineCachedResponse(this); +} diff --git a/netwerk/protocol/http/src/nsHttpChannel.h b/netwerk/protocol/http/src/nsHttpChannel.h index c26693498ac..a3523af8c29 100644 --- a/netwerk/protocol/http/src/nsHttpChannel.h +++ b/netwerk/protocol/http/src/nsHttpChannel.h @@ -153,7 +153,10 @@ private: } // AsyncCall may be used to call a member function asynchronously. - nsresult AsyncCall(nsAsyncCallback funcPtr); + // retval isn't refcounted and is set only when event was successfully + // posted, the event is returned for the purpose of cancelling when needed + nsresult AsyncCall(nsAsyncCallback funcPtr, + nsRunnableMethod **retval = nsnull); PRBool RequestIsConditional(); nsresult Connect(PRBool firstTime = PR_TRUE); @@ -205,6 +208,7 @@ private: nsresult InstallOfflineCacheListener(); void MaybeInvalidateCacheEntryForSubsequentGet(); nsCacheStoragePolicy DetermineStoragePolicy(); + void AsyncOnExamineCachedResponse(); // Handle the bogus Content-Encoding Apache sometimes sends void ClearBogusContentEncodingIfNeeded(); diff --git a/netwerk/protocol/http/src/nsHttpHandler.h b/netwerk/protocol/http/src/nsHttpHandler.h index 6ccd3de57c5..c12973a4bb8 100644 --- a/netwerk/protocol/http/src/nsHttpHandler.h +++ b/netwerk/protocol/http/src/nsHttpHandler.h @@ -195,6 +195,13 @@ public: // channel's and the global redirect observers. nsresult OnChannelRedirect(nsIChannel* oldChan, nsIChannel* newChan, PRUint32 flags); + + // Called by the channel when the response is read from the cache without + // communicating with the server. + void OnExamineCachedResponse(nsIHttpChannel *chan) + { + NotifyObservers(chan, NS_HTTP_ON_EXAMINE_CACHED_RESPONSE_TOPIC); + } private: //