зеркало из https://github.com/mozilla/pjs.git
update the offline cache atomically. b=389223, r=biesi, sr=jst
This commit is contained in:
Родитель
ea1f2f7e17
Коммит
53f92f7497
|
@ -47,6 +47,7 @@
|
|||
#include "nsNetCID.h"
|
||||
#include "nsICacheService.h"
|
||||
#include "nsICacheSession.h"
|
||||
#include "nsIOfflineCacheUpdate.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMError.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
@ -154,7 +155,6 @@ NS_INTERFACE_MAP_BEGIN(nsDOMOfflineLoadStatusList)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIDOMLoadStatusList)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIOfflineCacheUpdateObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(LoadStatusList)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
@ -199,7 +199,7 @@ nsDOMOfflineLoadStatusList::Init()
|
|||
rv = cacheUpdateService->GetUpdate(i, getter_AddRefs(cacheUpdate));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = WatchUpdate(cacheUpdate);
|
||||
UpdateAdded(cacheUpdate);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -210,6 +210,8 @@ nsDOMOfflineLoadStatusList::Init()
|
|||
|
||||
rv = observerServ->AddObserver(this, "offline-cache-update-added", PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = observerServ->AddObserver(this, "offline-cache-update-completed", PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -231,7 +233,7 @@ nsDOMOfflineLoadStatusList::FindWrapper(nsIDOMLoadStatus *aStatus,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsDOMOfflineLoadStatusList::WatchUpdate(nsIOfflineCacheUpdate *aUpdate)
|
||||
nsDOMOfflineLoadStatusList::UpdateAdded(nsIOfflineCacheUpdate *aUpdate)
|
||||
{
|
||||
nsCAutoString owner;
|
||||
nsresult rv = aUpdate->GetUpdateDomain(owner);
|
||||
|
@ -256,19 +258,50 @@ nsDOMOfflineLoadStatusList::WatchUpdate(nsIOfflineCacheUpdate *aUpdate)
|
|||
|
||||
mItems.AppendObject(wrapper);
|
||||
|
||||
rv = SendLoadEvent(NS_LITERAL_STRING(LOADREQUESTED_STR),
|
||||
mLoadRequestedEventListeners,
|
||||
wrapper);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
SendLoadEvent(NS_LITERAL_STRING(LOADREQUESTED_STR),
|
||||
mLoadRequestedEventListeners,
|
||||
wrapper);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aUpdate->AddObserver(this, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMOfflineLoadStatusList::UpdateCompleted(nsIOfflineCacheUpdate *aUpdate)
|
||||
{
|
||||
nsCAutoString owner;
|
||||
nsresult rv = aUpdate->GetUpdateDomain(owner);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (owner != mHostPort) {
|
||||
// This update doesn't belong to us
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint32 numItems;
|
||||
rv = aUpdate->GetCount(&numItems);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRUint32 i = 0; i < numItems; i++) {
|
||||
nsCOMPtr<nsIDOMLoadStatus> status;
|
||||
rv = aUpdate->Item(i, getter_AddRefs(status));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 index;
|
||||
nsCOMPtr<nsIDOMLoadStatus> wrapper = FindWrapper(status, &index);
|
||||
if (wrapper) {
|
||||
mItems.RemoveObjectAt(index);
|
||||
nsresult rv = SendLoadEvent(NS_LITERAL_STRING(LOADCOMPLETED_STR),
|
||||
mLoadCompletedEventListeners,
|
||||
wrapper);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// nsDOMOfflineLoadStatusList::nsIDOMLoadStatusList
|
||||
//
|
||||
|
@ -468,29 +501,13 @@ nsDOMOfflineLoadStatusList::Observe(nsISupports *aSubject,
|
|||
if (!strcmp(aTopic, "offline-cache-update-added")) {
|
||||
nsCOMPtr<nsIOfflineCacheUpdate> update = do_QueryInterface(aSubject);
|
||||
if (update) {
|
||||
rv = WatchUpdate(update);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
UpdateAdded(update);
|
||||
}
|
||||
} else if (!strcmp(aTopic, "offline-cache-update-completed")) {
|
||||
nsCOMPtr<nsIOfflineCacheUpdate> update = do_QueryInterface(aSubject);
|
||||
if (update) {
|
||||
UpdateCompleted(update);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// nsDOMLoadStatusList::nsIOfflineCacheUpdateObserver
|
||||
//
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMOfflineLoadStatusList::ItemCompleted(nsIDOMLoadStatus *aItem)
|
||||
{
|
||||
PRUint32 index;
|
||||
nsCOMPtr<nsIDOMLoadStatus> wrapper = FindWrapper(aItem, &index);
|
||||
if (wrapper) {
|
||||
mItems.RemoveObjectAt(index);
|
||||
nsresult rv = SendLoadEvent(NS_LITERAL_STRING(LOADCOMPLETED_STR),
|
||||
mLoadCompletedEventListeners,
|
||||
wrapper);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -59,7 +59,6 @@ class nsDOMOfflineLoadStatus;
|
|||
class nsDOMOfflineLoadStatusList : public nsIDOMLoadStatusList,
|
||||
public nsIDOMEventTarget,
|
||||
public nsIObserver,
|
||||
public nsIOfflineCacheUpdateObserver,
|
||||
public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
|
@ -67,7 +66,6 @@ public:
|
|||
NS_DECL_NSIDOMLOADSTATUSLIST
|
||||
NS_DECL_NSIDOMEVENTTARGET
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSIOFFLINECACHEUPDATEOBSERVER
|
||||
|
||||
nsDOMOfflineLoadStatusList(nsIURI *aURI);
|
||||
virtual ~nsDOMOfflineLoadStatusList();
|
||||
|
@ -75,7 +73,8 @@ public:
|
|||
nsresult Init();
|
||||
|
||||
private :
|
||||
nsresult WatchUpdate (nsIOfflineCacheUpdate *aUpdate);
|
||||
nsresult UpdateAdded (nsIOfflineCacheUpdate *aUpdate);
|
||||
nsresult UpdateCompleted (nsIOfflineCacheUpdate *aUpdate);
|
||||
nsIDOMLoadStatus *FindWrapper (nsIDOMLoadStatus *aStatus,
|
||||
PRUint32 *aIndex);
|
||||
void NotifyEventListeners(const nsCOMArray<nsIDOMEventListener>& aListeners,
|
||||
|
@ -95,6 +94,7 @@ private :
|
|||
|
||||
nsCOMArray<nsIDOMEventListener> mLoadRequestedEventListeners;
|
||||
nsCOMArray<nsIDOMEventListener> mLoadCompletedEventListeners;
|
||||
nsCOMArray<nsIDOMEventListener> mUpdateCompletedEventListeners;
|
||||
};
|
||||
|
||||
class nsDOMLoadStatusEvent : public nsDOMEvent,
|
||||
|
|
|
@ -50,7 +50,7 @@ interface nsIFile;
|
|||
* 3) Support for uniquely identifying cached data in cases when the URL
|
||||
* is insufficient (e.g., HTTP form submission).
|
||||
*/
|
||||
[scriptable, uuid(afafb719-bdf5-49c8-a4a9-db39ec331c9b)]
|
||||
[scriptable, uuid(09556ba7-b13d-47d2-b154-fe690b063899)]
|
||||
interface nsICachingChannel : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -105,6 +105,12 @@ interface nsICachingChannel : nsISupports
|
|||
*/
|
||||
attribute boolean cacheForOfflineUse;
|
||||
|
||||
/**
|
||||
* The session into which to cache offline data. If not specified,
|
||||
* data will be placed in "HTTP-offline"
|
||||
*/
|
||||
attribute ACString offlineCacheClientID;
|
||||
|
||||
/**
|
||||
* Get the "file" where the cached data can be found. This is valid for
|
||||
* as long as a reference to the cache token is held. This may return
|
||||
|
|
|
@ -48,7 +48,7 @@ interface nsICacheListener;
|
|||
interface nsICacheSession;
|
||||
interface nsICacheVisitor;
|
||||
|
||||
[scriptable, uuid(de114eb4-29fc-4959-b2f7-2d03eb9bc771)]
|
||||
[scriptable, uuid(98dd0187-aad4-4cab-82c5-1adddef3629d)]
|
||||
interface nsICacheService : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -84,6 +84,15 @@ interface nsICacheService : nsISupports
|
|||
* Evicts all entries in all devices implied by the storage policy.
|
||||
*/
|
||||
void evictEntries(in nsCacheStoragePolicy storagePolicy);
|
||||
|
||||
/**
|
||||
* Return a unique, temporary cache client ID.
|
||||
*
|
||||
* This is used by the offline cache. The offline cache lets clients
|
||||
* accumulate entries in a temporary client and merge them in as a group
|
||||
* using nsIOfflineCacheSession.mergeTemporaryClient().
|
||||
*/
|
||||
ACString createTemporaryClientID(in nsCacheStoragePolicy storagePolicy);
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
|
|
@ -40,37 +40,39 @@
|
|||
#include "nsISupports.idl"
|
||||
#include "nsICache.idl"
|
||||
|
||||
[scriptable, uuid(0058c32b-0d93-4cf8-a561-e6f749c8a7b1)]
|
||||
/**
|
||||
* The offline cache is meant to reliably store resources for
|
||||
* offline use. The expected semantics are:
|
||||
*
|
||||
* a) Once populated, the cache will not evict an application resource
|
||||
* unless explicitly asked.
|
||||
*
|
||||
* b) Resources no longer in use by the application should be evicted.
|
||||
*
|
||||
* c) If the cache fills up, new entries should be rejected rather
|
||||
* than throwing out old ones.
|
||||
*
|
||||
* The offline cache uses domains to concretely represent an
|
||||
* application. It maintains a list of resources to be pinned for
|
||||
* each domain. This list is separate from actual cache
|
||||
* population - the caller is still responsible for placing items
|
||||
* in the cache, and ownership can be declared without a
|
||||
* corresponding entry.
|
||||
*
|
||||
* A key can optionally be associated with a specific URI within
|
||||
* the domain.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(de7875e5-a7e2-4d8d-ad01-807ef55ef8c0)]
|
||||
interface nsIOfflineCacheSession : nsISupports
|
||||
{
|
||||
/**
|
||||
* The offline cache is meant to reliably store resources for
|
||||
* offline use. The expected semantics are:
|
||||
*
|
||||
* a) Once populated, the cache will not evict an application resource
|
||||
* unless explicitly asked.
|
||||
*
|
||||
* b) Resources no longer in use by the application should be evicted.
|
||||
*
|
||||
* c) If the cache fills up, new entries should be rejected rather
|
||||
* than throwing out old ones.
|
||||
*
|
||||
* The offline cache uses domains to concretely represent an
|
||||
* application. It maintains a list of resources to be pinned for
|
||||
* each domain. This list is separate from actual cache
|
||||
* population - the caller is still responsible for placing items
|
||||
* in the cache, and ownership can be declared without a
|
||||
* corresponding entry.
|
||||
*
|
||||
* A key can optionally be associated with a specific URI within
|
||||
* the domain.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets the list of owner domains in the cache.
|
||||
*
|
||||
* @param count The number of domains returned
|
||||
* @param uris The domains that own resources in the cache
|
||||
* @param count
|
||||
* The number of domains returned
|
||||
* @param uris
|
||||
* The domains that own resources in the cache
|
||||
*/
|
||||
void getOwnerDomains(out unsigned long count,
|
||||
[array, size_is(count)]out string domains);
|
||||
|
@ -78,9 +80,12 @@ interface nsIOfflineCacheSession : nsISupports
|
|||
/**
|
||||
* Gets the list of owner URIs associated with a domain.
|
||||
*
|
||||
* @param ownerDomain The domain to query
|
||||
* @param count The number of uris returned
|
||||
* @param uris The uris in this domain that own resources
|
||||
* @param ownerDomain
|
||||
* The domain to query
|
||||
* @param count
|
||||
* The number of uris returned
|
||||
* @param uris
|
||||
* The uris in this domain that own resources
|
||||
*/
|
||||
void getOwnerURIs(in ACString ownerDomain,
|
||||
out unsigned long count,
|
||||
|
@ -96,12 +101,16 @@ interface nsIOfflineCacheSession : nsISupports
|
|||
* an entry is created with this key, it will be owned by the
|
||||
* domain/URI pair.
|
||||
*
|
||||
* @param ownerDomain The domain that owns the resources.
|
||||
* @param ownerURI The specific URI that owns the resources. This can
|
||||
* be empty if no URI specifically owns the resources.
|
||||
* @param count The number of keys in keys.
|
||||
* @param keys The keys that the domain/URI pair own. This can be empty
|
||||
* to clear ownership for the domain/URI pair.
|
||||
* @param ownerDomain
|
||||
* The domain that owns the resources.
|
||||
* @param ownerURI
|
||||
* The specific URI that owns the resources. This can be empty if
|
||||
* no URI specifically owns the resources.
|
||||
* @param count
|
||||
* The number of keys in keys.
|
||||
* @param keys
|
||||
* The keys that the domain/URI pair own. This can be empty to
|
||||
* clear ownership for the domain/URI pair.
|
||||
*/
|
||||
void setOwnedKeys(in ACString ownerDomain,
|
||||
in ACString ownerURI,
|
||||
|
@ -111,11 +120,15 @@ interface nsIOfflineCacheSession : nsISupports
|
|||
/**
|
||||
* Gets the list of resources owned by a given domain/URI pair.
|
||||
*
|
||||
* @param ownerDomain The domain that owns the resources.
|
||||
* @param ownerURI The specific URI that owns the resources. This can
|
||||
* be empty if no URI specifically owns the resources.
|
||||
* @param count The number of keys in keys.
|
||||
* @param keys The keys that the domain/URI pair own.
|
||||
* @param ownerDomain
|
||||
* The domain that owns the resources.
|
||||
* @param ownerURI
|
||||
* The specific URI that owns the resources. This can be empty
|
||||
* if no URI specifically owns the resources.
|
||||
* @param count
|
||||
* The number of keys in keys.
|
||||
* @param keys
|
||||
* The keys that the domain/URI pair own.
|
||||
*/
|
||||
void getOwnedKeys(in ACString ownerDomain,
|
||||
in ACString ownerURI,
|
||||
|
@ -129,10 +142,13 @@ interface nsIOfflineCacheSession : nsISupports
|
|||
* an entry is created with this key, it will be owned by the
|
||||
* domain/URI pair.
|
||||
*
|
||||
* @param ownerDomain The domain that owns the resources.
|
||||
* @param ownerURI The specific URI that owns the resources. This can
|
||||
* be empty if no URI specifically owns the resources.
|
||||
* @param key The key to add.
|
||||
* @param ownerDomain
|
||||
* The domain that owns the resources.
|
||||
* @param ownerURI
|
||||
* The specific URI that owns the resources. This can be empty
|
||||
* if no URI specifically owns the resources.
|
||||
* @param key
|
||||
* The key to add.
|
||||
*/
|
||||
void addOwnedKey(in ACString ownerDomain,
|
||||
in ACString ownerURI,
|
||||
|
@ -144,9 +160,11 @@ interface nsIOfflineCacheSession : nsISupports
|
|||
* If the key does not exist, an NS_ERROR_NOT_AVAILABLE exception
|
||||
* will be thrown.
|
||||
*
|
||||
* @param ownerDomain The domain that owns the resources.
|
||||
* @param ownerURI The specific URI that owns the resources. This can
|
||||
* be empty if no URI specifically owns the resources.
|
||||
* @param ownerDomain
|
||||
* The domain that owns the resources.
|
||||
* @param ownerURI
|
||||
* The specific URI that owns the resources. This can be empty
|
||||
* if no URI specifically owns the resources.
|
||||
* @param key The key to remove.
|
||||
*/
|
||||
void removeOwnedKey(in ACString ownerDomain,
|
||||
|
@ -156,9 +174,11 @@ interface nsIOfflineCacheSession : nsISupports
|
|||
/**
|
||||
* Checks whether a key is owned by a given domain/URI pair.
|
||||
*
|
||||
* @param ownerDomain The domain that owns the resources.
|
||||
* @param ownerURI The specific URI that owns the resources. This can
|
||||
* be empty if no URI specifically owns the resources.
|
||||
* @param ownerDomain
|
||||
* The domain that owns the resources.
|
||||
* @param ownerURI
|
||||
* The specific URI that owns the resources. This can be empty
|
||||
* if no URI specifically owns the resources.
|
||||
* @param key The key to check
|
||||
*/
|
||||
boolean keyIsOwned(in ACString ownerDomain,
|
||||
|
@ -177,4 +197,17 @@ interface nsIOfflineCacheSession : nsISupports
|
|||
* Evict all entries that are not owned by a domain.
|
||||
*/
|
||||
void evictUnownedEntries();
|
||||
|
||||
/**
|
||||
* Merge the items from a temporary clientID in to this client. This lets
|
||||
* offline cache updates accumulate in a temporary client and be moved
|
||||
* in all at once.
|
||||
*
|
||||
* Entries in the temporary client will replace any entries in this client
|
||||
* with the same cache key.
|
||||
*
|
||||
* Ownership lists for a given domain/URI pair from the temporary client
|
||||
* will replace ownership lists for the same domain/URI pair.
|
||||
*/
|
||||
void mergeTemporaryClientID(in ACString temporaryClientID);
|
||||
};
|
||||
|
|
|
@ -1030,6 +1030,25 @@ nsresult nsCacheService::EvictUnownedOfflineEntries(nsCacheSession * session)
|
|||
#endif
|
||||
}
|
||||
|
||||
nsresult nsCacheService::MergeTemporaryClientID(nsCacheSession * session,
|
||||
const nsACString & clientID)
|
||||
{
|
||||
#ifdef NECKO_OFFLINE_CACHE
|
||||
if (session->StoragePolicy() != nsICache::STORE_OFFLINE)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
if (!gService->mOfflineDevice) {
|
||||
nsresult rv = gService->CreateOfflineDevice();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return gService->mOfflineDevice->MergeTemporaryClientID
|
||||
(session->ClientID()->get(), PromiseFlatCString(clientID).get());
|
||||
#else // !NECKO_OFFLINE_CACHE
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCacheService::VisitEntries(nsICacheVisitor *visitor)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(visitor);
|
||||
|
@ -1083,6 +1102,24 @@ NS_IMETHODIMP nsCacheService::EvictEntries(nsCacheStoragePolicy storagePolicy)
|
|||
return EvictEntriesForClient(nsnull, storagePolicy);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCacheService::CreateTemporaryClientID(nsCacheStoragePolicy storagePolicy,
|
||||
nsACString &clientID)
|
||||
{
|
||||
#ifdef NECKO_OFFLINE_CACHE
|
||||
// Only the offline cache device supports temporary clients
|
||||
if (storagePolicy != nsICache::STORE_OFFLINE)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
if (!gService->mOfflineDevice) {
|
||||
nsresult rv = gService->CreateOfflineDevice();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return gService->mOfflineDevice->CreateTemporaryClientID(clientID);
|
||||
#else // !NECKO_OFFLINE_CACHE
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal Methods
|
||||
|
|
|
@ -139,6 +139,9 @@ public:
|
|||
|
||||
static nsresult EvictUnownedOfflineEntries(nsCacheSession * session);
|
||||
|
||||
static nsresult MergeTemporaryClientID(nsCacheSession * session,
|
||||
const nsACString & fromClientID);
|
||||
|
||||
/**
|
||||
* Methods called by nsCacheEntryDescriptor
|
||||
*/
|
||||
|
|
|
@ -197,3 +197,7 @@ NS_IMETHODIMP nsCacheSession::EvictUnownedEntries()
|
|||
return nsCacheService::EvictUnownedOfflineEntries(this);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCacheSession::MergeTemporaryClientID(const nsACString& fromClientID)
|
||||
{
|
||||
return nsCacheService::MergeTemporaryClientID(this, fromClientID);
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ static const char OFFLINE_CACHE_DEVICE_ID[] = { "offline" };
|
|||
|
||||
#define LOG(args) CACHE_LOG_DEBUG(args)
|
||||
|
||||
static PRUint32 gNextTemporaryClientID = 0;
|
||||
|
||||
/*****************************************************************************
|
||||
* helpers
|
||||
|
@ -118,7 +119,7 @@ class EvictionObserver
|
|||
NS_LITERAL_CSTRING("CREATE TEMP TRIGGER cache_on_delete AFTER DELETE"
|
||||
" ON moz_cache FOR EACH ROW BEGIN SELECT"
|
||||
" cache_eviction_observer("
|
||||
" OLD.clientID, OLD.key, OLD.generation);"
|
||||
" OLD.key, OLD.generation);"
|
||||
" END;"));
|
||||
}
|
||||
|
||||
|
@ -175,19 +176,14 @@ NS_IMPL_ISUPPORTS1(nsOfflineCacheEvictionFunction, mozIStorageFunction)
|
|||
// helper function for directly exposing the same data file binding
|
||||
// path algorithm used in nsOfflineCacheBinding::Create
|
||||
static nsresult
|
||||
GetCacheDataFile(nsIFile *cacheDir, const char *cid, const char *key,
|
||||
GetCacheDataFile(nsIFile *cacheDir, const char *key,
|
||||
int generation, nsCOMPtr<nsIFile> &file)
|
||||
{
|
||||
cacheDir->Clone(getter_AddRefs(file));
|
||||
if (!file)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsCAutoString fullKey;
|
||||
fullKey.Append(cid);
|
||||
fullKey.Append(':');
|
||||
fullKey.Append(key);
|
||||
|
||||
PRUint64 hash = DCacheHash(fullKey.get());
|
||||
PRUint64 hash = DCacheHash(key);
|
||||
|
||||
PRUint32 dir1 = (PRUint32) (hash & 0x0F);
|
||||
PRUint32 dir2 = (PRUint32)((hash & 0xF0) >> 4);
|
||||
|
@ -212,20 +208,19 @@ nsOfflineCacheEvictionFunction::OnFunctionCall(mozIStorageValueArray *values, ns
|
|||
PRUint32 numEntries;
|
||||
nsresult rv = values->GetNumEntries(&numEntries);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(numEntries == 3, "unexpected number of arguments");
|
||||
NS_ASSERTION(numEntries == 2, "unexpected number of arguments");
|
||||
|
||||
PRUint32 valueLen;
|
||||
const char *cid = values->AsSharedUTF8String(0, &valueLen);
|
||||
const char *key = values->AsSharedUTF8String(1, &valueLen);
|
||||
int generation = values->AsInt32(2);
|
||||
const char *key = values->AsSharedUTF8String(0, &valueLen);
|
||||
int generation = values->AsInt32(1);
|
||||
|
||||
nsCOMPtr<nsIFile> file;
|
||||
rv = GetCacheDataFile(mDevice->CacheDirectory(), cid, key,
|
||||
rv = GetCacheDataFile(mDevice->CacheDirectory(), key,
|
||||
generation, file);
|
||||
if (NS_FAILED(rv))
|
||||
{
|
||||
LOG(("GetCacheDataFile [cid=%s key=%s generation=%d] failed [rv=%x]!\n",
|
||||
cid, key, generation, rv));
|
||||
LOG(("GetCacheDataFile [key=%s generation=%d] failed [rv=%x]!\n",
|
||||
key, generation, rv));
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -323,7 +318,7 @@ public:
|
|||
NS_DECL_ISUPPORTS
|
||||
|
||||
static nsOfflineCacheBinding *
|
||||
Create(nsIFile *cacheDir, const char *key, int generation);
|
||||
Create(nsIFile *cacheDir, const nsCString *key, int generation);
|
||||
|
||||
nsCOMPtr<nsIFile> mDataFile;
|
||||
int mGeneration;
|
||||
|
@ -333,7 +328,7 @@ NS_IMPL_THREADSAFE_ISUPPORTS0(nsOfflineCacheBinding)
|
|||
|
||||
nsOfflineCacheBinding *
|
||||
nsOfflineCacheBinding::Create(nsIFile *cacheDir,
|
||||
const char *key,
|
||||
const nsCString *fullKey,
|
||||
int generation)
|
||||
{
|
||||
nsCOMPtr<nsIFile> file;
|
||||
|
@ -341,6 +336,11 @@ nsOfflineCacheBinding::Create(nsIFile *cacheDir,
|
|||
if (!file)
|
||||
return nsnull;
|
||||
|
||||
nsCAutoString keyBuf;
|
||||
const char *cid, *key;
|
||||
if (!DecomposeCacheEntryKey(fullKey, &cid, &key, keyBuf))
|
||||
return nsnull;
|
||||
|
||||
PRUint64 hash = DCacheHash(key);
|
||||
|
||||
PRUint32 dir1 = (PRUint32) (hash & 0x0F);
|
||||
|
@ -444,7 +444,7 @@ CreateCacheEntry(nsOfflineCacheDevice *device,
|
|||
// create a binding object for this entry
|
||||
nsOfflineCacheBinding *binding =
|
||||
nsOfflineCacheBinding::Create(device->CacheDirectory(),
|
||||
fullKey->get(),
|
||||
fullKey,
|
||||
rec.generation);
|
||||
if (!binding)
|
||||
{
|
||||
|
@ -765,7 +765,7 @@ nsOfflineCacheDevice::Init()
|
|||
new nsOfflineCacheEvictionFunction(this);
|
||||
if (!evictionFunction) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
rv = mDB->CreateFunction(NS_LITERAL_CSTRING("cache_eviction_observer"), 3, evictionFunction);
|
||||
rv = mDB->CreateFunction(NS_LITERAL_CSTRING("cache_eviction_observer"), 2, evictionFunction);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// create all (most) of our statements up front
|
||||
|
@ -789,9 +789,11 @@ nsOfflineCacheDevice::Init()
|
|||
StatementSql ( mStatement_AddOwnership, "INSERT INTO moz_cache_owners (ClientID, Domain, URI, Key) VALUES (?, ?, ?, ?);" ),
|
||||
StatementSql ( mStatement_CheckOwnership, "SELECT Key From moz_cache_owners WHERE ClientID = ? AND Domain = ? AND URI = ? AND Key = ?;" ),
|
||||
StatementSql ( mStatement_ListOwned, "SELECT Key FROM moz_cache_owners WHERE ClientID = ? AND Domain = ? AND URI = ?;" ),
|
||||
StatementSql ( mStatement_ListOwners, "SELECT DISTINCT Domain, URI FROM moz_cache_owners WHERE ClientID = ?;"),
|
||||
StatementSql ( mStatement_ListOwnerDomains, "SELECT DISTINCT Domain FROM moz_cache_owners WHERE ClientID = ?;"),
|
||||
StatementSql ( mStatement_ListOwnerURIs, "SELECT DISTINCT URI FROM moz_cache_owners WHERE ClientID = ? AND Domain = ?;"),
|
||||
StatementSql ( mStatement_DeleteUnowned, "DELETE FROM moz_cache WHERE rowid IN (SELECT moz_cache.rowid FROM moz_cache LEFT OUTER JOIN moz_cache_owners ON (moz_cache.ClientID = moz_cache_owners.ClientID AND moz_cache.Key = moz_cache_owners.Key) WHERE moz_cache.ClientID = ? AND moz_cache_owners.Domain ISNULL);" )
|
||||
StatementSql ( mStatement_DeleteUnowned, "DELETE FROM moz_cache WHERE rowid IN (SELECT moz_cache.rowid FROM moz_cache LEFT OUTER JOIN moz_cache_owners ON (moz_cache.ClientID = moz_cache_owners.ClientID AND moz_cache.Key = moz_cache_owners.Key) WHERE moz_cache.ClientID = ? AND moz_cache_owners.Domain ISNULL);" ),
|
||||
StatementSql ( mStatement_SwapClientID, "UPDATE OR REPLACE moz_cache SET ClientID = ? WHERE ClientID = ?;")
|
||||
};
|
||||
for (PRUint32 i=0; i<NS_ARRAY_LENGTH(prepared); ++i)
|
||||
{
|
||||
|
@ -807,6 +809,14 @@ nsOfflineCacheDevice::Init()
|
|||
" WHERE (Flags & 1);"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Clear up dangling temporary sessions
|
||||
EvictionObserver evictionObserver(mDB);
|
||||
|
||||
rv = mDB->ExecuteSimpleSQL(
|
||||
NS_LITERAL_CSTRING("DELETE FROM moz_cache"
|
||||
" WHERE (ClientID GLOB \"TempClient*\")"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -972,7 +982,7 @@ nsOfflineCacheDevice::BindEntry(nsCacheEntry *entry)
|
|||
|
||||
// create binding, pick best generation number
|
||||
nsRefPtr<nsOfflineCacheBinding> binding =
|
||||
nsOfflineCacheBinding::Create(mCacheDirectory, entry->Key()->get(), -1);
|
||||
nsOfflineCacheBinding::Create(mCacheDirectory, entry->Key(), -1);
|
||||
if (!binding)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
|
@ -1474,6 +1484,84 @@ nsOfflineCacheDevice::EvictUnownedEntries(const char *clientID)
|
|||
return statement->Execute();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::CreateTemporaryClientID(nsACString &clientID)
|
||||
{
|
||||
nsCAutoString str;
|
||||
str.AssignLiteral("TempClient");
|
||||
str.AppendInt(gNextTemporaryClientID++);
|
||||
|
||||
clientID.Assign(str);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::MergeTemporaryClientID(const char *clientID,
|
||||
const char *fromClientID)
|
||||
{
|
||||
LOG(("nsOfflineCacheDevice::MergeTemporaryClientID [cid=%s, from=%s]\n",
|
||||
clientID, fromClientID));
|
||||
mozStorageTransaction transaction(mDB, PR_FALSE);
|
||||
|
||||
// Move over ownerships
|
||||
AutoResetStatement listOwnersStatement(mStatement_ListOwners);
|
||||
nsresult rv = listOwnersStatement->BindUTF8StringParameter(
|
||||
0, nsDependentCString(fromClientID));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// List all the owners in the new session
|
||||
nsTArray<nsCString> domainArray;
|
||||
nsTArray<nsCString> uriArray;
|
||||
|
||||
PRBool hasRows;
|
||||
rv = listOwnersStatement->ExecuteStep(&hasRows);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
while (hasRows)
|
||||
{
|
||||
PRUint32 length;
|
||||
domainArray.AppendElement(
|
||||
nsDependentCString(listOwnersStatement->AsSharedUTF8String(0, &length)));
|
||||
uriArray.AppendElement(
|
||||
nsDependentCString(listOwnersStatement->AsSharedUTF8String(1, &length)));
|
||||
|
||||
rv = listOwnersStatement->ExecuteStep(&hasRows);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Now move over each ownership set
|
||||
for (PRUint32 i = 0; i < domainArray.Length(); i++) {
|
||||
PRUint32 count;
|
||||
char **keys;
|
||||
rv = GetOwnedKeys(fromClientID, domainArray[i], uriArray[i],
|
||||
&count, &keys);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = SetOwnedKeys(clientID, domainArray[i], uriArray[i],
|
||||
count, const_cast<const char **>(keys));
|
||||
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, keys);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Now clear out the temporary session's copy
|
||||
rv = SetOwnedKeys(fromClientID, domainArray[i], uriArray[i], 0, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
EvictionObserver evictionObserver(mDB);
|
||||
|
||||
AutoResetStatement swapStatement(mStatement_SwapClientID);
|
||||
rv = swapStatement->BindUTF8StringParameter(
|
||||
0, nsDependentCString(clientID));
|
||||
rv |= swapStatement->BindUTF8StringParameter(
|
||||
1, nsDependentCString(fromClientID));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = swapStatement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return transaction.Commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Preference accessors
|
||||
*/
|
||||
|
|
|
@ -121,6 +121,10 @@ public:
|
|||
const nsACString &ownerDomain);
|
||||
nsresult EvictUnownedEntries(const char *clientID);
|
||||
|
||||
nsresult CreateTemporaryClientID(nsACString &clientID);
|
||||
nsresult MergeTemporaryClientID(const char *clientID,
|
||||
const char *fromClientID);
|
||||
|
||||
|
||||
/**
|
||||
* Preference accessors
|
||||
|
@ -163,8 +167,10 @@ private:
|
|||
nsCOMPtr<mozIStorageStatement> mStatement_CheckOwnership;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_DeleteUnowned;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_ListOwned;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_ListOwners;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_ListOwnerDomains;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_ListOwnerURIs;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_SwapClientID;
|
||||
|
||||
nsCOMPtr<nsILocalFile> mCacheDirectory;
|
||||
PRUint32 mCacheCapacity;
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
#include "nsStreamUtils.h"
|
||||
#include "nsIOService.h"
|
||||
#include "nsAuthInformationHolder.h"
|
||||
#include "nsICacheService.h"
|
||||
|
||||
// True if the local cache should be bypassed when processing a request.
|
||||
#define BYPASS_LOCAL_CACHE(loadFlags) \
|
||||
|
@ -1405,8 +1406,19 @@ nsHttpChannel::OpenOfflineCacheEntryForWriting()
|
|||
GenerateCacheKey(cacheKey);
|
||||
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
rv = gHttpHandler->GetCacheSession(nsICache::STORE_OFFLINE,
|
||||
getter_AddRefs(session));
|
||||
if (!mOfflineCacheClientID.IsEmpty()) {
|
||||
nsCOMPtr<nsICacheService> serv =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = serv->CreateSession(mOfflineCacheClientID.get(),
|
||||
nsICache::STORE_OFFLINE,
|
||||
nsICache::STREAM_BASED,
|
||||
getter_AddRefs(session));
|
||||
} else {
|
||||
rv = gHttpHandler->GetCacheSession(nsICache::STORE_OFFLINE,
|
||||
getter_AddRefs(session));
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = session->OpenCacheEntry(cacheKey, nsICache::ACCESS_READ_WRITE,
|
||||
|
@ -4550,6 +4562,22 @@ nsHttpChannel::SetCacheForOfflineUse(PRBool value)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::GetOfflineCacheClientID(nsACString &value)
|
||||
{
|
||||
value = mOfflineCacheClientID;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::SetOfflineCacheClientID(const nsACString &value)
|
||||
{
|
||||
mOfflineCacheClientID = value;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::GetCacheFile(nsIFile **cacheFile)
|
||||
{
|
||||
|
|
|
@ -254,6 +254,7 @@ private:
|
|||
|
||||
nsCOMPtr<nsICacheEntryDescriptor> mOfflineCacheEntry;
|
||||
nsCacheAccessMode mOfflineCacheAccess;
|
||||
nsCString mOfflineCacheClientID;
|
||||
|
||||
// auth specific data
|
||||
nsISupports *mProxyAuthContinuationState;
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "nsNetUtil.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "prlog.h"
|
||||
|
||||
static nsOfflineCacheUpdateService *gOfflineCacheUpdateService = nsnull;
|
||||
|
@ -85,10 +86,11 @@ private:
|
|||
// nsOfflineCacheUpdateItem::nsISupports
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMPL_ISUPPORTS5(nsOfflineCacheUpdateItem,
|
||||
NS_IMPL_ISUPPORTS6(nsOfflineCacheUpdateItem,
|
||||
nsIDOMLoadStatus,
|
||||
nsIRequestObserver,
|
||||
nsIStreamListener,
|
||||
nsIRunnable,
|
||||
nsIInterfaceRequestor,
|
||||
nsIChannelEventSink)
|
||||
|
||||
|
@ -99,9 +101,11 @@ NS_IMPL_ISUPPORTS5(nsOfflineCacheUpdateItem,
|
|||
nsOfflineCacheUpdateItem::nsOfflineCacheUpdateItem(nsOfflineCacheUpdate *aUpdate,
|
||||
nsIURI *aURI,
|
||||
nsIURI *aReferrerURI,
|
||||
nsIDOMNode *aSource)
|
||||
nsIDOMNode *aSource,
|
||||
const nsACString &aClientID)
|
||||
: mURI(aURI)
|
||||
, mReferrerURI(aReferrerURI)
|
||||
, mClientID(aClientID)
|
||||
, mUpdate(aUpdate)
|
||||
, mChannel(nsnull)
|
||||
, mState(nsIDOMLoadStatus::UNINITIALIZED)
|
||||
|
@ -139,6 +143,11 @@ nsOfflineCacheUpdateItem::OpenChannel()
|
|||
if (cachingChannel) {
|
||||
rv = cachingChannel->SetCacheForOfflineUse(PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!mClientID.IsEmpty()) {
|
||||
rv = cachingChannel->SetOfflineCacheClientID(mClientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
rv = mChannel->AsyncOpen(this, nsnull);
|
||||
|
@ -206,6 +215,20 @@ nsOfflineCacheUpdateItem::OnStopRequest(nsIRequest *aRequest,
|
|||
mChannel->GetContentLength(&mBytesRead);
|
||||
}
|
||||
|
||||
// We need to notify the update that the load is complete, but we
|
||||
// want to give the channel a chance to close the cache entries.
|
||||
NS_DispatchToCurrentThread(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsOfflineCacheUpdateItem::nsIRunnable
|
||||
//-----------------------------------------------------------------------------
|
||||
NS_IMETHODIMP
|
||||
nsOfflineCacheUpdateItem::Run()
|
||||
{
|
||||
mUpdate->LoadCompleted();
|
||||
|
||||
return NS_OK;
|
||||
|
@ -245,8 +268,15 @@ nsOfflineCacheUpdateItem::OnChannelRedirect(nsIChannel *aOldChannel,
|
|||
do_QueryInterface(aOldChannel);
|
||||
nsCOMPtr<nsICachingChannel> newCachingChannel =
|
||||
do_QueryInterface(aOldChannel);
|
||||
if (newCachingChannel)
|
||||
newCachingChannel->SetCacheForOfflineUse(PR_TRUE);
|
||||
if (newCachingChannel) {
|
||||
rv = newCachingChannel->SetCacheForOfflineUse(PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!mClientID.IsEmpty()) {
|
||||
rv = newCachingChannel->SetOfflineCacheClientID(mClientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PRBool match;
|
||||
rv = newURI->SchemeIs("http", &match);
|
||||
|
@ -370,6 +400,8 @@ nsOfflineCacheUpdate::nsOfflineCacheUpdate()
|
|||
: mState(STATE_UNINITIALIZED)
|
||||
, mAddedItems(PR_FALSE)
|
||||
, mPartialUpdate(PR_FALSE)
|
||||
, mSucceeded(PR_TRUE)
|
||||
, mCurrentItem(-1)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -409,9 +441,27 @@ nsOfflineCacheUpdate::Init(PRBool aPartialUpdate,
|
|||
getter_AddRefs(session));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCacheSession = do_QueryInterface(session, &rv);
|
||||
mMainCacheSession = do_QueryInterface(session, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Partial updates don't use temporary cache sessions
|
||||
if (aPartialUpdate) {
|
||||
mCacheSession = mMainCacheSession;
|
||||
} else {
|
||||
rv = cacheService->CreateTemporaryClientID(nsICache::STORE_OFFLINE,
|
||||
mClientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = cacheService->CreateSession(mClientID.get(),
|
||||
nsICache::STORE_OFFLINE,
|
||||
nsICache::STREAM_BASED,
|
||||
getter_AddRefs(session));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCacheSession = do_QueryInterface(session, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
mState = STATE_INITIALIZED;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -424,10 +474,23 @@ nsOfflineCacheUpdate::LoadCompleted()
|
|||
|
||||
LOG(("nsOfflineCacheUpdate::LoadCompleted [%p]", this));
|
||||
|
||||
NS_ASSERTION(mItems.Length() >= 1, "Unknown load completed");
|
||||
nsRefPtr<nsOfflineCacheUpdateItem> item = mItems[mCurrentItem];
|
||||
mCurrentItem++;
|
||||
|
||||
nsRefPtr<nsOfflineCacheUpdateItem> item = mItems[0];
|
||||
mItems.RemoveElementAt(0);
|
||||
PRUint16 status;
|
||||
rv = item->GetStatus(&status);
|
||||
|
||||
// Check for failures. Only connection or server errors (5XX) will cause
|
||||
// the update to fail.
|
||||
if (NS_FAILED(rv) || status == 0 || status >= 500) {
|
||||
// Only fail updates from this domain. Outside-of-domain updates
|
||||
// are not guaranteeed to be updated.
|
||||
nsCAutoString domain;
|
||||
item->mURI->GetHostPort(domain);
|
||||
if (domain == mUpdateDomain) {
|
||||
mSucceeded = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
rv = NotifyCompleted(item);
|
||||
if (NS_FAILED(rv)) return;
|
||||
|
@ -449,6 +512,7 @@ nsOfflineCacheUpdate::Begin()
|
|||
|
||||
mState = STATE_RUNNING;
|
||||
|
||||
mCurrentItem = 0;
|
||||
ProcessNextURI();
|
||||
|
||||
return NS_OK;
|
||||
|
@ -460,10 +524,12 @@ nsOfflineCacheUpdate::Cancel()
|
|||
LOG(("nsOfflineCacheUpdate::Cancel [%p]", this));
|
||||
|
||||
mState = STATE_CANCELLED;
|
||||
mSucceeded = PR_FALSE;
|
||||
|
||||
if (mItems.Length() > 0) {
|
||||
// First load might be running
|
||||
mItems[0]->Cancel();
|
||||
if (mCurrentItem >= 0 &&
|
||||
mCurrentItem < static_cast<PRInt32>(mItems.Length())) {
|
||||
// Load might be running
|
||||
mItems[mCurrentItem]->Cancel();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -478,8 +544,8 @@ nsOfflineCacheUpdate::AddOwnedItems(const nsACString &aOwnerURI)
|
|||
{
|
||||
PRUint32 count;
|
||||
char **keys;
|
||||
nsresult rv = mCacheSession->GetOwnedKeys(mUpdateDomain, aOwnerURI,
|
||||
&count, &keys);
|
||||
nsresult rv = mMainCacheSession->GetOwnedKeys(mUpdateDomain, aOwnerURI,
|
||||
&count, &keys);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
AutoFreeArray autoFree(count, keys);
|
||||
|
@ -488,7 +554,8 @@ nsOfflineCacheUpdate::AddOwnedItems(const nsACString &aOwnerURI)
|
|||
nsCOMPtr<nsIURI> uri;
|
||||
if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), keys[i]))) {
|
||||
nsRefPtr<nsOfflineCacheUpdateItem> item =
|
||||
new nsOfflineCacheUpdateItem(this, uri, mReferrerURI, nsnull);
|
||||
new nsOfflineCacheUpdateItem(this, uri, mReferrerURI,
|
||||
nsnull, mClientID);
|
||||
if (!item) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mItems.AppendElement(item);
|
||||
|
@ -504,7 +571,7 @@ nsOfflineCacheUpdate::AddDomainItems()
|
|||
{
|
||||
PRUint32 count;
|
||||
char **uris;
|
||||
nsresult rv = mCacheSession->GetOwnerURIs(mUpdateDomain, &count, &uris);
|
||||
nsresult rv = mMainCacheSession->GetOwnerURIs(mUpdateDomain, &count, &uris);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
AutoFreeArray autoFree(count, uris);
|
||||
|
@ -525,22 +592,23 @@ nsOfflineCacheUpdate::AddDomainItems()
|
|||
nsresult
|
||||
nsOfflineCacheUpdate::ProcessNextURI()
|
||||
{
|
||||
LOG(("nsOfflineCacheUpdate::ProcessNextURI [%p, numItems=%d]",
|
||||
this, mItems.Length()));
|
||||
LOG(("nsOfflineCacheUpdate::ProcessNextURI [%p, current=%d, numItems=%d]",
|
||||
this, mCurrentItem, mItems.Length()));
|
||||
|
||||
if (mState == STATE_CANCELLED || mItems.Length() == 0) {
|
||||
if (mState == STATE_CANCELLED ||
|
||||
mCurrentItem >= static_cast<PRInt32>(mItems.Length())) {
|
||||
return Finish();
|
||||
}
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
if (LOG_ENABLED()) {
|
||||
nsCAutoString spec;
|
||||
mItems[0]->mURI->GetSpec(spec);
|
||||
mItems[mCurrentItem]->mURI->GetSpec(spec);
|
||||
LOG(("%p: Opening channel for %s", this, spec.get()));
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult rv = mItems[0]->OpenChannel();
|
||||
nsresult rv = mItems[mCurrentItem]->OpenChannel();
|
||||
if (NS_FAILED(rv)) {
|
||||
LoadCompleted();
|
||||
return rv;
|
||||
|
@ -584,6 +652,21 @@ nsOfflineCacheUpdate::Finish()
|
|||
nsOfflineCacheUpdateService *service =
|
||||
nsOfflineCacheUpdateService::GetInstance();
|
||||
|
||||
if (!mPartialUpdate) {
|
||||
if (mSucceeded) {
|
||||
nsresult rv = mMainCacheSession->MergeTemporaryClientID(mClientID);
|
||||
if (NS_FAILED(rv))
|
||||
mSucceeded = PR_FALSE;
|
||||
}
|
||||
|
||||
if (!mSucceeded) {
|
||||
// Update was not merged, mark all the loads as failures
|
||||
for (PRUint32 i = 0; i < mItems.Length(); i++) {
|
||||
mItems[i]->Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!service)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
@ -651,8 +734,9 @@ nsOfflineCacheUpdate::AddURI(nsIURI *aURI, nsIDOMNode *aSource)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsRefPtr<nsOfflineCacheUpdateItem> item =
|
||||
new nsOfflineCacheUpdateItem(this, aURI, mReferrerURI, aSource);
|
||||
nsRefPtr<nsOfflineCacheUpdateItem> item =
|
||||
new nsOfflineCacheUpdateItem(this, aURI, mReferrerURI,
|
||||
aSource, mClientID);
|
||||
if (!item) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mItems.AppendElement(item);
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
#include "nsIOfflineCacheSession.h"
|
||||
#include "nsIPrefetchService.h"
|
||||
#include "nsIRequestObserver.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
|
@ -67,6 +68,7 @@ class nsOfflineCacheUpdate;
|
|||
|
||||
class nsOfflineCacheUpdateItem : public nsIDOMLoadStatus
|
||||
, public nsIStreamListener
|
||||
, public nsIRunnable
|
||||
, public nsIInterfaceRequestor
|
||||
, public nsIChannelEventSink
|
||||
{
|
||||
|
@ -75,18 +77,21 @@ public:
|
|||
NS_DECL_NSIDOMLOADSTATUS
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIRUNNABLE
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
|
||||
nsOfflineCacheUpdateItem(nsOfflineCacheUpdate *aUpdate,
|
||||
nsIURI *aURI,
|
||||
nsIURI *aReferrerURI,
|
||||
nsIDOMNode *aSource);
|
||||
nsIDOMNode *aSource,
|
||||
const nsACString &aClientID);
|
||||
~nsOfflineCacheUpdateItem();
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIURI> mReferrerURI;
|
||||
nsCOMPtr<nsIWeakReference> mSource;
|
||||
nsCString mClientID;
|
||||
|
||||
nsresult OpenChannel();
|
||||
nsresult Cancel();
|
||||
|
@ -131,14 +136,19 @@ private:
|
|||
|
||||
PRBool mAddedItems;
|
||||
PRBool mPartialUpdate;
|
||||
PRBool mSucceeded;
|
||||
nsCString mUpdateDomain;
|
||||
nsCString mOwnerURI;
|
||||
nsCOMPtr<nsIURI> mReferrerURI;
|
||||
|
||||
nsCString mClientID;
|
||||
nsCOMPtr<nsIOfflineCacheSession> mCacheSession;
|
||||
nsCOMPtr<nsIOfflineCacheSession> mMainCacheSession;
|
||||
|
||||
nsCOMPtr<nsIObserverService> mObserverService;
|
||||
|
||||
/* Items being updated */
|
||||
PRInt32 mCurrentItem;
|
||||
nsTArray<nsRefPtr<nsOfflineCacheUpdateItem> > mItems;
|
||||
|
||||
/* Clients watching this update for changes */
|
||||
|
|
Загрузка…
Ссылка в новой задаче