mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-11 16:32:59 +00:00
Fixes bug 72520 "support for cacheKeys must be implemented" r=gordon sr=dougt
This commit is contained in:
parent
70077848e8
commit
4e05acafb9
@ -55,8 +55,13 @@ interface nsICachingChannel : nsISupports
|
||||
* Set/get the cache key... uniquely identifies the data in the cache.
|
||||
* Holding a reference to this key DOES NOT prevent the cached data from
|
||||
* being removed. It is otherwise similar to the cacheToken.
|
||||
*
|
||||
* The fromCacheOnly flag inhibits fetching from the net if the data in the
|
||||
* cache has been evicted. An error of NS_ERROR_DOCUMENT_NOT_CACHED will
|
||||
* be sent to the listener's onStopRequest in this case.
|
||||
*/
|
||||
attribute nsISupports cacheKey;
|
||||
nsISupports getCacheKey();
|
||||
void setCacheKey(in nsISupports cacheKey, in boolean fromCacheOnly);
|
||||
|
||||
/**
|
||||
* Specifies whether or not the data should be cached to a file. This
|
||||
@ -74,3 +79,10 @@ interface nsICachingChannel : nsISupports
|
||||
*/
|
||||
readonly attribute nsIFile cacheFile;
|
||||
};
|
||||
|
||||
%{C++
|
||||
/**
|
||||
* nsresult passed through onStopRequest if the document could not be fetched from the cache.
|
||||
*/
|
||||
#define NS_ERROR_DOCUMENT_NOT_CACHED NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 70)
|
||||
%}
|
||||
|
@ -64,8 +64,12 @@
|
||||
|
||||
#ifdef MOZ_NEW_CACHE
|
||||
|
||||
#include "nsISupportsPrimitives.h" // for GetCacheKey
|
||||
|
||||
static NS_DEFINE_CID(kStreamListenerTeeCID, NS_STREAMLISTENERTEE_CID);
|
||||
|
||||
// XXX move these time routines to a shared library
|
||||
|
||||
static PRTime
|
||||
SecondsToPRTime(PRUint32 t_sec)
|
||||
{
|
||||
@ -106,7 +110,7 @@ TimeStringToSeconds(const char *str, PRUint32 *t_sec)
|
||||
|
||||
#define NowInSeconds() PRTimeToSeconds(PR_Now())
|
||||
|
||||
#else
|
||||
#else // MOZ_NEW_CACHE
|
||||
|
||||
#include "nsINetDataCacheManager.h"
|
||||
#include "nsINetDataCache.h"
|
||||
@ -141,6 +145,10 @@ nsHTTPChannel::nsHTTPChannel(nsIURI *aURL, nsHTTPHandler *aHandler)
|
||||
, mURI(dont_QueryInterface(aURL))
|
||||
, mLoadAttributes(LOAD_NORMAL)
|
||||
, mLoadGroup(nsnull)
|
||||
#ifdef MOZ_NEW_CACHE
|
||||
, mCacheAccess(nsICache::ACCESS_NONE)
|
||||
, mPostID(0)
|
||||
#endif
|
||||
, mAuthRealm(nsnull)
|
||||
, mProxyType(nsnull)
|
||||
, mProxy(nsnull)
|
||||
@ -150,7 +158,9 @@ nsHTTPChannel::nsHTTPChannel(nsIURI *aURL, nsHTTPHandler *aHandler)
|
||||
, mConnected(PR_FALSE)
|
||||
, mApplyConversion(PR_TRUE)
|
||||
, mOpenHasEventQueue(PR_TRUE)
|
||||
#ifndef MOZ_NEW_CACHE
|
||||
#ifdef MOZ_NEW_CACHE
|
||||
, mFromCacheOnly(PR_FALSE)
|
||||
#else
|
||||
, mCachedContentIsAvailable(PR_FALSE)
|
||||
#endif
|
||||
, mCachedContentIsValid(PR_FALSE)
|
||||
@ -841,42 +851,71 @@ nsHTTPChannel::OpenCacheEntry()
|
||||
NS_ENSURE_TRUE(mHandler, NS_ERROR_NOT_INITIALIZED);
|
||||
NS_ENSURE_TRUE(!mCacheEntry, NS_ERROR_FAILURE);
|
||||
|
||||
// for now we only cache GET and HEAD transactions.
|
||||
if ((mRequest->Method() != nsHTTPAtoms::Get) &&
|
||||
(mRequest->Method() != nsHTTPAtoms::Head))
|
||||
nsCAutoString cacheKey;
|
||||
|
||||
if (mRequest->Method() == nsHTTPAtoms::Post) {
|
||||
// If the post id is already set then this is an attempt to replay
|
||||
// a post transaction via the cache. Otherwise, we need a unique
|
||||
// post id for this transaction.
|
||||
if (mPostID == 0)
|
||||
mPostID = mHandler->CreatePostID();
|
||||
}
|
||||
else if ((mRequest->Method() != nsHTTPAtoms::Get) &&
|
||||
(mRequest->Method() != nsHTTPAtoms::Head))
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
GenerateCacheKey(cacheKey);
|
||||
|
||||
// Get a cache session with appropriate storage policy
|
||||
nsCacheStoragePolicy storagePolicy;
|
||||
if (mLoadAttributes & INHIBIT_PERSISTENT_CACHING)
|
||||
storagePolicy = nsICache::STORE_IN_MEMORY;
|
||||
else
|
||||
storagePolicy = nsICache::STORE_ANYWHERE; // allow on disk
|
||||
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
rv = mHandler->GetCacheSession(storagePolicy, getter_AddRefs(session));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Find out if we're offline
|
||||
// Are we offline?
|
||||
PRBool offline = PR_FALSE;
|
||||
nsCOMPtr<nsIIOService> ioService = do_GetIOService();
|
||||
if (ioService)
|
||||
ioService->GetOffline(&offline);
|
||||
|
||||
// Set the requested cache access...
|
||||
// Set the desired cache access mode accordingly...
|
||||
nsCacheAccessMode accessRequested;
|
||||
if (offline)
|
||||
accessRequested = nsICache::ACCESS_READ; // read from cache
|
||||
if (offline) {
|
||||
// Since we are offline, we can only read from the cache.
|
||||
accessRequested = nsICache::ACCESS_READ;
|
||||
mFromCacheOnly = PR_TRUE;
|
||||
}
|
||||
else if (mLoadAttributes & FORCE_RELOAD)
|
||||
accessRequested = nsICache::ACCESS_WRITE; // replace cache entry
|
||||
else if (mFromCacheOnly)
|
||||
accessRequested = nsICache::ACCESS_READ; // read from cache
|
||||
else
|
||||
accessRequested = nsICache::ACCESS_READ_WRITE; // normal browsing
|
||||
|
||||
// Open a cache entry with key = url
|
||||
return session->AsyncOpenCacheEntry(mRequest->Spec(),
|
||||
return session->AsyncOpenCacheEntry(cacheKey,
|
||||
accessRequested,
|
||||
this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTTPChannel::GenerateCacheKey(nsAWritableCString &cacheKey)
|
||||
{
|
||||
cacheKey.SetLength(0);
|
||||
if (mPostID) {
|
||||
char buf[32];
|
||||
PR_snprintf(buf, sizeof(buf), "%x", mPostID);
|
||||
cacheKey.Append("post-id=");
|
||||
cacheKey.Append(buf);
|
||||
cacheKey.Append("&url=");
|
||||
}
|
||||
cacheKey.Append(mRequest->Spec());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// The request-time is the time at which we sent the request.
|
||||
nsresult
|
||||
nsHTTPChannel::GetRequestTime(PRUint32 *value)
|
||||
@ -1105,7 +1144,10 @@ nsHTTPChannel::CheckCache()
|
||||
|
||||
// Get the cached HTTP response headers
|
||||
rv = mCacheEntry->GetMetaDataElement("http-headers", getter_Copies(str));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("cache entry does not contain http headers!");
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Parse the cached HTTP response headers
|
||||
NS_IF_RELEASE(mCachedResponse); // XXX this should already be cleared !!
|
||||
@ -1399,7 +1441,7 @@ nsHTTPChannel::CacheReceivedResponse(nsIStreamListener *aListener,
|
||||
*aResult = nsnull;
|
||||
|
||||
// Don't cache the response again if already cached... FinishResponseHeaders
|
||||
// calls ProcessStatusCode for handling cached redirects.
|
||||
// calls ProcessStatusCode for handling cached redirects, which can call us!
|
||||
if (mCachedContentIsValid)
|
||||
return NS_OK;
|
||||
|
||||
@ -1410,8 +1452,10 @@ nsHTTPChannel::CacheReceivedResponse(nsIStreamListener *aListener,
|
||||
LOG(("nsHTTPChannel::CacheReceivedResponse [this=%x entry=%x]\n",
|
||||
this, mCacheEntry.get()));
|
||||
|
||||
if (!ResponseIsCacheable()) {
|
||||
// XXX we should cache these as well, but doom them immediately.
|
||||
// Every POST transaction has a unique ID associated with it. If this
|
||||
// is not a POST transaction (or if the POST transaction should not be
|
||||
// cached) then the ID will be zero.
|
||||
if (!mPostID && !ResponseIsCacheable()) {
|
||||
CacheAbort(0);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2052,6 +2096,14 @@ nsHTTPChannel::Connect()
|
||||
// the cache...
|
||||
return ReadFromCache();
|
||||
}
|
||||
else if (mFromCacheOnly) {
|
||||
// The cache no longer contains the requested resource, and we
|
||||
// are not allowed to refetch it, so there's nothing more to do.
|
||||
// If this was a refetch of a POST transaction's resposne, then
|
||||
// this failure indicates that the response is no longer cached.
|
||||
rv = mPostID ? NS_ERROR_DOCUMENT_NOT_CACHED : NS_BINDING_FAILED;
|
||||
return ResponseCompleted(mResponseDataListener, rv, nsnull);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// If this request was deferred because there was no available socket
|
||||
@ -3442,14 +3494,33 @@ nsHTTPChannel::SetCacheToken(nsISupports *token)
|
||||
NS_IMETHODIMP
|
||||
nsHTTPChannel::GetCacheKey(nsISupports **key)
|
||||
{
|
||||
nsresult rv;
|
||||
NS_ENSURE_ARG_POINTER(key);
|
||||
return CallQueryInterface(mURI, key);
|
||||
|
||||
nsCOMPtr<nsISupportsPRUint32> container =
|
||||
do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = container->SetData(mPostID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return CallQueryInterface(container, key);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTTPChannel::SetCacheKey(nsISupports *key)
|
||||
nsHTTPChannel::SetCacheKey(nsISupports *key, PRBool fromCacheOnly)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
nsresult rv;
|
||||
NS_ENSURE_ARG_POINTER(key);
|
||||
|
||||
nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(key, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = container->GetData(&mPostID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mFromCacheOnly = fromCacheOnly;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -3493,8 +3564,6 @@ nsHTTPChannel::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry,
|
||||
LOG(("nsHTTPChannel::OnCacheEntryAvailable [this=%x entry=%x "
|
||||
"access=%x status=%x]\n", this, entry, access, status));
|
||||
|
||||
LOG(("Got cache entry descriptor: access=%x\n", access));
|
||||
|
||||
if (NS_SUCCEEDED(status)) {
|
||||
mCacheEntry = entry;
|
||||
mCacheAccess = access;
|
||||
|
@ -139,6 +139,7 @@ protected:
|
||||
|
||||
#ifdef MOZ_NEW_CACHE
|
||||
nsresult OpenCacheEntry();
|
||||
nsresult GenerateCacheKey(nsAWritableCString &);
|
||||
|
||||
nsresult GetRequestTime(PRUint32 *);
|
||||
nsresult SetRequestTime(PRUint32);
|
||||
@ -219,6 +220,7 @@ protected:
|
||||
nsCOMPtr<nsITransport> mCacheTransport;
|
||||
nsCOMPtr<nsIRequest> mCacheReadRequest;
|
||||
nsCacheAccessMode mCacheAccess;
|
||||
PRUint32 mPostID;
|
||||
#else
|
||||
nsCOMPtr<nsICachedNetData> mCacheEntry;
|
||||
nsCOMPtr<nsIChannel> mCacheChannel;
|
||||
@ -249,7 +251,9 @@ protected:
|
||||
PRPackedBool mOpenHasEventQueue;
|
||||
|
||||
// Cache-related flags
|
||||
#ifndef MOZ_NEW_CACHE
|
||||
#ifdef MOZ_NEW_CACHE
|
||||
PRPackedBool mFromCacheOnly;
|
||||
#else
|
||||
PRPackedBool mCachedContentIsAvailable;
|
||||
#endif
|
||||
PRPackedBool mCachedContentIsValid;
|
||||
|
@ -94,9 +94,24 @@ static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); // remove now TODO
|
||||
static NS_DEFINE_CID(kProtocolProxyServiceCID, NS_PROTOCOLPROXYSERVICE_CID);
|
||||
|
||||
#ifdef MOZ_NEW_CACHE
|
||||
|
||||
#include "nsICacheService.h"
|
||||
static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
|
||||
#endif
|
||||
|
||||
// XXX move these time routines to a shared library
|
||||
static PRUint32
|
||||
PRTimeToSeconds(PRTime t_usec)
|
||||
{
|
||||
PRTime usec_per_sec;
|
||||
PRUint32 t_sec;
|
||||
LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
|
||||
LL_DIV(t_usec, t_usec, usec_per_sec);
|
||||
LL_L2I(t_sec, t_usec);
|
||||
return t_sec;
|
||||
}
|
||||
#define NowInSeconds() PRTimeToSeconds(PR_Now())
|
||||
|
||||
#endif // MOZ_NEW_CACHE
|
||||
|
||||
NS_DEFINE_CID(kCategoryManagerCID, NS_CATEGORYMANAGER_CID);
|
||||
|
||||
@ -731,6 +746,9 @@ nsHTTPHandler::SetMisc(const PRUnichar *misc)
|
||||
}
|
||||
|
||||
nsHTTPHandler::nsHTTPHandler():
|
||||
#ifdef MOZ_NEW_CACHE
|
||||
mLastPostID(NowInSeconds()),
|
||||
#endif
|
||||
mAcceptLanguages(nsnull),
|
||||
mAcceptEncodings(nsnull),
|
||||
mAcceptCharset(nsnull),
|
||||
|
@ -148,6 +148,7 @@ public:
|
||||
|
||||
#ifdef MOZ_NEW_CACHE
|
||||
nsresult GetCacheSession(nsCacheStoragePolicy, nsICacheSession **);
|
||||
PRUint32 CreatePostID() { return ++mLastPostID; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@ -166,6 +167,7 @@ protected:
|
||||
#ifdef MOZ_NEW_CACHE
|
||||
nsCOMPtr<nsICacheSession> mCacheSession_ANY;
|
||||
nsCOMPtr<nsICacheSession> mCacheSession_MEM;
|
||||
PRUint32 mLastPostID;
|
||||
#endif
|
||||
|
||||
char* mAcceptLanguages;
|
||||
|
Loading…
Reference in New Issue
Block a user