Backed out changeset d0b284052d29 for Talos regression investigation on tp4.

This commit is contained in:
Mounir Lamouri 2010-08-22 20:16:05 +02:00
Родитель a6a3b44e9d
Коммит 45466cd1fa
10 изменённых файлов: 169 добавлений и 451 удалений

1
netwerk/cache/nsCacheRequest.h поставляемый
Просмотреть файл

@ -54,7 +54,6 @@ class nsCacheRequest : public PRCList
private: private:
friend class nsCacheService; friend class nsCacheService;
friend class nsCacheEntry; friend class nsCacheEntry;
friend class nsProcessRequestEvent;
nsCacheRequest( nsCString * key, nsCacheRequest( nsCString * key,
nsICacheListener * listener, nsICacheListener * listener,

92
netwerk/cache/nsCacheService.cpp поставляемый
Просмотреть файл

@ -614,44 +614,6 @@ nsCacheProfilePrefObserver::MemoryCacheCapacity()
return capacity; return capacity;
} }
/******************************************************************************
* nsProcessRequestEvent
*****************************************************************************/
class nsProcessRequestEvent : public nsRunnable {
public:
nsProcessRequestEvent(nsCacheRequest *aRequest)
{
mRequest = aRequest;
}
NS_IMETHOD Run()
{
nsresult rv;
NS_ASSERTION(mRequest->mListener,
"Sync OpenCacheEntry() posted to background thread!");
nsCacheServiceAutoLock lock;
rv = nsCacheService::gService->ProcessRequest(mRequest,
PR_FALSE,
nsnull);
// Don't delete the request if it was queued
if (rv != NS_ERROR_CACHE_WAIT_FOR_VALIDATION)
delete mRequest;
return NS_OK;
}
protected:
virtual ~nsProcessRequestEvent() {}
private:
nsCacheRequest *mRequest;
};
/****************************************************************************** /******************************************************************************
* nsCacheService * nsCacheService
*****************************************************************************/ *****************************************************************************/
@ -719,13 +681,8 @@ nsCacheService::Init()
CACHE_LOG_INIT(); CACHE_LOG_INIT();
nsresult rv = NS_NewThread(getter_AddRefs(mCacheIOThread));
if (NS_FAILED(rv)) {
NS_WARNING("Can't create cache IO thread");
}
// initialize hashtable for active cache entries // initialize hashtable for active cache entries
rv = mActiveEntries.Init(); nsresult rv = mActiveEntries.Init();
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
// create profile/preference observer // create profile/preference observer
@ -746,9 +703,6 @@ nsCacheService::Init()
void void
nsCacheService::Shutdown() nsCacheService::Shutdown()
{ {
nsCOMPtr<nsIThread> cacheIOThread;
{
nsCacheServiceAutoLock lock; nsCacheServiceAutoLock lock;
NS_ASSERTION(mInitialized, NS_ASSERTION(mInitialized,
"can't shutdown nsCacheService unless it has been initialized."); "can't shutdown nsCacheService unless it has been initialized.");
@ -780,13 +734,7 @@ nsCacheService::Shutdown()
#if defined(NECKO_DISK_CACHE) && defined(PR_LOGGING) #if defined(NECKO_DISK_CACHE) && defined(PR_LOGGING)
LogCacheStatistics(); LogCacheStatistics();
#endif #endif
mCacheIOThread.swap(cacheIOThread);
} }
} // lock
if (cacheIOThread)
cacheIOThread->Shutdown();
} }
@ -999,17 +947,6 @@ NS_IMETHODIMP nsCacheService::EvictEntries(nsCacheStoragePolicy storagePolicy)
return EvictEntriesForClient(nsnull, storagePolicy); return EvictEntriesForClient(nsnull, storagePolicy);
} }
NS_IMETHODIMP nsCacheService::GetCacheIOTarget(nsIEventTarget * *aCacheIOTarget)
{
nsCacheServiceAutoLock lock;
if (!mCacheIOThread)
return NS_ERROR_NOT_AVAILABLE;
NS_ADDREF(*aCacheIOTarget = mCacheIOThread);
return NS_OK;
}
/** /**
* Internal Methods * Internal Methods
*/ */
@ -1298,28 +1235,11 @@ nsCacheService::OpenCacheEntry(nsCacheSession * session,
CACHE_LOG_DEBUG(("Created request %p\n", request)); CACHE_LOG_DEBUG(("Created request %p\n", request));
// Process the request on the background thread if we are on the main thread rv = gService->ProcessRequest(request, PR_TRUE, result);
// and the the request is asynchronous
if (NS_IsMainThread() && listener && gService->mCacheIOThread) {
nsCOMPtr<nsIRunnable> ev =
new nsProcessRequestEvent(request);
if (ev) {
rv = gService->mCacheIOThread->Dispatch(ev, NS_DISPATCH_NORMAL);
} else {
rv = NS_ERROR_OUT_OF_MEMORY;
}
// delete request if we didn't post the event // delete requests that have completed
if (NS_FAILED(rv)) if (!(listener && (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION)))
delete request; delete request;
}
else {
rv = gService->ProcessRequest(request, PR_TRUE, result);
// delete requests that have completed
if (!(listener && (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION)))
delete request;
}
return rv; return rv;
} }
@ -1859,7 +1779,7 @@ nsCacheService::ReleaseObject_Locked(nsISupports * obj,
NS_ASSERTION(gService->mLockedThread == PR_GetCurrentThread(), "oops"); NS_ASSERTION(gService->mLockedThread == PR_GetCurrentThread(), "oops");
PRBool isCur; PRBool isCur;
if (!target || (NS_SUCCEEDED(target->IsOnCurrentThread(&isCur)) && isCur)) { if (!target || NS_SUCCEEDED(target->IsOnCurrentThread(&isCur)) && isCur) {
gService->mDoomedObjects.AppendElement(obj); gService->mDoomedObjects.AppendElement(obj);
} else { } else {
NS_ProxyRelease(target, obj); NS_ProxyRelease(target, obj);

3
netwerk/cache/nsCacheService.h поставляемый
Просмотреть файл

@ -166,7 +166,6 @@ public:
private: private:
friend class nsCacheServiceAutoLock; friend class nsCacheServiceAutoLock;
friend class nsOfflineCacheDevice; friend class nsOfflineCacheDevice;
friend class nsProcessRequestEvent;
/** /**
* Internal Methods * Internal Methods
@ -246,8 +245,6 @@ private:
PRThread * mLockedThread; // The thread holding mLock PRThread * mLockedThread; // The thread holding mLock
#endif #endif
nsCOMPtr<nsIThread> mCacheIOThread;
nsTArray<nsISupports*> mDoomedObjects; nsTArray<nsISupports*> mDoomedObjects;
PRBool mInitialized; PRBool mInitialized;

78
netwerk/cache/nsDiskCacheDeviceSQL.cpp поставляемый
Просмотреть файл

@ -54,7 +54,6 @@
#include "nsArrayUtils.h" #include "nsArrayUtils.h"
#include "nsIArray.h" #include "nsIArray.h"
#include "nsIVariant.h" #include "nsIVariant.h"
#include "nsThreadUtils.h"
#include "mozIStorageService.h" #include "mozIStorageService.h"
#include "mozIStorageStatement.h" #include "mozIStorageStatement.h"
@ -172,7 +171,7 @@ DCacheHash(const char * key)
* nsOfflineCacheEvictionFunction * nsOfflineCacheEvictionFunction
*/ */
NS_IMPL_THREADSAFE_ISUPPORTS1(nsOfflineCacheEvictionFunction, mozIStorageFunction) NS_IMPL_ISUPPORTS1(nsOfflineCacheEvictionFunction, mozIStorageFunction)
// helper function for directly exposing the same data file binding // helper function for directly exposing the same data file binding
// path algorithm used in nsOfflineCacheBinding::Create // path algorithm used in nsOfflineCacheBinding::Create
@ -769,37 +768,11 @@ nsApplicationCache::GetUsage(PRUint32 *usage)
return mDevice->GetUsage(mClientID, usage); return mDevice->GetUsage(mClientID, usage);
} }
/******************************************************************************
* nsCloseDBEvent
*****************************************************************************/
class nsCloseDBEvent : public nsRunnable {
public:
nsCloseDBEvent(mozIStorageConnection *aDB)
{
mDB = aDB;
}
NS_IMETHOD Run()
{
mDB->Close();
return NS_OK;
}
protected:
virtual ~nsCloseDBEvent() {}
private:
nsCOMPtr<mozIStorageConnection> mDB;
};
/****************************************************************************** /******************************************************************************
* nsOfflineCacheDevice * nsOfflineCacheDevice
*/ */
NS_IMPL_THREADSAFE_ISUPPORTS1(nsOfflineCacheDevice, nsIApplicationCacheService) NS_IMPL_ISUPPORTS1(nsOfflineCacheDevice, nsIApplicationCacheService)
nsOfflineCacheDevice::nsOfflineCacheDevice() nsOfflineCacheDevice::nsOfflineCacheDevice()
: mDB(nsnull) : mDB(nsnull)
@ -1013,8 +986,6 @@ nsOfflineCacheDevice::Init()
rv = ss->OpenDatabase(indexFile, getter_AddRefs(mDB)); rv = ss->OpenDatabase(indexFile, getter_AddRefs(mDB));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
mInitThread = do_GetCurrentThread();
mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("PRAGMA synchronous = OFF;")); mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("PRAGMA synchronous = OFF;"));
// XXX ... other initialization steps // XXX ... other initialization steps
@ -1230,7 +1201,6 @@ nsOfflineCacheDevice::Shutdown()
if (mCaches.IsInitialized()) if (mCaches.IsInitialized())
mCaches.EnumerateRead(ShutdownApplicationCache, this); mCaches.EnumerateRead(ShutdownApplicationCache, this);
{
EvictionObserver evictionObserver(mDB, mEvictionFunction); EvictionObserver evictionObserver(mDB, mEvictionFunction);
// Delete all rows whose clientID is not an active clientID. // Delete all rows whose clientID is not an active clientID.
@ -1257,51 +1227,9 @@ nsOfflineCacheDevice::Shutdown()
if (NS_FAILED(rv)) if (NS_FAILED(rv))
NS_WARNING("Failed to clean up namespaces."); NS_WARNING("Failed to clean up namespaces.");
mDB = 0;
mEvictionFunction = 0; mEvictionFunction = 0;
mStatement_CacheSize = nsnull;
mStatement_ApplicationCacheSize = nsnull;
mStatement_EntryCount = nsnull;
mStatement_UpdateEntry = nsnull;
mStatement_UpdateEntrySize = nsnull;
mStatement_UpdateEntryFlags = nsnull;
mStatement_DeleteEntry = nsnull;
mStatement_FindEntry = nsnull;
mStatement_BindEntry = nsnull;
mStatement_ClearDomain = nsnull;
mStatement_MarkEntry = nsnull;
mStatement_UnmarkEntry = nsnull;
mStatement_GetTypes = nsnull;
mStatement_FindNamespaceEntry = nsnull;
mStatement_InsertNamespaceEntry = nsnull;
mStatement_CleanupUnmarked = nsnull;
mStatement_GatherEntries = nsnull;
mStatement_ActivateClient = nsnull;
mStatement_DeactivateGroup = nsnull;
mStatement_FindClient = nsnull;
mStatement_FindClientByNamespace = nsnull;
mStatement_EnumerateGroups = nsnull;
}
// Close Database on the correct thread
PRBool isOnCurrentThread = PR_TRUE;
if (mInitThread)
mInitThread->IsOnCurrentThread(&isOnCurrentThread);
if (!isOnCurrentThread) {
nsCOMPtr<nsIRunnable> ev = new nsCloseDBEvent(mDB);
if (ev) {
mInitThread->Dispatch(ev, NS_DISPATCH_NORMAL);
}
}
else {
mDB->Close();
}
mDB = nsnull;
mInitThread = nsnull;
return NS_OK; return NS_OK;
} }

2
netwerk/cache/nsDiskCacheDeviceSQL.h поставляемый
Просмотреть файл

@ -275,8 +275,6 @@ private:
nsInterfaceHashtable<nsCStringHashKey, nsIWeakReference> mCaches; nsInterfaceHashtable<nsCStringHashKey, nsIWeakReference> mCaches;
nsClassHashtable<nsCStringHashKey, nsCString> mActiveCachesByGroup; nsClassHashtable<nsCStringHashKey, nsCString> mActiveCachesByGroup;
nsCStringHashSet mActiveCaches; nsCStringHashSet mActiveCaches;
nsCOMPtr<nsIThread> mInitThread;
}; };
#endif // nsOfflineCacheDevice_h__ #endif // nsOfflineCacheDevice_h__

8
netwerk/cache/nsICacheService.idl поставляемый
Просмотреть файл

@ -47,9 +47,8 @@ interface nsISimpleEnumerator;
interface nsICacheListener; interface nsICacheListener;
interface nsICacheSession; interface nsICacheSession;
interface nsICacheVisitor; interface nsICacheVisitor;
interface nsIEventTarget;
[scriptable, uuid(14dbe1e9-f3bc-45af-92f4-2c574fcd4e39)] [scriptable, uuid(de114eb4-29fc-4959-b2f7-2d03eb9bc771)]
interface nsICacheService : nsISupports interface nsICacheService : nsISupports
{ {
/** /**
@ -88,11 +87,6 @@ interface nsICacheService : nsISupports
* everything. * everything.
*/ */
void evictEntries(in nsCacheStoragePolicy storagePolicy); void evictEntries(in nsCacheStoragePolicy storagePolicy);
/**
* Event target which is used for I/O operations
*/
readonly attribute nsIEventTarget cacheIOTarget;
}; };
%{C++ %{C++

Просмотреть файл

@ -115,8 +115,6 @@ nsHttpChannel::nsHttpChannel()
, mCacheAccess(0) , mCacheAccess(0)
, mPostID(0) , mPostID(0)
, mRequestTime(0) , mRequestTime(0)
, mOnCacheEntryAvailableCallback(nsnull)
, mAsyncCacheOpen(PR_FALSE)
, mPendingAsyncCallOnResume(nsnull) , mPendingAsyncCallOnResume(nsnull)
, mSuspendCount(0) , mSuspendCount(0)
, mApplyConversion(PR_TRUE) , mApplyConversion(PR_TRUE)
@ -200,6 +198,8 @@ nsHttpChannel::Connect(PRBool firstTime)
// true when called from AsyncOpen // true when called from AsyncOpen
if (firstTime) { if (firstTime) {
PRBool delayed = PR_FALSE;
// are we offline? // are we offline?
PRBool offline = gIOService->IsOffline(); PRBool offline = gIOService->IsOffline();
if (offline) if (offline)
@ -214,7 +214,7 @@ nsHttpChannel::Connect(PRBool firstTime)
} }
// open a cache entry for this channel... // open a cache entry for this channel...
rv = OpenCacheEntry(); rv = OpenCacheEntry(offline, &delayed);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
LOG(("OpenCacheEntry failed [rv=%x]\n", rv)); LOG(("OpenCacheEntry failed [rv=%x]\n", rv));
@ -238,7 +238,7 @@ nsHttpChannel::Connect(PRBool firstTime)
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
} }
if (NS_SUCCEEDED(rv) && mAsyncCacheOpen) if (NS_SUCCEEDED(rv) && delayed)
return NS_OK; return NS_OK;
} }
@ -271,14 +271,6 @@ nsHttpChannel::Connect(PRBool firstTime)
return NS_ERROR_DOCUMENT_NOT_CACHED; return NS_ERROR_DOCUMENT_NOT_CACHED;
} }
} }
else if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
// If we have a fallback URI (and we're not already
// falling back), process the fallback asynchronously.
if (!mFallbackChannel && !mFallbackKey.IsEmpty()) {
return AsyncCall(&nsHttpChannel::HandleAsyncFallback);
}
return NS_ERROR_DOCUMENT_NOT_CACHED;
}
// check to see if authorization headers should be included // check to see if authorization headers should be included
mAuthProvider->AddAuthorizationHeaders(); mAuthProvider->AddAuthorizationHeaders();
@ -1692,11 +1684,11 @@ IsSubRangeRequest(nsHttpRequestHead &aRequestHead)
} }
nsresult nsresult
nsHttpChannel::OpenCacheEntry() nsHttpChannel::OpenCacheEntry(PRBool offline, PRBool *delayed)
{ {
nsresult rv; nsresult rv;
mAsyncCacheOpen = PR_FALSE; *delayed = PR_FALSE;
mLoadedFromApplicationCache = PR_FALSE; mLoadedFromApplicationCache = PR_FALSE;
LOG(("nsHttpChannel::OpenCacheEntry [this=%p]", this)); LOG(("nsHttpChannel::OpenCacheEntry [this=%p]", this));
@ -1732,10 +1724,23 @@ nsHttpChannel::OpenCacheEntry()
GenerateCacheKey(mPostID, cacheKey); GenerateCacheKey(mPostID, cacheKey);
// Get a cache session with appropriate storage policy
nsCacheStoragePolicy storagePolicy = DetermineStoragePolicy();
// Set the desired cache access mode accordingly... // Set the desired cache access mode accordingly...
nsCacheAccessMode accessRequested; nsCacheAccessMode accessRequested;
rv = DetermineCacheAccess(&accessRequested); if (offline || (mLoadFlags & INHIBIT_CACHING)) {
if NS_FAILED(rv) return rv; // If we have been asked to bypass the cache and not write to the
// cache, then don't use the cache at all. Unless we're actually
// offline, which takes precedence over BYPASS_LOCAL_CACHE.
if (BYPASS_LOCAL_CACHE(mLoadFlags) && !offline)
return NS_ERROR_NOT_AVAILABLE;
accessRequested = nsICache::ACCESS_READ;
}
else if (BYPASS_LOCAL_CACHE(mLoadFlags))
accessRequested = nsICache::ACCESS_WRITE; // replace cache entry
else
accessRequested = nsICache::ACCESS_READ_WRITE; // normal browsing
if (!mApplicationCache && mInheritApplicationCache) { if (!mApplicationCache && mInheritApplicationCache) {
// Pick up an application cache from the notification // Pick up an application cache from the notification
@ -1764,6 +1769,10 @@ nsHttpChannel::OpenCacheEntry()
nsCOMPtr<nsICacheSession> session; nsCOMPtr<nsICacheSession> session;
// Will be set to true if we've found the right session, but need
// to open the cache entry asynchronously.
PRBool waitingForValidation = PR_FALSE;
// If we have an application cache, we check it first. // If we have an application cache, we check it first.
if (mApplicationCache) { if (mApplicationCache) {
nsCAutoString appCacheClientID; nsCAutoString appCacheClientID;
@ -1779,217 +1788,107 @@ nsHttpChannel::OpenCacheEntry()
getter_AddRefs(session)); getter_AddRefs(session));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) { // we'll try to synchronously open the cache entry... however,
// must use synchronous open for LOAD_BYPASS_LOCAL_CACHE_IF_BUSY // it may be in use and not yet validated, in which case we'll
rv = session->OpenCacheEntry(cacheKey, // try asynchronously opening the cache entry.
nsICache::ACCESS_READ, PR_FALSE, //
getter_AddRefs(mCacheEntry)); // We open with ACCESS_READ only, because we don't want to
if (NS_SUCCEEDED(rv)) { // overwrite the offline cache entry non-atomically.
mCacheEntry->GetAccessGranted(&mCacheAccess); // ACCESS_READ will prevent us from writing to the offline
LOG(("nsHttpChannel::OpenCacheEntry [this=%p grantedAccess=%d]", // cache as a normal cache entry.
this, mCacheAccess)); rv = session->OpenCacheEntry(cacheKey,
mLoadedFromApplicationCache = PR_TRUE; nsICache::ACCESS_READ, PR_FALSE,
return NS_OK; getter_AddRefs(mCacheEntry));
} else if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) { if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) {
LOG(("bypassing local cache since it is busy\n")); accessRequested = nsICache::ACCESS_READ;
// Don't try to load normal cache entry waitingForValidation = PR_TRUE;
return NS_ERROR_NOT_AVAILABLE; rv = NS_OK;
}
} else {
mOnCacheEntryAvailableCallback =
&nsHttpChannel::OnOfflineCacheEntryAvailable;
// We open with ACCESS_READ only, because we don't want to
// overwrite the offline cache entry non-atomically.
// ACCESS_READ will prevent us from writing to the offline
// cache as a normal cache entry.
rv = session->AsyncOpenCacheEntry(cacheKey,
nsICache::ACCESS_READ,
this);
if (NS_SUCCEEDED(rv)) {
mAsyncCacheOpen = PR_TRUE;
return NS_OK;
}
} }
// sync or async opening failed if (NS_FAILED(rv) && !mCacheForOfflineUse && !mFallbackChannel) {
return OnOfflineCacheEntryAvailable(nsnull, nsICache::ACCESS_NONE, // Check for namespace match.
rv, PR_TRUE); nsCOMPtr<nsIApplicationCacheNamespace> namespaceEntry;
} rv = mApplicationCache->GetMatchingNamespace
(cacheKey, getter_AddRefs(namespaceEntry));
return OpenNormalCacheEntry(PR_TRUE);
}
nsresult
nsHttpChannel::OnOfflineCacheEntryAvailable(nsICacheEntryDescriptor *aEntry,
nsCacheAccessMode aAccess,
nsresult aEntryStatus,
PRBool aIsSync)
{
nsresult rv;
if (NS_SUCCEEDED(aEntryStatus)) {
// We successfully opened an offline cache session and the entry,
// so indicate we will load from the offline cache.
mLoadedFromApplicationCache = PR_TRUE;
mCacheEntry = aEntry;
mCacheAccess = aAccess;
}
if (mCanceled && NS_FAILED(mStatus)) {
LOG(("channel was canceled [this=%p status=%x]\n", this, mStatus));
return mStatus;
}
if (NS_SUCCEEDED(aEntryStatus))
// Called from OnCacheEntryAvailable, advance to the next state
return Connect(PR_FALSE);
if (!mCacheForOfflineUse && !mFallbackChannel) {
nsCAutoString cacheKey;
GenerateCacheKey(mPostID, cacheKey);
// Check for namespace match.
nsCOMPtr<nsIApplicationCacheNamespace> namespaceEntry;
rv = mApplicationCache->GetMatchingNamespace
(cacheKey, getter_AddRefs(namespaceEntry));
if (NS_FAILED(rv) && !aIsSync)
return Connect(PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
PRUint32 namespaceType = 0;
if (!namespaceEntry ||
NS_FAILED(namespaceEntry->GetItemType(&namespaceType)) ||
(namespaceType &
(nsIApplicationCacheNamespace::NAMESPACE_FALLBACK |
nsIApplicationCacheNamespace::NAMESPACE_OPPORTUNISTIC |
nsIApplicationCacheNamespace::NAMESPACE_BYPASS)) == 0) {
// When loading from an application cache, only items
// on the whitelist or matching a
// fallback/opportunistic namespace should hit the
// network...
mLoadFlags |= LOAD_ONLY_FROM_CACHE;
// ... and if there were an application cache entry,
// we would have found it earlier.
return aIsSync ? NS_ERROR_CACHE_KEY_NOT_FOUND : Connect(PR_FALSE);
}
if (namespaceType &
nsIApplicationCacheNamespace::NAMESPACE_FALLBACK) {
rv = namespaceEntry->GetData(mFallbackKey);
if (NS_FAILED(rv) && !aIsSync)
return Connect(PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
PRUint32 namespaceType = 0;
if (!namespaceEntry ||
NS_FAILED(namespaceEntry->GetItemType(&namespaceType)) ||
(namespaceType &
(nsIApplicationCacheNamespace::NAMESPACE_FALLBACK |
nsIApplicationCacheNamespace::NAMESPACE_OPPORTUNISTIC |
nsIApplicationCacheNamespace::NAMESPACE_BYPASS)) == 0) {
// When loading from an application cache, only items
// on the whitelist or matching a
// fallback/opportunistic namespace should hit the
// network...
mLoadFlags |= LOAD_ONLY_FROM_CACHE;
// ... and if there were an application cache entry,
// we would have found it earlier.
return NS_ERROR_CACHE_KEY_NOT_FOUND;
}
if (namespaceType &
nsIApplicationCacheNamespace::NAMESPACE_FALLBACK) {
rv = namespaceEntry->GetData(mFallbackKey);
NS_ENSURE_SUCCESS(rv, rv);
}
if ((namespaceType &
nsIApplicationCacheNamespace::NAMESPACE_OPPORTUNISTIC) &&
mLoadFlags & LOAD_DOCUMENT_URI) {
// Document loads for items in an opportunistic namespace
// should be placed in the offline cache.
nsCString clientID;
mApplicationCache->GetClientID(clientID);
mCacheForOfflineUse = !clientID.IsEmpty();
SetOfflineCacheClientID(clientID);
mCachingOpportunistically = PR_TRUE;
}
} }
else if (NS_SUCCEEDED(rv)) {
if ((namespaceType & // We successfully opened an offline cache session and the entry,
nsIApplicationCacheNamespace::NAMESPACE_OPPORTUNISTIC) && // now indiciate we load from the offline cache.
mLoadFlags & LOAD_DOCUMENT_URI) { mLoadedFromApplicationCache = PR_TRUE;
// Document loads for items in an opportunistic namespace
// should be placed in the offline cache.
nsCString clientID;
mApplicationCache->GetClientID(clientID);
mCacheForOfflineUse = !clientID.IsEmpty();
SetOfflineCacheClientID(clientID);
mCachingOpportunistically = PR_TRUE;
} }
} }
return OpenNormalCacheEntry(aIsSync); if (!mCacheEntry && !waitingForValidation) {
} rv = gHttpHandler->GetCacheSession(storagePolicy,
getter_AddRefs(session));
if (NS_FAILED(rv)) return rv;
nsresult
nsHttpChannel::OpenNormalCacheEntry(PRBool aIsSync)
{
NS_ASSERTION(!mCacheEntry, "We have already mCacheEntry");
nsresult rv;
nsCAutoString cacheKey;
GenerateCacheKey(mPostID, cacheKey);
nsCacheStoragePolicy storagePolicy = DetermineStoragePolicy();
nsCOMPtr<nsICacheSession> session;
rv = gHttpHandler->GetCacheSession(storagePolicy,
getter_AddRefs(session));
if (NS_FAILED(rv)) return rv;
nsCacheAccessMode accessRequested;
rv = DetermineCacheAccess(&accessRequested);
if NS_FAILED(rv) return rv;
if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) {
if (!aIsSync) {
// Unexpected state: we were called from OnCacheEntryAvailable(),
// so LOAD_BYPASS_LOCAL_CACHE_IF_BUSY shouldn't be set. Unless
// somebody altered mLoadFlags between OpenCacheEntry() and
// OnCacheEntryAvailable()...
NS_WARNING(
"OpenNormalCacheEntry() called from OnCacheEntryAvailable() "
"when LOAD_BYPASS_LOCAL_CACHE_IF_BUSY was specified");
}
// must use synchronous open for LOAD_BYPASS_LOCAL_CACHE_IF_BUSY
rv = session->OpenCacheEntry(cacheKey, accessRequested, PR_FALSE, rv = session->OpenCacheEntry(cacheKey, accessRequested, PR_FALSE,
getter_AddRefs(mCacheEntry)); getter_AddRefs(mCacheEntry));
if (NS_SUCCEEDED(rv)) { if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) {
mCacheEntry->GetAccessGranted(&mCacheAccess); waitingForValidation = PR_TRUE;
LOG(("nsHttpChannel::OpenCacheEntry [this=%p grantedAccess=%d]", rv = NS_OK;
this, mCacheAccess));
} }
else if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) { if (NS_FAILED(rv)) return rv;
}
if (waitingForValidation) {
// access to the cache entry has been denied (because the
// cache entry is probably in use by another channel).
if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) {
LOG(("bypassing local cache since it is busy\n")); LOG(("bypassing local cache since it is busy\n"));
rv = NS_ERROR_NOT_AVAILABLE; return NS_ERROR_NOT_AVAILABLE;
} }
}
else {
mOnCacheEntryAvailableCallback =
&nsHttpChannel::OnNormalCacheEntryAvailable;
rv = session->AsyncOpenCacheEntry(cacheKey, accessRequested, this); rv = session->AsyncOpenCacheEntry(cacheKey, accessRequested, this);
if (NS_SUCCEEDED(rv)) { if (NS_FAILED(rv)) return rv;
mAsyncCacheOpen = PR_TRUE; // we'll have to wait for the cache entry
return NS_OK; *delayed = PR_TRUE;
} }
else if (NS_SUCCEEDED(rv)) {
mCacheEntry->GetAccessGranted(&mCacheAccess);
LOG(("nsHttpChannel::OpenCacheEntry [this=%p grantedAccess=%d]", this, mCacheAccess));
} }
if (!aIsSync)
// Called from OnCacheEntryAvailable, advance to the next state
rv = Connect(PR_FALSE);
return rv; return rv;
} }
nsresult
nsHttpChannel::OnNormalCacheEntryAvailable(nsICacheEntryDescriptor *aEntry,
nsCacheAccessMode aAccess,
nsresult aEntryStatus,
PRBool aIsSync)
{
NS_ASSERTION(!aIsSync, "aIsSync should be false");
if (NS_SUCCEEDED(aEntryStatus)) {
mCacheEntry = aEntry;
mCacheAccess = aAccess;
}
if (mCanceled && NS_FAILED(mStatus)) {
LOG(("channel was canceled [this=%p status=%x]\n", this, mStatus));
return mStatus;
}
if ((mLoadFlags & LOAD_ONLY_FROM_CACHE) && NS_FAILED(aEntryStatus))
// if this channel is only allowed to pull from the cache, then
// we must fail if we were unable to open a cache entry.
return NS_ERROR_DOCUMENT_NOT_CACHED;
// advance to the next state...
return Connect(PR_FALSE);
}
nsresult nsresult
nsHttpChannel::OpenOfflineCacheEntryForWriting() nsHttpChannel::OpenOfflineCacheEntryForWriting()
@ -2816,26 +2715,20 @@ nsHttpChannel::InstallCacheListener(PRUint32 offset)
do_CreateInstance(kStreamListenerTeeCID, &rv); do_CreateInstance(kStreamListenerTeeCID, &rv);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsICacheService> serv =
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIEventTarget> cacheIOTarget;
serv->GetCacheIOTarget(getter_AddRefs(cacheIOTarget));
nsCacheStoragePolicy policy; nsCacheStoragePolicy policy;
rv = mCacheEntry->GetStoragePolicy(&policy); rv = mCacheEntry->GetStoragePolicy(&policy);
if (NS_FAILED(rv) || policy == nsICache::STORE_ON_DISK_AS_FILE || if (!gHttpHandler->mCacheWriteThread ||
!cacheIOTarget) { NS_FAILED(rv) ||
LOG(("nsHttpChannel::InstallCacheListener sync tee %p rv=%x policy=%d " policy == nsICache::STORE_ON_DISK_AS_FILE) {
"cacheIOTarget=%p", tee.get(), rv, policy, cacheIOTarget.get())); LOG(("nsHttpChannel::InstallCacheListener sync tee %p\n", tee.get()));
rv = tee->Init(mListener, out, nsnull); rv = tee->Init(mListener, out, nsnull);
} else { } else {
LOG(("nsHttpChannel::InstallCacheListener async tee %p", tee.get())); LOG(("nsHttpChannel::InstallCacheListener async tee %p\n",
rv = tee->InitAsync(mListener, cacheIOTarget, out, nsnull); tee.get()));
rv = tee->InitAsync(mListener, gHttpHandler->mCacheWriteThread, out, nsnull);
} }
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
mListener = tee; mListener = tee;
return NS_OK; return NS_OK;
@ -4188,8 +4081,6 @@ nsHttpChannel::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry,
nsCacheAccessMode access, nsCacheAccessMode access,
nsresult status) nsresult status)
{ {
nsresult rv;
LOG(("nsHttpChannel::OnCacheEntryAvailable [this=%p entry=%p " LOG(("nsHttpChannel::OnCacheEntryAvailable [this=%p entry=%p "
"access=%x status=%x]\n", this, entry, access, status)); "access=%x status=%x]\n", this, entry, access, status));
@ -4198,24 +4089,28 @@ nsHttpChannel::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry,
if (!mIsPending) if (!mIsPending)
return NS_OK; return NS_OK;
nsOnCacheEntryAvailableCallback callback = mOnCacheEntryAvailableCallback; // otherwise, we have to handle this event.
mOnCacheEntryAvailableCallback = nsnull; if (NS_SUCCEEDED(status)) {
mCacheEntry = entry;
mCacheAccess = access;
}
NS_ASSERTION(callback, nsresult rv;
"nsHttpChannel::OnCacheEntryAvailable called without callback");
rv = ((*this).*callback)(entry, access, status, PR_FALSE);
if (mCanceled && NS_FAILED(mStatus)) {
LOG(("channel was canceled [this=%p status=%x]\n", this, mStatus));
rv = mStatus;
}
else if ((mLoadFlags & LOAD_ONLY_FROM_CACHE) && NS_FAILED(status))
// if this channel is only allowed to pull from the cache, then
// we must fail if we were unable to open a cache entry.
rv = NS_ERROR_DOCUMENT_NOT_CACHED;
else
// advance to the next state...
rv = Connect(PR_FALSE);
// a failure from Connect means that we have to abort the channel.
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
LOG(("AsyncOpenCacheEntry failed [rv=%x]\n", rv));
if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
// If we have a fallback URI (and we're not already
// falling back), process the fallback asynchronously.
if (!mFallbackChannel && !mFallbackKey.IsEmpty()) {
rv = AsyncCall(&nsHttpChannel::HandleAsyncFallback);
if (NS_SUCCEEDED(rv))
return rv;
}
}
CloseCacheEntry(PR_TRUE); CloseCacheEntry(PR_TRUE);
AsyncAbort(rv); AsyncAbort(rv);
} }
@ -4682,27 +4577,6 @@ nsHttpChannel::DetermineStoragePolicy()
return policy; return policy;
} }
nsresult
nsHttpChannel::DetermineCacheAccess(nsCacheAccessMode *_retval)
{
PRBool offline = gIOService->IsOffline();
if (offline || (mLoadFlags & INHIBIT_CACHING)) {
// If we have been asked to bypass the cache and not write to the
// cache, then don't use the cache at all. Unless we're actually
// offline, which takes precedence over BYPASS_LOCAL_CACHE.
if (BYPASS_LOCAL_CACHE(mLoadFlags) && !offline)
return NS_ERROR_NOT_AVAILABLE;
*_retval = nsICache::ACCESS_READ;
}
else if (BYPASS_LOCAL_CACHE(mLoadFlags))
*_retval = nsICache::ACCESS_WRITE; // replace cache entry
else
*_retval = nsICache::ACCESS_READ_WRITE; // normal browsing
return NS_OK;
}
void void
nsHttpChannel::AsyncOnExamineCachedResponse() nsHttpChannel::AsyncOnExamineCachedResponse()
{ {

Просмотреть файл

@ -216,16 +216,7 @@ private:
nsresult ResolveProxy(); nsresult ResolveProxy();
// cache specific methods // cache specific methods
nsresult OpenCacheEntry(); nsresult OpenCacheEntry(PRBool offline, PRBool *delayed);
nsresult OnOfflineCacheEntryAvailable(nsICacheEntryDescriptor *aEntry,
nsCacheAccessMode aAccess,
nsresult aResult,
PRBool aSync);
nsresult OpenNormalCacheEntry(PRBool aSync);
nsresult OnNormalCacheEntryAvailable(nsICacheEntryDescriptor *aEntry,
nsCacheAccessMode aAccess,
nsresult aResult,
PRBool aSync);
nsresult OpenOfflineCacheEntryForWriting(); nsresult OpenOfflineCacheEntryForWriting();
nsresult GenerateCacheKey(PRUint32 postID, nsACString &key); nsresult GenerateCacheKey(PRUint32 postID, nsACString &key);
nsresult UpdateExpirationTime(); nsresult UpdateExpirationTime();
@ -243,7 +234,6 @@ private:
nsresult InstallOfflineCacheListener(); nsresult InstallOfflineCacheListener();
void MaybeInvalidateCacheEntryForSubsequentGet(); void MaybeInvalidateCacheEntryForSubsequentGet();
nsCacheStoragePolicy DetermineStoragePolicy(); nsCacheStoragePolicy DetermineStoragePolicy();
nsresult DetermineCacheAccess(nsCacheAccessMode *_retval);
void AsyncOnExamineCachedResponse(); void AsyncOnExamineCachedResponse();
// Handle the bogus Content-Encoding Apache sometimes sends // Handle the bogus Content-Encoding Apache sometimes sends
@ -274,11 +264,6 @@ private:
PRUint32 mPostID; PRUint32 mPostID;
PRUint32 mRequestTime; PRUint32 mRequestTime;
typedef nsresult (nsHttpChannel:: *nsOnCacheEntryAvailableCallback)(
nsICacheEntryDescriptor *, nsCacheAccessMode, nsresult, PRBool);
nsOnCacheEntryAvailableCallback mOnCacheEntryAvailableCallback;
PRBool mAsyncCacheOpen;
nsCOMPtr<nsICacheEntryDescriptor> mOfflineCacheEntry; nsCOMPtr<nsICacheEntryDescriptor> mOfflineCacheEntry;
nsCacheAccessMode mOfflineCacheAccess; nsCacheAccessMode mOfflineCacheAccess;
nsCString mOfflineCacheClientID; nsCString mOfflineCacheClientID;

Просмотреть файл

@ -294,6 +294,14 @@ nsHttpHandler::Init()
rv = InitConnectionMgr(); rv = InitConnectionMgr();
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
rv = NS_NewThread(getter_AddRefs(mCacheWriteThread));
if (NS_FAILED(rv)) {
mCacheWriteThread = nsnull;
LOG(("Failed creating cache-write thread - writes will be synchronous"));
} else {
LOG(("Created cache-write thread = %p", mCacheWriteThread.get()));
}
nsCOMPtr<nsIXULAppInfo> appInfo = nsCOMPtr<nsIXULAppInfo> appInfo =
do_GetService("@mozilla.org/xre/app-info;1"); do_GetService("@mozilla.org/xre/app-info;1");
if (appInfo) if (appInfo)
@ -313,6 +321,7 @@ nsHttpHandler::Init()
mObserverService->AddObserver(this, "profile-change-net-restore", PR_TRUE); mObserverService->AddObserver(this, "profile-change-net-restore", PR_TRUE);
mObserverService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_TRUE); mObserverService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_TRUE);
mObserverService->AddObserver(this, "net:clear-active-logins", PR_TRUE); mObserverService->AddObserver(this, "net:clear-active-logins", PR_TRUE);
mObserverService->AddObserver(this, "xpcom-shutdown-threads", PR_TRUE);
} }
StartPruneDeadConnectionsTimer(); StartPruneDeadConnectionsTimer();
@ -1771,6 +1780,18 @@ nsHttpHandler::Observe(nsISupports *subject,
else if (strcmp(topic, "net:clear-active-logins") == 0) { else if (strcmp(topic, "net:clear-active-logins") == 0) {
mAuthCache.ClearAll(); mAuthCache.ClearAll();
} }
else if (strcmp(topic, "xpcom-shutdown-threads") == 0) {
// Shutdown the cache write thread. This must be done after shutting down
// the cache service, because the (memory) cache entries' storage streams
// get released on the thread on which they were first written to, which
// is this thread.
if (mCacheWriteThread) {
LOG((" shutting down cache-write thread...\n"));
mCacheWriteThread->Shutdown();
LOG((" cache-write thread shutdown complete\n"));
mCacheWriteThread = nsnull;
}
}
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -210,6 +210,8 @@ public:
static nsresult GenerateHostPort(const nsCString& host, PRInt32 port, static nsresult GenerateHostPort(const nsCString& host, PRInt32 port,
nsCString& hostLine); nsCString& hostLine);
// The thread used to implement async cache-writes
nsCOMPtr<nsIThread> mCacheWriteThread;
private: private:
// //