Bug 442806: Use seperate, versioned caches for offline apps. r+sr=bz
This commit is contained in:
Родитель
92ad32b4a2
Коммит
b3962f72df
|
@ -5408,14 +5408,8 @@ var OfflineApps = {
|
|||
// XXX: duplicated in preferences/advanced.js
|
||||
_getOfflineAppUsage: function (host)
|
||||
{
|
||||
var cacheService = Components.classes["@mozilla.org/network/cache-service;1"].
|
||||
getService(Components.interfaces.nsICacheService);
|
||||
var cacheSession = cacheService.createSession("HTTP-offline",
|
||||
Components.interfaces.nsICache.STORE_OFFLINE,
|
||||
true).
|
||||
QueryInterface(Components.interfaces.nsIOfflineCacheSession);
|
||||
var usage = cacheSession.getDomainUsage(host);
|
||||
|
||||
// XXX Bug 442810: include offline cache usage.
|
||||
var usage = 0;
|
||||
var storageManager = Components.classes["@mozilla.org/dom/storagemanager;1"].
|
||||
getService(Components.interfaces.nsIDOMStorageManager);
|
||||
usage += storageManager.getUsage(host);
|
||||
|
|
|
@ -216,13 +216,8 @@ var gAdvancedPane = {
|
|||
// XXX: duplicated in browser.js
|
||||
_getOfflineAppUsage: function (host)
|
||||
{
|
||||
var cacheService = Components.classes["@mozilla.org/network/cache-service;1"].
|
||||
getService(Components.interfaces.nsICacheService);
|
||||
var cacheSession = cacheService.createSession("HTTP-offline",
|
||||
Components.interfaces.nsICache.STORE_OFFLINE,
|
||||
true).
|
||||
QueryInterface(Components.interfaces.nsIOfflineCacheSession);
|
||||
var usage = cacheSession.getDomainUsage(host);
|
||||
// XXX Bug 442710: include offline cache usage.
|
||||
var usage = 0;
|
||||
|
||||
var storageManager = Components.classes["@mozilla.org/dom/storagemanager;1"].
|
||||
getService(Components.interfaces.nsIDOMStorageManager);
|
||||
|
|
|
@ -71,6 +71,8 @@
|
|||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsIOfflineCacheUpdate.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsIApplicationCacheContainer.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIDOMLoadStatus.h"
|
||||
#include "nsICookieService.h"
|
||||
|
@ -881,6 +883,24 @@ nsContentSink::ProcessOfflineManifest(nsIContent *aElement)
|
|||
return;
|
||||
}
|
||||
|
||||
// XXX: at this point in the spec there is an algorithm for
|
||||
// confirming whether the cache that was selected at load time was
|
||||
// the proper application cache for this document. This will
|
||||
// be implemented in a separate patch; For now just assume that we
|
||||
// chose an acceptable application cache.
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheContainer> channelContainer =
|
||||
do_QueryInterface(mDocument->GetChannel());
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheContainer> docContainer =
|
||||
do_QueryInterface(mDocument);
|
||||
|
||||
if (channelContainer && docContainer) {
|
||||
nsCOMPtr<nsIApplicationCache> appCache;
|
||||
channelContainer->GetApplicationCache(getter_AddRefs(appCache));
|
||||
docContainer->SetApplicationCache(appCache);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> manifestURI;
|
||||
nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(manifestURI),
|
||||
manifestSpec, mDocument,
|
||||
|
|
|
@ -804,41 +804,7 @@ nsContentUtils::GetOfflineAppManifest(nsIDOMWindow *aWindow, nsIURI **aURI)
|
|||
PRBool
|
||||
nsContentUtils::OfflineAppAllowed(nsIURI *aURI)
|
||||
{
|
||||
nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(aURI);
|
||||
if (!innerURI)
|
||||
return PR_FALSE;
|
||||
|
||||
// only http and https applications can use offline APIs.
|
||||
PRBool match;
|
||||
nsresult rv = innerURI->SchemeIs("http", &match);
|
||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
||||
|
||||
if (!match) {
|
||||
rv = innerURI->SchemeIs("https", &match);
|
||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
||||
if (!match) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> permissionManager =
|
||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||
if (!permissionManager) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRUint32 perm;
|
||||
permissionManager->TestExactPermission(innerURI, "offline-app", &perm);
|
||||
|
||||
if (perm == nsIPermissionManager::UNKNOWN_ACTION) {
|
||||
return GetBoolPref("offline-apps.allow_by_default");
|
||||
}
|
||||
|
||||
if (perm == nsIPermissionManager::DENY_ACTION) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
return NS_OfflineAppAllowed(aURI, sPrefBranch);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -1143,6 +1143,7 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
|
|||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIRadioGroupContainer)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIMutationObserver)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMNodeSelector)
|
||||
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIApplicationCacheContainer)
|
||||
// nsNodeSH::PreCreate() depends on the identity pointer being the
|
||||
// same as nsINode (which nsIDocument inherits), so if you change
|
||||
// the below line, make sure nsNodeSH::PreCreate() still does the
|
||||
|
@ -1953,6 +1954,22 @@ nsDocument::SetPrincipal(nsIPrincipal *aNewPrincipal)
|
|||
mNodeInfoManager->SetDocumentPrincipal(aNewPrincipal);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::GetApplicationCache(nsIApplicationCache **aApplicationCache)
|
||||
{
|
||||
NS_IF_ADDREF(*aApplicationCache = mApplicationCache);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::SetApplicationCache(nsIApplicationCache *aApplicationCache)
|
||||
{
|
||||
mApplicationCache = aApplicationCache;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::GetContentType(nsAString& aContentType)
|
||||
{
|
||||
|
|
|
@ -93,6 +93,8 @@
|
|||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsContentList.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsIApplicationCacheContainer.h"
|
||||
|
||||
// Put these here so all document impls get them automatically
|
||||
#include "nsHTMLStyleSheet.h"
|
||||
|
@ -408,6 +410,7 @@ class nsDocument : public nsIDocument,
|
|||
public nsIScriptObjectPrincipal,
|
||||
public nsIRadioGroupContainer,
|
||||
public nsIDOMNodeSelector,
|
||||
public nsIApplicationCacheContainer,
|
||||
public nsStubMutationObserver
|
||||
{
|
||||
public:
|
||||
|
@ -752,6 +755,9 @@ public:
|
|||
// nsIScriptObjectPrincipal
|
||||
virtual nsIPrincipal* GetPrincipal();
|
||||
|
||||
// nsIApplicationCacheContainer
|
||||
NS_DECL_NSIAPPLICATIONCACHECONTAINER
|
||||
|
||||
virtual nsresult Init();
|
||||
|
||||
virtual nsresult AddXMLEventsContent(nsIContent * aXMLEventsElement);
|
||||
|
@ -1021,6 +1027,10 @@ protected:
|
|||
// Our update nesting level
|
||||
PRUint32 mUpdateNestLevel;
|
||||
|
||||
// The application cache that this document is associated with, if
|
||||
// any. This can change during the lifetime of the document.
|
||||
nsCOMPtr<nsIApplicationCache> mApplicationCache;
|
||||
|
||||
private:
|
||||
friend class nsUnblockOnloadEvent;
|
||||
|
||||
|
|
|
@ -143,6 +143,9 @@
|
|||
#include "nsINestedURI.h"
|
||||
#include "nsITransportSecurityInfo.h"
|
||||
#include "nsINSSErrorsService.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsIApplicationCacheContainer.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
|
||||
// Editor-related
|
||||
#include "nsIEditingSession.h"
|
||||
|
@ -458,6 +461,22 @@ NS_IMETHODIMP nsDocShell::GetInterface(const nsIID & aIID, void **aSink)
|
|||
mContentViewer->GetDOMDocument((nsIDOMDocument **) aSink);
|
||||
return *aSink ? NS_OK : NS_NOINTERFACE;
|
||||
}
|
||||
else if (aIID.Equals(NS_GET_IID(nsIApplicationCacheContainer)) &&
|
||||
NS_SUCCEEDED(EnsureContentViewer())) {
|
||||
*aSink = nsnull;
|
||||
|
||||
// Return the toplevel document as an
|
||||
// nsIApplicationCacheContainer.
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> rootItem;
|
||||
GetSameTypeRootTreeItem(getter_AddRefs(rootItem));
|
||||
nsCOMPtr<nsIDOMDocument> domDoc = do_GetInterface(rootItem);
|
||||
NS_ASSERTION(domDoc, "Should have a document.");
|
||||
if (!domDoc)
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
|
||||
return domDoc->QueryInterface(aIID, aSink);
|
||||
}
|
||||
else if (aIID.Equals(NS_GET_IID(nsIPrompt)) &&
|
||||
NS_SUCCEEDED(EnsureScriptEnvironment())) {
|
||||
nsresult rv;
|
||||
|
@ -7275,6 +7294,15 @@ nsDocShell::DoURILoad(nsIURI * aURI,
|
|||
if (aFirstParty) {
|
||||
// tag first party URL loads
|
||||
loadFlags |= nsIChannel::LOAD_INITIAL_DOCUMENT_URI;
|
||||
|
||||
// Toplevel document loads in domains with the offline-app
|
||||
// permission should check for an associated application
|
||||
// cache.
|
||||
nsCOMPtr<nsIDocShellTreeItem> root;
|
||||
GetSameTypeRootTreeItem(getter_AddRefs(root));
|
||||
if (root == this && NS_OfflineAppAllowed(aURI)) {
|
||||
loadFlags |= nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE;
|
||||
}
|
||||
}
|
||||
|
||||
if (mLoadType == LOAD_ERROR_PAGE) {
|
||||
|
|
|
@ -59,6 +59,7 @@ REQUIRES = xpcom \
|
|||
nkcache \
|
||||
pref \
|
||||
prefetch \
|
||||
docshell \
|
||||
widget \
|
||||
xpconnect \
|
||||
$(NULL)
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include "nsNetCID.h"
|
||||
#include "nsICacheSession.h"
|
||||
#include "nsICacheService.h"
|
||||
#include "nsIOfflineCacheSession.h"
|
||||
#include "nsIOfflineCacheUpdate.h"
|
||||
#include "nsIDOMLoadStatus.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
@ -55,6 +54,7 @@
|
|||
#include "nsIPrivateDOMEvent.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
|
||||
// Event names
|
||||
|
||||
|
@ -73,7 +73,7 @@ static const char kMaxEntriesPref[] = "offline.max_site_resources";
|
|||
#define DEFAULT_MAX_ENTRIES 100
|
||||
#define MAX_URI_LENGTH 2048
|
||||
|
||||
static nsCAutoString gCachedAsciiHost;
|
||||
static nsCAutoString gCachedManifestSpec;
|
||||
static char **gCachedKeys = nsnull;
|
||||
static PRUint32 gCachedKeysCount = 0;
|
||||
|
||||
|
@ -85,7 +85,6 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMOfflineResourceList)
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMOfflineResourceList)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCacheSession)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCacheUpdate)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mCheckingListeners)
|
||||
|
@ -114,7 +113,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMOfflineResourceList)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCacheSession)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCacheUpdate)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mCheckingListeners)
|
||||
|
@ -181,36 +179,20 @@ nsDOMOfflineResourceList::Init()
|
|||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
mManifestURI->GetAsciiSpec(mManifestSpec);
|
||||
|
||||
nsresult rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckSameOriginURI(mManifestURI, mDocumentURI, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Dynamically-managed resources are stored as a separate ownership list
|
||||
// from the manifest.
|
||||
rv = mManifestURI->GetAsciiSpec(mDynamicOwnerSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mDynamicOwnerSpec.Append("#dynamic");
|
||||
|
||||
nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(mDocumentURI);
|
||||
if (!innerURI)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
rv = innerURI->GetAsciiHost(mAsciiHost);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsICacheService> serv = do_GetService(NS_CACHESERVICE_CONTRACTID,
|
||||
&rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
rv = serv->CreateSession("HTTP-offline",
|
||||
nsICache::STORE_OFFLINE,
|
||||
nsICache::STREAM_BASED,
|
||||
getter_AddRefs(session));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCacheSession = do_QueryInterface(session, &rv);
|
||||
mApplicationCacheService =
|
||||
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Check for in-progress cache updates
|
||||
|
@ -319,6 +301,11 @@ nsDOMOfflineResourceList::Add(const nsAString& aURI)
|
|||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIApplicationCache> appCache = GetDocumentAppCache();
|
||||
if (!appCache) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
if (aURI.Length() > MAX_URI_LENGTH) return NS_ERROR_DOM_BAD_URI;
|
||||
|
||||
// this will fail if the URI is not absolute
|
||||
|
@ -374,16 +361,24 @@ nsDOMOfflineResourceList::Remove(const nsAString& aURI)
|
|||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIApplicationCache> appCache = GetDocumentAppCache();
|
||||
if (!appCache) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
nsCAutoString key;
|
||||
rv = GetCacheKey(aURI, key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ClearCachedKeys();
|
||||
|
||||
rv = mCacheSession->RemoveOwnedKey(mAsciiHost, mDynamicOwnerSpec, key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// XXX: This is a race condition. remove() is specced to remove
|
||||
// from the currently associated application cache, but if this
|
||||
// happens during an update (or after an update, if we haven't
|
||||
// swapped yet), that remove() will be lost when the next update is
|
||||
// finished. Need to bring this issue up.
|
||||
|
||||
rv = mCacheSession->EvictUnownedEntries();
|
||||
rv = appCache->UnmarkEntry(key, nsIApplicationCache::ITEM_DYNAMIC);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -394,29 +389,41 @@ nsDOMOfflineResourceList::GetStatus(PRUint16 *aStatus)
|
|||
{
|
||||
nsresult rv = Init();
|
||||
|
||||
// It is OK to check the status without a manifest attribute (you'll
|
||||
// just get "uncached").
|
||||
if (rv == NS_ERROR_DOM_INVALID_STATE_ERR && !mManifestURI) {
|
||||
// Init may fail with INVALID_STATE_ERR if there is no manifest URI.
|
||||
// The status attribute should not throw that exception, convert it
|
||||
// to an UNCACHED.
|
||||
if (rv == NS_ERROR_DOM_INVALID_STATE_ERR ||
|
||||
!nsContentUtils::OfflineAppAllowed(mDocumentURI)) {
|
||||
*aStatus = nsIDOMOfflineResourceList::UNCACHED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If there is an update in process, use its status.
|
||||
if (mCacheUpdate) {
|
||||
return mCacheUpdate->GetStatus(aStatus);
|
||||
rv = mCacheUpdate->GetStatus(aStatus);
|
||||
if (NS_SUCCEEDED(rv) && *aStatus != nsIDOMOfflineResourceList::IDLE) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: the spec allows either UNCACHED or IDLE, depending on whether
|
||||
// the application is associated with a specific offline cache. Until
|
||||
// we have versioned application caches, the best approximation is
|
||||
// probably IDLE if the offline-app permission is set, and UNCACHED
|
||||
// otherwise.
|
||||
// If this object is not associated with a cache, return UNCACHED
|
||||
nsCOMPtr<nsIApplicationCache> appCache = GetDocumentAppCache();
|
||||
if (!appCache) {
|
||||
*aStatus = nsIDOMOfflineResourceList::UNCACHED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (nsContentUtils::OfflineAppAllowed(mDocumentURI)) {
|
||||
nsCOMPtr<nsIApplicationCache> activeCache;
|
||||
rv = mApplicationCacheService->GetActiveCache(mManifestSpec,
|
||||
getter_AddRefs(activeCache));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (appCache == activeCache) {
|
||||
*aStatus = nsIDOMOfflineResourceList::IDLE;
|
||||
} else {
|
||||
*aStatus = nsIDOMOfflineResourceList::UNCACHED;
|
||||
*aStatus = nsIDOMOfflineResourceList::UPDATEREADY;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -454,7 +461,35 @@ nsDOMOfflineResourceList::SwapCache()
|
|||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
if (!mToplevel) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheService> serv =
|
||||
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIApplicationCache> currentAppCache = GetDocumentAppCache();
|
||||
|
||||
nsCOMPtr<nsIApplicationCache> newAppCache;
|
||||
rv = serv->GetActiveCache(mManifestSpec, getter_AddRefs(newAppCache));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!newAppCache || newAppCache == currentAppCache) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
ClearCachedKeys();
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer =
|
||||
GetDocumentAppCacheContainer();
|
||||
|
||||
if (appCacheContainer) {
|
||||
rv = appCacheContainer->SetApplicationCache(newAppCache);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -944,20 +979,25 @@ nsDOMOfflineResourceList::UpdateCompleted(nsIOfflineCacheUpdate *aUpdate)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool partial;
|
||||
mCacheUpdate->GetPartial(&partial);
|
||||
PRBool isUpgrade;
|
||||
mCacheUpdate->GetIsUpgrade(&isUpgrade);
|
||||
|
||||
PRBool succeeded;
|
||||
nsresult rv = mCacheUpdate->GetSucceeded(&succeeded);
|
||||
|
||||
mCacheUpdate->RemoveObserver(this);
|
||||
mCacheUpdate = nsnull;
|
||||
|
||||
if (NS_SUCCEEDED(rv) && succeeded) {
|
||||
// XXX: the spec requires a "cached" event to be sent if this is a
|
||||
// first-time cache attempt, and "updateready" if this page was loaded
|
||||
// from an existing application cache. Since we don't have versioned
|
||||
// application caches yet, basically each update acts like a first-time
|
||||
// update, so we'll always fire "cached" for now.
|
||||
SendEvent(NS_LITERAL_STRING(CACHED_STR),
|
||||
mOnCachedListener, mCachedListeners);
|
||||
if (NS_SUCCEEDED(rv) && succeeded && !partial) {
|
||||
if (isUpgrade) {
|
||||
SendEvent(NS_LITERAL_STRING(UPDATEREADY_STR),
|
||||
mOnUpdateReadyListener, mUpdateReadyListeners);
|
||||
} else {
|
||||
SendEvent(NS_LITERAL_STRING(CACHED_STR),
|
||||
mOnCachedListener, mCachedListeners);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -981,19 +1021,61 @@ nsDOMOfflineResourceList::GetCacheKey(nsIURI *aURI, nsCString &aKey)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIApplicationCacheContainer>
|
||||
nsDOMOfflineResourceList::GetDocumentAppCacheContainer()
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindow> window = do_QueryReferent(mWindow);
|
||||
if (!window) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWebNavigation> webnav = do_GetInterface(window);
|
||||
if (!webnav) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer =
|
||||
do_GetInterface(webnav);
|
||||
return appCacheContainer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIApplicationCache>
|
||||
nsDOMOfflineResourceList::GetDocumentAppCache()
|
||||
{
|
||||
nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer =
|
||||
GetDocumentAppCacheContainer();
|
||||
|
||||
if (appCacheContainer) {
|
||||
nsCOMPtr<nsIApplicationCache> applicationCache;
|
||||
appCacheContainer->GetApplicationCache(
|
||||
getter_AddRefs(applicationCache));
|
||||
return applicationCache.forget();
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDOMOfflineResourceList::CacheKeys()
|
||||
{
|
||||
if (gCachedKeys && mAsciiHost == gCachedAsciiHost)
|
||||
if (gCachedKeys && mManifestSpec == gCachedManifestSpec)
|
||||
return NS_OK;
|
||||
|
||||
ClearCachedKeys();
|
||||
|
||||
nsresult rv = mCacheSession->GetOwnedKeys(mAsciiHost, mDynamicOwnerSpec,
|
||||
&gCachedKeysCount, &gCachedKeys);
|
||||
nsCOMPtr<nsIApplicationCache> appCache;
|
||||
mApplicationCacheService->GetActiveCache(mManifestSpec,
|
||||
getter_AddRefs(appCache));
|
||||
|
||||
if (!appCache) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
nsresult rv = appCache->GatherEntries(nsIApplicationCache::ITEM_DYNAMIC,
|
||||
&gCachedKeysCount, &gCachedKeys);
|
||||
|
||||
if (NS_SUCCEEDED(rv))
|
||||
gCachedAsciiHost = mAsciiHost;
|
||||
gCachedManifestSpec = mManifestSpec;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -1007,8 +1089,6 @@ nsDOMOfflineResourceList::ClearCachedKeys()
|
|||
gCachedKeysCount = 0;
|
||||
}
|
||||
|
||||
gCachedAsciiHost = "";
|
||||
gCachedManifestSpec = "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -41,7 +41,9 @@
|
|||
|
||||
#include "nscore.h"
|
||||
#include "nsIDOMOfflineResourceList.h"
|
||||
#include "nsIOfflineCacheSession.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsIApplicationCacheContainer.h"
|
||||
#include "nsIApplicationCacheService.h"
|
||||
#include "nsIOfflineCacheUpdate.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsString.h"
|
||||
|
@ -97,6 +99,9 @@ private:
|
|||
nsresult UpdateAdded(nsIOfflineCacheUpdate *aUpdate);
|
||||
nsresult UpdateCompleted(nsIOfflineCacheUpdate *aUpdate);
|
||||
|
||||
already_AddRefed<nsIApplicationCacheContainer> GetDocumentAppCacheContainer();
|
||||
already_AddRefed<nsIApplicationCache> GetDocumentAppCache();
|
||||
|
||||
nsresult GetCacheKey(const nsAString &aURI, nsCString &aKey);
|
||||
nsresult GetCacheKey(nsIURI *aURI, nsCString &aKey);
|
||||
|
||||
|
@ -105,13 +110,15 @@ private:
|
|||
|
||||
PRBool mInitialized;
|
||||
PRBool mToplevel;
|
||||
|
||||
nsCOMPtr<nsIURI> mManifestURI;
|
||||
// AsciiSpec of mManifestURI
|
||||
nsCString mManifestSpec;
|
||||
|
||||
nsCOMPtr<nsIURI> mDocumentURI;
|
||||
nsCOMPtr<nsIWeakReference> mWindow;
|
||||
nsCOMPtr<nsIOfflineCacheSession> mCacheSession;
|
||||
nsCOMPtr<nsIApplicationCacheService> mApplicationCacheService;
|
||||
nsCOMPtr<nsIOfflineCacheUpdate> mCacheUpdate;
|
||||
nsCAutoString mAsciiHost;
|
||||
nsCAutoString mDynamicOwnerSpec;
|
||||
|
||||
nsCOMArray<nsIDOMEventListener> mCheckingListeners;
|
||||
nsCOMArray<nsIDOMEventListener> mErrorListeners;
|
||||
|
|
|
@ -51,14 +51,9 @@ fetch: function(callback)
|
|||
var url = this.urls.shift();
|
||||
var self = this;
|
||||
|
||||
var cacheService = Cc["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Ci.nsICacheService);
|
||||
var cacheSession = cacheService.createSession("HTTP-offline",
|
||||
Ci.nsICache.STORE_OFFLINE,
|
||||
true);
|
||||
var cacheSession = OfflineTest.getActiveSession();
|
||||
cacheSession.asyncOpenCacheEntry(url, Ci.nsICache.ACCESS_READ, this);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var OfflineTest = {
|
||||
|
@ -167,29 +162,13 @@ isnot: function(a, b, name)
|
|||
|
||||
clear: function()
|
||||
{
|
||||
// Clear the ownership list
|
||||
var cacheService = Cc["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Ci.nsICacheService);
|
||||
var cacheSession = cacheService.createSession("HTTP-offline",
|
||||
Ci.nsICache.STORE_OFFLINE,
|
||||
true)
|
||||
.QueryInterface(Ci.nsIOfflineCacheSession);
|
||||
|
||||
// Get the asciiHost from the page URL
|
||||
var locationURI = Cc["@mozilla.org/network/standard-url;1"]
|
||||
.createInstance(Ci.nsIURI);
|
||||
locationURI.spec = window.location.href;
|
||||
var asciiHost = locationURI.asciiHost;
|
||||
|
||||
// Clear manifest-owned urls
|
||||
cacheSession.setOwnedKeys(asciiHost,
|
||||
this.getManifestUrl() + "#manifest", 0, []);
|
||||
|
||||
// Clear dynamically-owned urls
|
||||
cacheSession.setOwnedKeys(asciiHost,
|
||||
this.getManifestUrl() + "#dynamic", 0, []);
|
||||
|
||||
cacheSession.evictUnownedEntries();
|
||||
// XXX: maybe we should just wipe out the entire disk cache.
|
||||
var appCacheService = Cc["@mozilla.org/network/application-cache-service;1"]
|
||||
.getService(Ci.nsIApplicationCacheService);
|
||||
var applicationCache = this.getActiveCache();
|
||||
if (applicationCache) {
|
||||
applicationCache.discard();
|
||||
}
|
||||
},
|
||||
|
||||
failEvent: function(e)
|
||||
|
@ -203,11 +182,7 @@ waitForAdd: function(url, onFinished) {
|
|||
// Check every half second for ten seconds.
|
||||
var numChecks = 20;
|
||||
var waitFunc = function() {
|
||||
var cacheService = Cc["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Ci.nsICacheService);
|
||||
var cacheSession = cacheService.createSession("HTTP-offline",
|
||||
Ci.nsICache.STORE_OFFLINE,
|
||||
true);
|
||||
var cacheSession = OfflineTest.getActiveSession();
|
||||
var entry;
|
||||
try {
|
||||
var entry = cacheSession.openCacheEntry(url, Ci.nsICache.ACCESS_READ, true);
|
||||
|
@ -236,6 +211,27 @@ getManifestUrl: function()
|
|||
return window.top.document.documentElement.getAttribute("manifest");
|
||||
},
|
||||
|
||||
getActiveCache: function()
|
||||
{
|
||||
// Note that this is the current active cache in the cache stack, not the
|
||||
// one associated with this window.
|
||||
var serv = Cc["@mozilla.org/network/application-cache-service;1"]
|
||||
.getService(Ci.nsIApplicationCacheService);
|
||||
return serv.getActiveCache(this.getManifestUrl());
|
||||
},
|
||||
|
||||
getActiveSession: function()
|
||||
{
|
||||
var cache = this.getActiveCache();
|
||||
if (!cache) return null;
|
||||
|
||||
var cacheService = Cc["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Ci.nsICacheService);
|
||||
return cacheService.createSession(cache.clientID,
|
||||
Ci.nsICache.STORE_OFFLINE,
|
||||
true);
|
||||
},
|
||||
|
||||
priv: function(func)
|
||||
{
|
||||
var self = this;
|
||||
|
@ -247,11 +243,16 @@ priv: function(func)
|
|||
|
||||
checkCache: function(url, expectEntry)
|
||||
{
|
||||
var cacheService = Cc["@mozilla.org/network/cache-service;1"]
|
||||
.getService(Ci.nsICacheService);
|
||||
var cacheSession = cacheService.createSession("HTTP-offline",
|
||||
Ci.nsICache.STORE_OFFLINE,
|
||||
true);
|
||||
var cacheSession = this.getActiveSession();
|
||||
if (!cacheSession) {
|
||||
if (expectEntry) {
|
||||
this.ok(false, url + " should exist in the offline cache");
|
||||
} else {
|
||||
this.ok(true, url + " should not exist in the offline cache");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var entry = cacheSession.openCacheEntry(url, Ci.nsICache.ACCESS_READ, false);
|
||||
if (expectEntry) {
|
||||
|
@ -267,7 +268,7 @@ checkCache: function(url, expectEntry)
|
|||
} else {
|
||||
this.ok(true, url + " should not exist in the offline cache");
|
||||
}
|
||||
} else if (e.result == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) {
|
||||
} else if (e.result == NS_ERROR_CACHE_KEY_WAIT_FOR_VALIDATION) {
|
||||
// There was a cache key that we couldn't access yet, that's good enough.
|
||||
if (expectEntry) {
|
||||
this.ok(true, url + " should exist in the offline cache");
|
||||
|
|
|
@ -51,8 +51,9 @@ function manifestUpdated()
|
|||
gCacheContents = contents;
|
||||
|
||||
// Now make sure applicationCache.update() does what we expect.
|
||||
applicationCache.oncached = OfflineTest.priv(manifestUpdatedAgain);
|
||||
applicationCache.onupdateready = OfflineTest.priv(manifestUpdatedAgain);
|
||||
applicationCache.onnoupdate = failAndFinish;
|
||||
applicationCache.oncached = failAndFinish;
|
||||
|
||||
gGotChecking = false;
|
||||
gGotDownloading = false;
|
||||
|
|
|
@ -36,26 +36,6 @@ function addFinished()
|
|||
OfflineTest.finish();
|
||||
}
|
||||
|
||||
function secondUpdate()
|
||||
{
|
||||
OfflineTest.ok(gGotChecking, "Should get a checking event");
|
||||
OfflineTest.ok(gGotDownloading, "Should get a downloading event");
|
||||
|
||||
// The document that requested the manifest should be in the cache
|
||||
OfflineTest.checkCache(window.location.href, true);
|
||||
|
||||
OfflineTest.checkCache("http://localhost:8888/tests/SimpleTest/SimpleTest.js", true);
|
||||
OfflineTest.checkCache("http://localhost:8888/MochiKit/packed.js", true);
|
||||
OfflineTest.checkCache("http://localhost:8888/tests/dom/tests/mochitest/ajax/offline/offlineTests.js", true);
|
||||
|
||||
// Now add a file using the applicationCache API
|
||||
applicationCache.add("http://localhost:8888/tests/SimpleTest/EventUtils.js");
|
||||
|
||||
// Wait for the add() to be downloaded
|
||||
OfflineTest.waitForAdd("http://localhost:8888/tests/SimpleTest/EventUtils.js",
|
||||
OfflineTest.priv(addFinished));
|
||||
}
|
||||
|
||||
function manifestUpdated()
|
||||
{
|
||||
OfflineTest.ok(gGotChecking, "Should get a checking event");
|
||||
|
@ -76,26 +56,18 @@ function manifestUpdated()
|
|||
OfflineTest.checkCache("https://localhost:8888/MochiKit/packed.js", false);
|
||||
OfflineTest.checkCache("bad:/uri/invalid", false);
|
||||
|
||||
// Remove items from the cache.
|
||||
OfflineTest.clear();
|
||||
applicationCache.swapCache();
|
||||
|
||||
// Make sure OfflineTest.clear() properly removed the items
|
||||
// XXX: make sure that the previous version went away after the swapCache().
|
||||
|
||||
OfflineTest.checkCache("http://localhost:8888/tests/SimpleTest/SimpleTest.js", false);
|
||||
OfflineTest.checkCache("http://localhost:8888/MochiKit/packed.js", false);
|
||||
OfflineTest.checkCache("http://localhost:8888/tests/dom/tests/mochitest/ajax/offline/offlineTests.js", false);
|
||||
OfflineTest.checkCache("http://localhost:8888/tests/SimpleTest/EventUtils.js",
|
||||
false);
|
||||
// Now add a file using the applicationCache API
|
||||
applicationCache.add("http://localhost:8888/tests/SimpleTest/EventUtils.js");
|
||||
|
||||
// Now make sure applicationCache.update() does what we expect.
|
||||
applicationCache.oncached = OfflineTest.priv(secondUpdate);
|
||||
|
||||
gGotChecking = false;
|
||||
gGotDownloading = false;
|
||||
applicationCache.update();
|
||||
// Wait for the add() to be downloaded
|
||||
OfflineTest.waitForAdd("http://localhost:8888/tests/SimpleTest/EventUtils.js",
|
||||
OfflineTest.priv(addFinished));
|
||||
}
|
||||
|
||||
|
||||
if (OfflineTest.setup()) {
|
||||
OfflineTest.ok(applicationCache instanceof EventTarget,
|
||||
"applicationCache should be an event target");
|
||||
|
|
|
@ -61,6 +61,9 @@ SDK_XPIDLSRCS = \
|
|||
$(NULL)
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIApplicationCache.idl \
|
||||
nsIApplicationCacheContainer.idl \
|
||||
nsIApplicationCacheService.idl \
|
||||
nsIAuthInformation.idl \
|
||||
nsIAuthPrompt.idl \
|
||||
nsIAuthPrompt2.idl \
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is nsIApplicationCache.idl.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dave Camp <dcamp@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* Application caches store resources for offline use. Each
|
||||
* application cache has a unique client ID for use with
|
||||
* nsICacheService::openSession() to access the cache's entries.
|
||||
*
|
||||
* Each entry in the application cache can be marked with a set of
|
||||
* types, as discussed in the WHAT-WG offline applications
|
||||
* specification.
|
||||
*
|
||||
* All application caches with the same group ID belong to a cache
|
||||
* group. Each group has one "active" cache that will service future
|
||||
* loads. Inactive caches will be removed from the cache when they are
|
||||
* no longer referenced.
|
||||
*/
|
||||
[scriptable, uuid(a9cfbeef-8f8d-49c3-b899-303390383ae9)]
|
||||
interface nsIApplicationCache : nsISupports
|
||||
{
|
||||
/**
|
||||
* Entries in an application cache can be marked as one or more of
|
||||
* the following types.
|
||||
*/
|
||||
|
||||
/* This item is the application manifest. */
|
||||
const unsigned long ITEM_MANIFEST = 1 << 0;
|
||||
|
||||
/* This item was explicitly listed in the application manifest. */
|
||||
const unsigned long ITEM_EXPLICIT = 1 << 1;
|
||||
|
||||
/* This item was navigated in a toplevel browsing context, and
|
||||
* named this cache's group as its manifest. */
|
||||
const unsigned long ITEM_IMPLICIT = 1 << 2;
|
||||
|
||||
/* This item was added by the dynamic scripting API */
|
||||
const unsigned long ITEM_DYNAMIC = 1 << 3;
|
||||
|
||||
/* This item was listed in the application manifest, but named a
|
||||
* different cache group as its manifest. */
|
||||
const unsigned long ITEM_FOREIGN = 1 << 4;
|
||||
|
||||
/* This item was listed as a fallback entry. */
|
||||
const unsigned long ITEM_FALLBACK = 1 << 5;
|
||||
|
||||
/* This item matched an opportunistic cache namespace and was
|
||||
* cached accordingly. */
|
||||
const unsigned long ITEM_OPPORTUNISTIC = 1 << 6;
|
||||
|
||||
/**
|
||||
* The group ID for this cache group. This is the URI of the
|
||||
* manifest file.
|
||||
**/
|
||||
readonly attribute ACString groupID;
|
||||
|
||||
/**
|
||||
* The client ID for this application cache. Clients can open a
|
||||
* session with nsICacheService::createSession() using this client
|
||||
* ID and a storage policy of STORE_OFFLINE to access this cache.
|
||||
*/
|
||||
readonly attribute ACString clientID;
|
||||
|
||||
/**
|
||||
* TRUE if the cache is the active cache for this group.
|
||||
*/
|
||||
readonly attribute boolean active;
|
||||
|
||||
/**
|
||||
* Makes this cache the active application cache for this group.
|
||||
* Future loads associated with this group will come from this
|
||||
* cache. Other caches from this cache group will be deactivated.
|
||||
*/
|
||||
void activate();
|
||||
|
||||
/**
|
||||
* Discard this application cache. Removes all cached resources
|
||||
* for this cache. If this is the active application cache for the
|
||||
* group, the group will be removed.
|
||||
*/
|
||||
void discard();
|
||||
|
||||
/**
|
||||
* Adds item types to a given entry.
|
||||
*/
|
||||
void markEntry(in ACString key, in unsigned long typeBits);
|
||||
|
||||
/**
|
||||
* Removes types from a given entry. If the resulting entry has
|
||||
* no types left, the entry is removed.
|
||||
*/
|
||||
void unmarkEntry(in ACString key, in unsigned long typeBits);
|
||||
|
||||
/**
|
||||
* Gets the types for a given entry.
|
||||
*/
|
||||
unsigned long getTypes(in ACString key);
|
||||
|
||||
/**
|
||||
* Returns any entries in the application cache whose type matches
|
||||
* one or more of the bits in typeBits.
|
||||
*/
|
||||
void gatherEntries(in PRUint32 typeBits,
|
||||
out unsigned long count,
|
||||
[array, size_is(count)] out string keys);
|
||||
};
|
|
@ -0,0 +1,52 @@
|
|||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is nsIApplicationCache.idl.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dave Camp <dcamp@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIApplicationCache;
|
||||
|
||||
/**
|
||||
* Interface used by objects that can be associated with an
|
||||
* application cache.
|
||||
*/
|
||||
[scriptable, uuid(bbb80700-1f7f-4258-aff4-1743cc5a7d23)]
|
||||
interface nsIApplicationCacheContainer : nsISupports
|
||||
{
|
||||
attribute nsIApplicationCache applicationCache;
|
||||
};
|
|
@ -0,0 +1,71 @@
|
|||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is nsIApplicationCache.idl.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dave Camp <dcamp@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIApplicationCache;
|
||||
|
||||
/**
|
||||
* The application cache service manages the set of application cache
|
||||
* groups.
|
||||
*/
|
||||
[scriptable, uuid(3f411c68-0d17-420d-839a-6355eea877b9)]
|
||||
interface nsIApplicationCacheService : nsISupports
|
||||
{
|
||||
/**
|
||||
* Create a new, empty application cache for the given cache
|
||||
* group.
|
||||
*/
|
||||
nsIApplicationCache createApplicationCache(in ACString group);
|
||||
|
||||
/**
|
||||
* Get an application cache object for the given client ID.
|
||||
*/
|
||||
nsIApplicationCache getApplicationCache(in ACString clientID);
|
||||
|
||||
/**
|
||||
* Get the currently active cache object for a cache group.
|
||||
*/
|
||||
nsIApplicationCache getActiveCache(in ACString group);
|
||||
|
||||
/**
|
||||
* Try to find the best application cache to serve a resource.
|
||||
*/
|
||||
nsIApplicationCache chooseApplicationCache(in ACString key);
|
||||
};
|
|
@ -41,6 +41,7 @@
|
|||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIURI;
|
||||
interface nsIPrefBranch;
|
||||
|
||||
/**
|
||||
* nsINetUtil provides various network-related utility methods.
|
||||
|
@ -220,3 +221,25 @@ interface nsINetUtil : nsISupports
|
|||
out long aCharsetStart,
|
||||
out long aCharsetEnd);
|
||||
};
|
||||
|
||||
/**
|
||||
* nsINetUtil methods added in mozilla 1.9.1.
|
||||
*
|
||||
* XXX bug 451255: Merge this up in to nsINetUtil as soon as possible.
|
||||
*/
|
||||
[scriptable, uuid(da76ab60-2ec5-4649-84c4-4954a08f6d37)]
|
||||
interface nsINetUtil_MOZILLA_1_9_1 : nsISupports
|
||||
{
|
||||
/**
|
||||
* Checks whether a document at the given URI should have access
|
||||
* to the offline cache.
|
||||
* @param aURI
|
||||
* The URI to check
|
||||
* @param aPrefBranch
|
||||
* The pref branch to use to check the
|
||||
* offline-apps.allow_by_default pref. If not specified,
|
||||
* the pref service will be used.
|
||||
*/
|
||||
boolean OfflineAppAllowed(in nsIURI aURI,
|
||||
in nsIPrefBranch aPrefBranch);
|
||||
};
|
||||
|
|
|
@ -1441,4 +1441,28 @@ NS_GetFinalChannelURI(nsIChannel* channel, nsIURI** uri)
|
|||
return channel->GetOriginalURI(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a document at the given URI should have access
|
||||
* to the offline cache.
|
||||
* @param uri
|
||||
* The URI to check
|
||||
* @param prefBranch
|
||||
* The pref branch to use to check the
|
||||
* offline-apps.allow_by_default pref. If not specified,
|
||||
* the pref service will be used.
|
||||
*/
|
||||
inline PRBool
|
||||
NS_OfflineAppAllowed(nsIURI *aURI, nsIPrefBranch *aPrefBranch = nsnull)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsINetUtil_MOZILLA_1_9_1> util = do_GetIOService(&rv);
|
||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
||||
|
||||
PRBool allowed;
|
||||
rv = util->OfflineAppAllowed(aURI, aPrefBranch, &allowed);
|
||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
||||
|
||||
return allowed;
|
||||
}
|
||||
|
||||
#endif // !nsNetUtil_h__
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
#include "nsINestedURI.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
#include "nsNativeConnectionHelper.h"
|
||||
|
@ -278,12 +279,13 @@ nsIOService::GetInstance() {
|
|||
return gIOService;
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS5(nsIOService,
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS6(nsIOService,
|
||||
nsIIOService,
|
||||
nsIIOService2,
|
||||
nsINetUtil,
|
||||
nsIObserver,
|
||||
nsISupportsWeakReference)
|
||||
nsISupportsWeakReference,
|
||||
nsINetUtil_MOZILLA_1_9_1)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -983,3 +985,58 @@ nsIOService::ExtractCharsetFromContentType(const nsACString &aTypeHeader,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIOService::OfflineAppAllowed(nsIURI *aURI,
|
||||
nsIPrefBranch *aPrefBranch,
|
||||
PRBool *aAllowed)
|
||||
{
|
||||
*aAllowed = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(aURI);
|
||||
if (!innerURI)
|
||||
return NS_OK;
|
||||
|
||||
// only http and https applications can use offline APIs.
|
||||
PRBool match;
|
||||
nsresult rv = innerURI->SchemeIs("http", &match);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!match) {
|
||||
rv = innerURI->SchemeIs("https", &match);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!match) {
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPermissionManager> permissionManager =
|
||||
do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
|
||||
if (!permissionManager) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint32 perm;
|
||||
permissionManager->TestExactPermission(innerURI, "offline-app", &perm);
|
||||
|
||||
if (perm == nsIPermissionManager::UNKNOWN_ACTION) {
|
||||
nsCOMPtr<nsIPrefBranch> branch = aPrefBranch;
|
||||
if (!branch) {
|
||||
branch = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
}
|
||||
if (branch) {
|
||||
rv = branch->GetBoolPref("offline-apps.allow_by_default", aAllowed);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (perm == nsIPermissionManager::DENY_ACTION) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aAllowed = PR_TRUE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ class nsIPrefBranch2;
|
|||
class nsIOService : public nsIIOService2
|
||||
, public nsIObserver
|
||||
, public nsINetUtil
|
||||
, public nsINetUtil_MOZILLA_1_9_1
|
||||
, public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
|
@ -85,6 +86,7 @@ public:
|
|||
NS_DECL_NSIIOSERVICE2
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSINETUTIL
|
||||
NS_DECL_NSINETUTIL_MOZILLA_1_9_1
|
||||
|
||||
// Gets the singleton instance of the IO Service, creating it as needed
|
||||
// Returns nsnull on out of memory or failure to initialize.
|
||||
|
|
|
@ -113,6 +113,11 @@ SHARED_LIBRARY_LIBS += \
|
|||
LOCAL_INCLUDES += -I$(srcdir)/../cookie/src
|
||||
endif
|
||||
|
||||
ifdef MOZ_STORAGE
|
||||
REQUIRES += storage
|
||||
DEFINES += -DNECKO_OFFLINE_CACHE
|
||||
endif
|
||||
|
||||
EXTRA_DSO_LDOPTS = \
|
||||
$(LIBS_DIR) \
|
||||
$(EXTRA_DSO_LIBS) \
|
||||
|
|
|
@ -465,6 +465,18 @@
|
|||
{0x8f, 0xbc, 0xbe, 0xe8, 0xf9, 0x22, 0xea, 0x67} \
|
||||
}
|
||||
|
||||
// service implementing nsIApplicationCacheService.
|
||||
#define NS_APPLICATIONCACHESERVICE_CLASSNAME \
|
||||
"nsApplicationCacheService"
|
||||
#define NS_APPLICATIONCACHESERVICE_CONTRACTID \
|
||||
"@mozilla.org/network/application-cache-service;1"
|
||||
#define NS_APPLICATIONCACHESERVICE_CID \
|
||||
{ /* 02bf7a2a-39d8-4a23-a50c-2cbb085ab7a5 */ \
|
||||
0x02bf7a2a, \
|
||||
0x39d8, \
|
||||
0x4a23, \
|
||||
{0xa5, 0x0c, 0x2c, 0xbb, 0x08, 0x5a, 0xb7, 0xa5} \
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* netwerk/protocol/http/ classes
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include "nsMIMEInputStream.h"
|
||||
#include "nsSOCKSSocketProvider.h"
|
||||
#include "nsCacheService.h"
|
||||
#include "nsDiskCacheDeviceSQL.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsNetStrings.h"
|
||||
|
||||
|
@ -187,7 +188,11 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsSafeAboutProtocolHandler)
|
|||
#include "nsAboutCacheEntry.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAboutCacheEntry)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef NECKO_OFFLINE_CACHE
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsOfflineCacheDevice, nsOfflineCacheDevice::GetInstance)
|
||||
#endif
|
||||
|
||||
#ifdef NECKO_PROTOCOL_file
|
||||
// file
|
||||
#include "nsFileProtocolHandler.h"
|
||||
|
@ -1045,6 +1050,14 @@ static const nsModuleComponentInfo gNetModuleInfo[] = {
|
|||
nsCacheService::Create
|
||||
},
|
||||
|
||||
#ifdef NECKO_OFFLINE_CACHE
|
||||
{ NS_APPLICATIONCACHESERVICE_CLASSNAME,
|
||||
NS_APPLICATIONCACHESERVICE_CID,
|
||||
NS_APPLICATIONCACHESERVICE_CONTRACTID,
|
||||
nsOfflineCacheDeviceConstructor
|
||||
},
|
||||
#endif
|
||||
|
||||
#ifdef NECKO_COOKIES
|
||||
{ NS_COOKIEMANAGER_CLASSNAME,
|
||||
NS_COOKIEMANAGER_CID,
|
||||
|
|
|
@ -53,7 +53,6 @@ XPIDLSRCS = \
|
|||
nsICacheService.idl \
|
||||
nsICacheSession.idl \
|
||||
nsICacheVisitor.idl \
|
||||
nsIOfflineCacheSession.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -86,11 +86,7 @@ interface nsICacheService : nsISupports
|
|||
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().
|
||||
* This method is deprecated and will throw NS_ERROR_NOT_IMPLEMENTED.
|
||||
*/
|
||||
ACString createTemporaryClientID(in nsCacheStoragePolicy storagePolicy);
|
||||
};
|
||||
|
|
|
@ -1,233 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is nsIOfflineCacheSession.idl.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2007
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Dave Camp <dcamp@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
#include "nsICache.idl"
|
||||
|
||||
/**
|
||||
* 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(3a33e268-4175-4440-a933-89d461c86c5f)]
|
||||
interface nsIOfflineCacheSession : nsISupports
|
||||
{
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
void getOwnerDomains(out unsigned long count,
|
||||
[array, size_is(count)]out string domains);
|
||||
|
||||
/**
|
||||
* Gets the list of owner URIs associated with a domain.
|
||||
*
|
||||
* @param ownerAsciiDomain
|
||||
* The domain to query
|
||||
* !! IMPORTANT !! : This must be ascii encoded host - nsIURI.asciiHost
|
||||
* @param count
|
||||
* The number of uris returned
|
||||
* @param uris
|
||||
* The uris in this domain that own resources
|
||||
*/
|
||||
void getOwnerURIs(in ACString ownerAsciiDomain,
|
||||
out unsigned long count,
|
||||
[array, size_is(count)]out string uris);
|
||||
|
||||
/**
|
||||
* Sets the resources owned by a given domain/URI pair.
|
||||
*
|
||||
* Setting a list will remove any resources previously owned by this
|
||||
* domain/URI pair.
|
||||
*
|
||||
* A key can be added while there is no associated entry. When
|
||||
* an entry is created with this key, it will be owned by the
|
||||
* domain/URI pair.
|
||||
*
|
||||
* @param ownerAsciiDomain
|
||||
* The domain that owns the resources
|
||||
* !! IMPORTANT !! : This must be ascii encoded host - nsIURI.asciiHost
|
||||
* @param ownerAsciiKey
|
||||
* The specific key that owns the resources. You may use
|
||||
* ascii encoded URI spec of the owner - nsIURI.asciiSpec.
|
||||
* This can be empty if none 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 ownerAsciiDomain,
|
||||
in ACString ownerAsciiKey,
|
||||
in unsigned long count,
|
||||
[array, size_is(count)]in string keys);
|
||||
|
||||
/**
|
||||
* Gets the list of resources owned by a given domain/URI pair.
|
||||
*
|
||||
* @param ownerAsciiDomain
|
||||
* The domain that owns the resources
|
||||
* !! IMPORTANT !! : This must be ascii encoded host - nsIURI.asciiHost
|
||||
* @param ownerAsciiKey
|
||||
* The specific key that owns the resources. You may use
|
||||
* ascii encoded URI spec of the owner - nsIURI.asciiSpec.
|
||||
* This can be empty if none 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 ownerAsciiDomain,
|
||||
in ACString ownerAsciiKey,
|
||||
out unsigned long count,
|
||||
[array, size_is(count)]out string keys);
|
||||
|
||||
/**
|
||||
* Adds an owned key to a domain/URI pair.
|
||||
*
|
||||
* A key can be added while there is no associated entry. When
|
||||
* an entry is created with this key, it will be owned by the
|
||||
* domain/URI pair.
|
||||
*
|
||||
* @param ownerAsciiDomain
|
||||
* The domain that owns the resources
|
||||
* !! IMPORTANT !! : This must be ascii encoded host - nsIURI.asciiHost
|
||||
* @param ownerAsciiKey
|
||||
* The specific key that owns the resources. You may use
|
||||
* ascii encoded URI spec of the owner - nsIURI.asciiSpec.
|
||||
* This can be empty if none specifically owns the resources.
|
||||
* @param key
|
||||
* The key to add.
|
||||
*/
|
||||
void addOwnedKey(in ACString ownerAsciiDomain,
|
||||
in ACString ownerAsciiKey,
|
||||
in ACString key);
|
||||
|
||||
/**
|
||||
* Removes an owned key from a domain/URI pair.
|
||||
*
|
||||
* If the key does not exist, an NS_ERROR_NOT_AVAILABLE exception
|
||||
* will be thrown.
|
||||
*
|
||||
* @param ownerAsciiDomain
|
||||
* The domain that owns the resources
|
||||
* !! IMPORTANT !! : This must be ascii encoded host - nsIURI.asciiHost
|
||||
* @param ownerAsciiKey
|
||||
* The specific key that owns the resources. You may use
|
||||
* ascii encoded URI spec of the owner - nsIURI.asciiSpec.
|
||||
* This can be empty if none specifically owns the resources.
|
||||
* @param key The key to remove.
|
||||
*/
|
||||
void removeOwnedKey(in ACString ownerAsciiDomain,
|
||||
in ACString ownerAsciiKey,
|
||||
in ACString key);
|
||||
|
||||
/**
|
||||
* Checks whether a key is owned by a given domain/URI pair.
|
||||
*
|
||||
* @param ownerAsciiDomain
|
||||
* The domain that owns the resources
|
||||
* !! IMPORTANT !! : This must be ascii encoded host - nsIURI.asciiHost
|
||||
* @param ownerAsciiKey
|
||||
* The specific key that owns the resources. You may use
|
||||
* ascii encoded URI spec of the owner - nsIURI.asciiSpec.
|
||||
* This can be empty if none specifically owns the resources.
|
||||
* @param key The key to check
|
||||
*/
|
||||
boolean keyIsOwned(in ACString ownerAsciiDomain,
|
||||
in ACString ownerAsciiKey,
|
||||
in ACString key);
|
||||
|
||||
/**
|
||||
* Remove all keys owned by a domain, including keys owned by
|
||||
* a specific URI.
|
||||
*
|
||||
* @param ownerAsciiDomain
|
||||
* The domain for which keys should be removed
|
||||
* !! IMPORTANT !! : This must be ascii encoded host - nsIURI.asciiHost
|
||||
*/
|
||||
void clearKeysOwnedByDomain(in ACString ownerAsciiDomain);
|
||||
|
||||
/**
|
||||
* Get the number of bytes used in the cache by a domain.
|
||||
*
|
||||
* @param domain The domain to check.
|
||||
*/
|
||||
unsigned long getDomainUsage(in ACString ownerDomain);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
};
|
|
@ -663,8 +663,7 @@ nsCacheService::Shutdown()
|
|||
#endif // !NECKO_DISK_CACHE
|
||||
|
||||
#ifdef NECKO_OFFLINE_CACHE
|
||||
delete mOfflineDevice;
|
||||
mOfflineDevice = nsnull;
|
||||
NS_IF_RELEASE(mOfflineDevice);
|
||||
#endif // !NECKO_OFFLINE_CACHE
|
||||
|
||||
#if defined(NECKO_DISK_CACHE) && defined(PR_LOGGING)
|
||||
|
@ -829,245 +828,6 @@ nsCacheService::IsStorageEnabledForPolicy_Locked(nsCacheStoragePolicy storagePo
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
nsresult nsCacheService::GetOfflineOwnerDomains(nsCacheSession * session,
|
||||
PRUint32 * count,
|
||||
char *** domains)
|
||||
{
|
||||
#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->GetOwnerDomains(session->ClientID()->get(),
|
||||
count, domains);
|
||||
#else // !NECKO_OFFLINE_CACHE
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
nsresult nsCacheService::GetOfflineOwnerURIs(nsCacheSession * session,
|
||||
const nsACString & ownerDomain,
|
||||
PRUint32 * count,
|
||||
char *** uris)
|
||||
{
|
||||
#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->GetOwnerURIs(session->ClientID()->get(),
|
||||
ownerDomain, count, uris);
|
||||
#else // !NECKO_OFFLINE_CACHE
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCacheService::SetOfflineOwnedKeys(nsCacheSession * session,
|
||||
const nsACString & ownerDomain,
|
||||
const nsACString & ownerURI,
|
||||
PRUint32 count,
|
||||
const char ** keys)
|
||||
{
|
||||
#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->SetOwnedKeys(session->ClientID()->get(),
|
||||
ownerDomain,
|
||||
ownerURI,
|
||||
count,
|
||||
keys);
|
||||
#else // !NECKO_OFFLINE_CACHE
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult nsCacheService::GetOfflineOwnedKeys(nsCacheSession * session,
|
||||
const nsACString & ownerDomain,
|
||||
const nsACString & ownerURI,
|
||||
PRUint32 * count,
|
||||
char *** keys)
|
||||
{
|
||||
#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->GetOwnedKeys(session->ClientID()->get(),
|
||||
ownerDomain,
|
||||
ownerURI,
|
||||
count,
|
||||
keys);
|
||||
#else // !NECKO_OFFLINE_CACHE
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult nsCacheService::AddOfflineOwnedKey(nsCacheSession * session,
|
||||
const nsACString & ownerDomain,
|
||||
const nsACString & ownerURI,
|
||||
const nsACString & key)
|
||||
{
|
||||
#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->AddOwnedKey(session->ClientID()->get(),
|
||||
ownerDomain,
|
||||
ownerURI,
|
||||
key);
|
||||
#else // !NECKO_OFFLINE_CACHE
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult nsCacheService::RemoveOfflineOwnedKey(nsCacheSession * session,
|
||||
const nsACString & ownerDomain,
|
||||
const nsACString & ownerURI,
|
||||
const nsACString & key)
|
||||
{
|
||||
#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->RemoveOwnedKey(session->ClientID()->get(),
|
||||
ownerDomain,
|
||||
ownerURI,
|
||||
key);
|
||||
#else // !NECKO_OFFLINE_CACHE
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult nsCacheService::OfflineKeyIsOwned(nsCacheSession * session,
|
||||
const nsACString & ownerDomain,
|
||||
const nsACString & ownerURI,
|
||||
const nsACString & key,
|
||||
PRBool *isOwned)
|
||||
{
|
||||
#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->KeyIsOwned(session->ClientID()->get(),
|
||||
ownerDomain,
|
||||
ownerURI,
|
||||
key,
|
||||
isOwned);
|
||||
#else // !NECKO_OFFLINE_CACHE
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult nsCacheService::ClearOfflineKeysOwnedByDomain(nsCacheSession * session,
|
||||
const nsACString & domain)
|
||||
{
|
||||
#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->ClearKeysOwnedByDomain(session->ClientID()->get(),
|
||||
domain);
|
||||
#else // !NECKO_OFFLINE_CACHE
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult nsCacheService::GetOfflineDomainUsage(nsCacheSession * session,
|
||||
const nsACString & domain,
|
||||
PRUint32 * usage)
|
||||
{
|
||||
#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->GetDomainUsage(session->ClientID()->get(),
|
||||
domain,
|
||||
usage);
|
||||
#else // !NECKO_OFFLINE_CACHE
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult nsCacheService::EvictUnownedOfflineEntries(nsCacheSession * session)
|
||||
{
|
||||
#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->EvictUnownedEntries(session->ClientID()->get());
|
||||
#else // !NECKO_OFFLINE_CACHE
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#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);
|
||||
|
@ -1124,20 +884,7 @@ NS_IMETHODIMP nsCacheService::EvictEntries(nsCacheStoragePolicy 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
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1188,6 +935,8 @@ nsCacheService::CreateOfflineDevice()
|
|||
mOfflineDevice = new nsOfflineCacheDevice;
|
||||
if (!mOfflineDevice) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(mOfflineDevice);
|
||||
|
||||
// set the preferences
|
||||
mOfflineDevice->SetCacheParentDirectory(
|
||||
mObserver->OfflineCacheParentDirectory());
|
||||
|
@ -1199,8 +948,7 @@ nsCacheService::CreateOfflineDevice()
|
|||
CACHE_LOG_DEBUG((" - disabling offline cache for this session.\n"));
|
||||
|
||||
mEnableOfflineDevice = PR_FALSE;
|
||||
delete mOfflineDevice;
|
||||
mOfflineDevice = nsnull;
|
||||
NS_RELEASE(mOfflineDevice);
|
||||
}
|
||||
return rv;
|
||||
#else // !NECKO_DISK_CACHE
|
||||
|
|
|
@ -97,54 +97,6 @@ public:
|
|||
static nsresult IsStorageEnabledForPolicy(nsCacheStoragePolicy storagePolicy,
|
||||
PRBool * result);
|
||||
|
||||
|
||||
static nsresult GetOfflineOwnerDomains(nsCacheSession * session,
|
||||
PRUint32 * count,
|
||||
char *** domains);
|
||||
static nsresult GetOfflineOwnerURIs(nsCacheSession * session,
|
||||
const nsACString & ownerDomain,
|
||||
PRUint32 * count,
|
||||
char *** uris);
|
||||
|
||||
static nsresult SetOfflineOwnedKeys(nsCacheSession * session,
|
||||
const nsACString & ownerDomain,
|
||||
const nsACString & ownerUri,
|
||||
PRUint32 count,
|
||||
const char ** keys);
|
||||
|
||||
static nsresult GetOfflineOwnedKeys(nsCacheSession * session,
|
||||
const nsACString & ownerDomain,
|
||||
const nsACString & ownerURI,
|
||||
PRUint32 * count,
|
||||
char *** keys);
|
||||
|
||||
static nsresult AddOfflineOwnedKey(nsCacheSession * session,
|
||||
const nsACString & ownerDomain,
|
||||
const nsACString & ownerURI,
|
||||
const nsACString & key);
|
||||
|
||||
static nsresult RemoveOfflineOwnedKey(nsCacheSession * session,
|
||||
const nsACString & ownerDomain,
|
||||
const nsACString & ownerURI,
|
||||
const nsACString & key);
|
||||
|
||||
static nsresult OfflineKeyIsOwned(nsCacheSession * session,
|
||||
const nsACString & ownerDomain,
|
||||
const nsACString & ownerURI,
|
||||
const nsACString & key,
|
||||
PRBool * isOwned);
|
||||
|
||||
static nsresult ClearOfflineKeysOwnedByDomain(nsCacheSession * session,
|
||||
const nsACString & domain);
|
||||
static nsresult GetOfflineDomainUsage(nsCacheSession * session,
|
||||
const nsACString & domain,
|
||||
PRUint32 * usage);
|
||||
|
||||
static nsresult EvictUnownedOfflineEntries(nsCacheSession * session);
|
||||
|
||||
static nsresult MergeTemporaryClientID(nsCacheSession * session,
|
||||
const nsACString & fromClientID);
|
||||
|
||||
/**
|
||||
* Methods called by nsCacheEntryDescriptor
|
||||
*/
|
||||
|
@ -208,6 +160,7 @@ public:
|
|||
void Shutdown();
|
||||
private:
|
||||
friend class nsCacheServiceAutoLock;
|
||||
friend class nsOfflineCacheDevice;
|
||||
|
||||
/**
|
||||
* Internal Methods
|
||||
|
|
|
@ -44,15 +44,7 @@
|
|||
#include "nsCacheService.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
NS_IMPL_ADDREF(nsCacheSession)
|
||||
NS_IMPL_RELEASE(nsCacheSession)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsCacheSession)
|
||||
NS_INTERFACE_MAP_ENTRY(nsICacheSession)
|
||||
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(
|
||||
nsIOfflineCacheSession, (StoragePolicy() == nsICache::STORE_OFFLINE))
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsICacheSession)
|
||||
NS_INTERFACE_MAP_END
|
||||
NS_IMPL_ISUPPORTS1(nsCacheSession, nsICacheSession)
|
||||
|
||||
nsCacheSession::nsCacheSession(const char * clientID,
|
||||
nsCacheStoragePolicy storagePolicy,
|
||||
|
@ -135,75 +127,3 @@ NS_IMETHODIMP nsCacheSession::IsStorageEnabled(PRBool *result)
|
|||
|
||||
return nsCacheService::IsStorageEnabledForPolicy(StoragePolicy(), result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCacheSession::GetOwnerDomains(PRUint32 * count,
|
||||
char *** domains)
|
||||
{
|
||||
return nsCacheService::GetOfflineOwnerDomains(this, count, domains);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCacheSession::GetOwnerURIs(const nsACString & domain,
|
||||
PRUint32 * count,
|
||||
char *** uris)
|
||||
{
|
||||
return nsCacheService::GetOfflineOwnerURIs(this, domain, count, uris);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCacheSession::SetOwnedKeys(const nsACString & domain,
|
||||
const nsACString & uri,
|
||||
PRUint32 count,
|
||||
const char ** keys)
|
||||
{
|
||||
return nsCacheService::SetOfflineOwnedKeys(this, domain, uri, count, keys);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCacheSession::GetOwnedKeys(const nsACString & domain,
|
||||
const nsACString & uri,
|
||||
PRUint32 * count,
|
||||
char *** keys)
|
||||
{
|
||||
return nsCacheService::GetOfflineOwnedKeys(this, domain, uri, count, keys);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCacheSession::AddOwnedKey(const nsACString & domain,
|
||||
const nsACString & uri,
|
||||
const nsACString & key)
|
||||
{
|
||||
return nsCacheService::AddOfflineOwnedKey(this, domain, uri, key);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCacheSession::RemoveOwnedKey(const nsACString & domain,
|
||||
const nsACString & uri,
|
||||
const nsACString & key)
|
||||
{
|
||||
return nsCacheService::RemoveOfflineOwnedKey(this, domain, uri, key);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCacheSession::KeyIsOwned(const nsACString & domain,
|
||||
const nsACString & uri,
|
||||
const nsACString & key,
|
||||
PRBool * isOwned)
|
||||
{
|
||||
return nsCacheService::OfflineKeyIsOwned(this, domain, uri, key, isOwned);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCacheSession::ClearKeysOwnedByDomain(const nsACString & domain)
|
||||
{
|
||||
return nsCacheService::ClearOfflineKeysOwnedByDomain(this, domain);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCacheSession::GetDomainUsage(const nsACString & domain,
|
||||
PRUint32 *usage)
|
||||
{
|
||||
return nsCacheService::GetOfflineDomainUsage(this, domain, usage);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCacheSession::EvictUnownedEntries()
|
||||
{
|
||||
return nsCacheService::EvictUnownedOfflineEntries(this);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsCacheSession::MergeTemporaryClientID(const nsACString& fromClientID)
|
||||
{
|
||||
return nsCacheService::MergeTemporaryClientID(this, fromClientID);
|
||||
}
|
||||
|
|
|
@ -46,16 +46,13 @@
|
|||
#include "nspr.h"
|
||||
#include "nsError.h"
|
||||
#include "nsICacheSession.h"
|
||||
#include "nsIOfflineCacheSession.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsCacheSession : public nsICacheSession
|
||||
, public nsIOfflineCacheSession
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICACHESESSION
|
||||
NS_DECL_NSIOFFLINECACHESESSION
|
||||
|
||||
nsCacheSession(const char * clientID, nsCacheStoragePolicy storagePolicy, PRBool streamBased);
|
||||
virtual ~nsCacheSession();
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsString.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsCRT.h"
|
||||
|
@ -57,6 +58,7 @@
|
|||
#include "nsISeekableStream.h"
|
||||
|
||||
static const char OFFLINE_CACHE_DEVICE_ID[] = { "offline" };
|
||||
static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
|
||||
|
||||
#define LOG(args) CACHE_LOG_DEBUG(args)
|
||||
|
||||
|
@ -540,10 +542,144 @@ nsOfflineCacheEntryInfo::GetDataSize(PRUint32 *aDataSize)
|
|||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* nsApplicationCache
|
||||
*/
|
||||
|
||||
class nsApplicationCache : public nsIApplicationCache
|
||||
, public nsSupportsWeakReference
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIAPPLICATIONCACHE
|
||||
|
||||
nsApplicationCache(nsOfflineCacheDevice *device,
|
||||
const nsACString &group,
|
||||
const nsACString &clientID);
|
||||
|
||||
virtual ~nsApplicationCache();
|
||||
|
||||
void MarkInvalid() { mValid = PR_FALSE; }
|
||||
|
||||
private:
|
||||
nsRefPtr<nsOfflineCacheDevice> mDevice;
|
||||
nsCString mGroup;
|
||||
nsCString mClientID;
|
||||
PRBool mValid;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsApplicationCache,
|
||||
nsIApplicationCache,
|
||||
nsISupportsWeakReference)
|
||||
|
||||
nsApplicationCache::nsApplicationCache(nsOfflineCacheDevice *device,
|
||||
const nsACString &group,
|
||||
const nsACString &clientID)
|
||||
: mDevice(device)
|
||||
, mGroup(group)
|
||||
, mClientID(clientID)
|
||||
, mValid(PR_TRUE)
|
||||
{
|
||||
}
|
||||
|
||||
nsApplicationCache::~nsApplicationCache()
|
||||
{
|
||||
mDevice->mCaches.Remove(mClientID);
|
||||
|
||||
// If this isn't an active cache anymore, it can be destroyed.
|
||||
if (mValid && !mDevice->IsActiveCache(mGroup, mClientID))
|
||||
Discard();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationCache::GetGroupID(nsACString &out)
|
||||
{
|
||||
out = mGroup;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationCache::GetClientID(nsACString &out)
|
||||
{
|
||||
out = mClientID;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationCache::GetActive(PRBool *out)
|
||||
{
|
||||
*out = mDevice->IsActiveCache(mGroup, mClientID);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationCache::Activate()
|
||||
{
|
||||
NS_ENSURE_TRUE(mValid, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
mDevice->ActivateCache(mGroup, mClientID);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationCache::Discard()
|
||||
{
|
||||
NS_ENSURE_TRUE(mValid, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
mValid = PR_FALSE;
|
||||
|
||||
if (mDevice->IsActiveCache(mGroup, mClientID))
|
||||
{
|
||||
mDevice->DeactivateGroup(mGroup);
|
||||
}
|
||||
|
||||
return mDevice->EvictEntries(mClientID.get());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationCache::MarkEntry(const nsACString &key,
|
||||
PRUint32 typeBits)
|
||||
{
|
||||
NS_ENSURE_TRUE(mValid, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
return mDevice->MarkEntry(mClientID, key, typeBits);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationCache::UnmarkEntry(const nsACString &key,
|
||||
PRUint32 typeBits)
|
||||
{
|
||||
NS_ENSURE_TRUE(mValid, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
return mDevice->UnmarkEntry(mClientID, key, typeBits);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationCache::GetTypes(const nsACString &key,
|
||||
PRUint32 *typeBits)
|
||||
{
|
||||
NS_ENSURE_TRUE(mValid, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
return mDevice->GetTypes(mClientID, key, typeBits);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationCache::GatherEntries(PRUint32 typeBits,
|
||||
PRUint32 * count,
|
||||
char *** keys)
|
||||
{
|
||||
NS_ENSURE_TRUE(mValid, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
return mDevice->GatherEntries(mClientID, typeBits, count, keys);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* nsOfflineCacheDevice
|
||||
*/
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsOfflineCacheDevice, nsIApplicationCacheService)
|
||||
|
||||
nsOfflineCacheDevice::nsOfflineCacheDevice()
|
||||
: mDB(nsnull)
|
||||
, mCacheCapacity(0)
|
||||
|
@ -697,6 +833,23 @@ nsOfflineCacheDevice::DeleteData(nsCacheEntry *entry)
|
|||
* nsCacheDevice implementation
|
||||
*/
|
||||
|
||||
/* static */
|
||||
nsOfflineCacheDevice *
|
||||
nsOfflineCacheDevice::GetInstance()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsICacheService> serv = do_GetService(kCacheServiceCID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
nsICacheService *iservice = static_cast<nsICacheService*>(serv.get());
|
||||
nsCacheService *cacheService = static_cast<nsCacheService*>(iservice);
|
||||
rv = cacheService->CreateOfflineDevice();
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
NS_IF_ADDREF(cacheService->mOfflineDevice);
|
||||
return cacheService->mOfflineDevice;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::Init()
|
||||
{
|
||||
|
@ -735,8 +888,8 @@ nsOfflineCacheDevice::Init()
|
|||
// "Generation" is the data file generation number.
|
||||
// "Flags" is a bit-field indicating the state of the entry.
|
||||
//
|
||||
mDB->ExecuteSimpleSQL(
|
||||
NS_LITERAL_CSTRING("CREATE TABLE moz_cache (\n"
|
||||
rv = mDB->ExecuteSimpleSQL(
|
||||
NS_LITERAL_CSTRING("CREATE TABLE IF NOT EXISTS moz_cache (\n"
|
||||
" ClientID TEXT,\n"
|
||||
" Key TEXT,\n"
|
||||
" MetaData BLOB,\n"
|
||||
|
@ -746,24 +899,38 @@ nsOfflineCacheDevice::Init()
|
|||
" FetchCount INTEGER,\n"
|
||||
" LastFetched INTEGER,\n"
|
||||
" LastModified INTEGER,\n"
|
||||
" ExpirationTime INTEGER\n"
|
||||
" ExpirationTime INTEGER,\n"
|
||||
" ItemType INTEGER DEFAULT 0\n"
|
||||
");\n"));
|
||||
// maybe the table already exists, so don't bother checking for errors.
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// build the ownership table
|
||||
// Databases from 1.9.0 don't have the ItemType column. Add the column
|
||||
// here, but don't worry about failures (the column probably already exists)
|
||||
mDB->ExecuteSimpleSQL(
|
||||
NS_LITERAL_CSTRING("CREATE TABLE moz_cache_owners (\n"
|
||||
" ClientID TEXT,\n"
|
||||
" Domain TEXT,\n"
|
||||
" URI TEXT,\n"
|
||||
" Key TEXT\n"
|
||||
NS_LITERAL_CSTRING("ALTER TABLE moz_cache ADD ItemType INTEGER DEFAULT 0"));
|
||||
|
||||
// Create the table for storing cache groups. All actions on
|
||||
// moz_cache_groups use the GroupID, so use it as the primary key.
|
||||
rv = mDB->ExecuteSimpleSQL(
|
||||
NS_LITERAL_CSTRING("CREATE TABLE IF NOT EXISTS moz_cache_groups (\n"
|
||||
" GroupID TEXT PRIMARY KEY,\n"
|
||||
" ActiveClientID TEXT\n"
|
||||
");\n"));
|
||||
// maybe the table already exists, so don't bother checking for errors.
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mDB->ExecuteSimpleSQL(
|
||||
NS_LITERAL_CSTRING("CREATE UNIQUE INDEX moz_cache_index"
|
||||
" ON moz_cache (ClientID, Key);"));
|
||||
// maybe the index already exists, so don't bother checking for errors.
|
||||
// Databases from 1.9.0 have a moz_cache_index that should be dropped
|
||||
rv = mDB->ExecuteSimpleSQL(
|
||||
NS_LITERAL_CSTRING("DROP INDEX IF EXISTS moz_cache_index"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Key/ClientID pairs should be unique in the database. All queries
|
||||
// against moz_cache use the Key (which is also the most unique), so
|
||||
// use it as the primary key for this index.
|
||||
rv = mDB->ExecuteSimpleSQL(
|
||||
NS_LITERAL_CSTRING("CREATE UNIQUE INDEX IF NOT EXISTS "
|
||||
" moz_cache_key_clientid_index"
|
||||
" ON moz_cache (Key, ClientID);"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mEvictionFunction = new nsOfflineCacheEvictionFunction(this);
|
||||
if (!mEvictionFunction) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
@ -779,7 +946,8 @@ nsOfflineCacheDevice::Init()
|
|||
statement (aStatement), sql (aSql) {}
|
||||
} prepared[] = {
|
||||
StatementSql ( mStatement_CacheSize, "SELECT Sum(DataSize) from moz_cache;" ),
|
||||
StatementSql ( mStatement_DomainSize, "SELECT Sum(moz_cache.DataSize) FROM moz_cache INNER 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=?;" ),
|
||||
// XXX bug 442810: Restore the ability to monitor individual cache usage
|
||||
StatementSql ( mStatement_DomainSize, "SELECT 0;"),
|
||||
StatementSql ( mStatement_EntryCount, "SELECT count(*) from moz_cache;" ),
|
||||
StatementSql ( mStatement_UpdateEntry, "UPDATE moz_cache SET MetaData = ?, Flags = ?, DataSize = ?, FetchCount = ?, LastFetched = ?, LastModified = ?, ExpirationTime = ? WHERE ClientID = ? AND Key = ?;" ),
|
||||
StatementSql ( mStatement_UpdateEntrySize, "UPDATE moz_cache SET DataSize = ? WHERE ClientID = ? AND Key = ?;" ),
|
||||
|
@ -787,25 +955,25 @@ nsOfflineCacheDevice::Init()
|
|||
StatementSql ( mStatement_DeleteEntry, "DELETE FROM moz_cache WHERE ClientID = ? AND Key = ?;" ),
|
||||
StatementSql ( mStatement_FindEntry, "SELECT MetaData, Generation, Flags, DataSize, FetchCount, LastFetched, LastModified, ExpirationTime FROM moz_cache WHERE ClientID = ? AND Key = ?;" ),
|
||||
StatementSql ( mStatement_BindEntry, "INSERT INTO moz_cache (ClientID, Key, MetaData, Generation, Flags, DataSize, FetchCount, LastFetched, LastModified, ExpirationTime) VALUES(?,?,?,?,?,?,?,?,?,?);" ),
|
||||
StatementSql ( mStatement_ClearOwnership, "DELETE FROM moz_cache_owners WHERE ClientId = ? AND Domain = ? AND URI = ?;" ),
|
||||
StatementSql ( mStatement_RemoveOwnership, "DELETE FROM moz_cache_owners WHERE ClientID = ? AND Domain = ? AND URI = ? AND Key = ?;" ),
|
||||
StatementSql ( mStatement_ClearDomain, "DELETE FROM moz_cache_owners WHERE ClientID = ? AND Domain = ?;" ),
|
||||
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_DeleteConflicts, "DELETE FROM moz_cache WHERE rowid IN (SELECT old.rowid FROM moz_cache AS old, moz_cache AS new WHERE old.Key = new.Key AND old.ClientID = ? AND new.ClientID = ?)"),
|
||||
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 = ?;")
|
||||
|
||||
StatementSql ( mStatement_MarkEntry, "UPDATE moz_cache SET ItemType = (ItemType | ?) WHERE ClientID = ? AND Key = ?;" ),
|
||||
StatementSql ( mStatement_UnmarkEntry, "UPDATE moz_cache SET ItemType = (ItemType & ~?) WHERE ClientID = ? AND Key = ?;" ),
|
||||
StatementSql ( mStatement_GetTypes, "SELECT ItemType FROM moz_cache WHERE ClientID = ? AND Key = ?;"),
|
||||
StatementSql ( mStatement_CleanupUnmarked, "DELETE FROM moz_cache WHERE ClientID = ? AND Key = ? AND ItemType = 0;" ),
|
||||
StatementSql ( mStatement_GatherEntries, "SELECT Key FROM moz_cache WHERE ClientID = ? AND (ItemType & ?) > 0;" ),
|
||||
|
||||
StatementSql ( mStatement_ActivateClient, "INSERT OR REPLACE INTO moz_cache_groups (GroupID, ActiveClientID) VALUES (?, ?);" ),
|
||||
StatementSql ( mStatement_DeactivateGroup, "DELETE FROM moz_cache_groups WHERE GroupID = ?;" ),
|
||||
StatementSql ( mStatement_FindClient, "SELECT ClientID FROM moz_cache WHERE Key = ? ORDER BY LastFetched DESC, LastModified DESC;")
|
||||
};
|
||||
for (PRUint32 i=0; i<NS_ARRAY_LENGTH(prepared); ++i)
|
||||
for (PRUint32 i = 0; NS_SUCCEEDED(rv) && i < NS_ARRAY_LENGTH(prepared); ++i)
|
||||
{
|
||||
rv |= mDB->CreateStatement(nsDependentCString(prepared[i].sql),
|
||||
getter_AddRefs(prepared[i].statement));
|
||||
LOG(("Creating statement: %s\n", prepared[i].sql));
|
||||
|
||||
rv = mDB->CreateStatement(nsDependentCString(prepared[i].sql),
|
||||
getter_AddRefs(prepared[i].statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Clear up any dangling active flags
|
||||
rv = mDB->ExecuteSimpleSQL(
|
||||
|
@ -814,24 +982,83 @@ nsOfflineCacheDevice::Init()
|
|||
" WHERE (Flags & 1);"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Clear up dangling temporary sessions
|
||||
EvictionObserver evictionObserver(mDB, mEvictionFunction);
|
||||
|
||||
rv = mDB->ExecuteSimpleSQL(
|
||||
NS_LITERAL_CSTRING("DELETE FROM moz_cache"
|
||||
" WHERE (ClientID GLOB \"TempClient*\")"));
|
||||
rv = InitActiveCaches();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
evictionObserver.Apply();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::InitActiveCaches()
|
||||
{
|
||||
NS_ENSURE_TRUE(mCaches.Init(), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(mActiveCachesByGroup.Init(), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = mActiveCaches.Init(5);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
rv =
|
||||
mDB->CreateStatement(NS_LITERAL_CSTRING("SELECT GroupID, ActiveClientID"
|
||||
" FROM moz_cache_groups"),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool hasRows;
|
||||
rv = statement->ExecuteStep(&hasRows);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
while (hasRows)
|
||||
{
|
||||
nsCAutoString group;
|
||||
statement->GetUTF8String(0, group);
|
||||
nsCString clientID;
|
||||
statement->GetUTF8String(1, clientID);
|
||||
|
||||
mActiveCaches.Put(clientID);
|
||||
mActiveCachesByGroup.Put(group, new nsCString(clientID));
|
||||
|
||||
rv = statement->ExecuteStep(&hasRows);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
PLDHashOperator
|
||||
nsOfflineCacheDevice::ShutdownApplicationCache(const nsACString &key,
|
||||
nsIWeakReference *weakRef,
|
||||
void *ctx)
|
||||
{
|
||||
nsCOMPtr<nsIApplicationCache> obj = do_QueryReferent(weakRef);
|
||||
if (obj)
|
||||
{
|
||||
nsApplicationCache *appCache = static_cast<nsApplicationCache*>(obj.get());
|
||||
appCache->MarkInvalid();
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::Shutdown()
|
||||
{
|
||||
NS_ENSURE_TRUE(mDB, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
if (mCaches.IsInitialized())
|
||||
mCaches.EnumerateRead(ShutdownApplicationCache, this);
|
||||
|
||||
EvictionObserver evictionObserver(mDB, mEvictionFunction);
|
||||
|
||||
// Delete all rows whose clientID is not an active clientID.
|
||||
nsresult rv = mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_cache WHERE rowid IN (SELECT moz_cache.rowid FROM moz_cache LEFT OUTER JOIN moz_cache_groups ON (moz_cache.ClientID = moz_cache_groups.ActiveClientID) WHERE moz_cache_groups.GroupID ISNULL)"));
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
NS_WARNING("Failed to clean up unused application caches.");
|
||||
else
|
||||
evictionObserver.Apply();
|
||||
|
||||
mDB = 0;
|
||||
mEvictionFunction = 0;
|
||||
|
||||
|
@ -1026,7 +1253,6 @@ nsOfflineCacheDevice::BindEntry(nsCacheEntry *entry)
|
|||
PRBool hasRows;
|
||||
rv = statement->ExecuteStep(&hasRows);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ASSERTION(!hasRows, "INSERT should not result in output");
|
||||
|
||||
entry->SetData(binding);
|
||||
|
@ -1250,23 +1476,25 @@ nsOfflineCacheDevice::EvictEntries(const char *clientID)
|
|||
// so we can delete the corresponding data file.
|
||||
EvictionObserver evictionObserver(mDB, mEvictionFunction);
|
||||
|
||||
const char *deleteCmd;
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
nsresult rv;
|
||||
if (clientID)
|
||||
{
|
||||
deleteCmd =
|
||||
PR_smprintf("DELETE FROM moz_cache WHERE ClientID=%q AND Flags=0;",
|
||||
clientID);
|
||||
if (!deleteCmd)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
rv = mDB->CreateStatement(NS_LITERAL_CSTRING("DELETE FROM moz_cache WHERE ClientID=? AND Flags = 0;"),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->BindUTF8StringParameter(0, nsDependentCString(clientID));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else
|
||||
{
|
||||
deleteCmd = "DELETE FROM moz_cache WHERE Flags = 0;";
|
||||
rv = mDB->CreateStatement(NS_LITERAL_CSTRING("DELETE FROM moz_cache WHERE Flags = 0;"),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsresult rv = mDB->ExecuteSimpleSQL(nsDependentCString(deleteCmd));
|
||||
if (clientID)
|
||||
PR_smprintf_free((char *) deleteCmd);
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
evictionObserver.Apply();
|
||||
|
@ -1274,6 +1502,110 @@ nsOfflineCacheDevice::EvictEntries(const char *clientID)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::MarkEntry(const nsCString &clientID,
|
||||
const nsACString &key,
|
||||
PRUint32 typeBits)
|
||||
{
|
||||
LOG(("nsOfflineCacheDevice::MarkEntry [cid=%s, key=%s, typeBits=%d]\n",
|
||||
clientID.get(), PromiseFlatCString(key).get(), typeBits));
|
||||
|
||||
AutoResetStatement statement(mStatement_MarkEntry);
|
||||
nsresult rv = statement->BindInt32Parameter(0, typeBits);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindUTF8StringParameter(1, clientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindUTF8StringParameter(2, key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::UnmarkEntry(const nsCString &clientID,
|
||||
const nsACString &key,
|
||||
PRUint32 typeBits)
|
||||
{
|
||||
LOG(("nsOfflineCacheDevice::UnmarkEntry [cid=%s, key=%s, typeBits=%d]\n",
|
||||
clientID.get(), PromiseFlatCString(key).get(), typeBits));
|
||||
|
||||
AutoResetStatement statement(mStatement_UnmarkEntry);
|
||||
nsresult rv = statement->BindInt32Parameter(0, typeBits);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindUTF8StringParameter(1, clientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindUTF8StringParameter(2, key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Remove the entry if it is now empty.
|
||||
|
||||
EvictionObserver evictionObserver(mDB, mEvictionFunction);
|
||||
|
||||
AutoResetStatement cleanupStatement(mStatement_CleanupUnmarked);
|
||||
rv = cleanupStatement->BindUTF8StringParameter(0, clientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = cleanupStatement->BindUTF8StringParameter(1, key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = cleanupStatement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
evictionObserver.Apply();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::GetTypes(const nsCString &clientID,
|
||||
const nsACString &key,
|
||||
PRUint32 *typeBits)
|
||||
{
|
||||
LOG(("nsOfflineCacheDevice::GetTypes [cid=%s, key=%s]\n",
|
||||
clientID.get(), PromiseFlatCString(key).get()));
|
||||
|
||||
AutoResetStatement statement(mStatement_GetTypes);
|
||||
nsresult rv = statement->BindUTF8StringParameter(0, clientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindUTF8StringParameter(1, key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool hasRows;
|
||||
rv = statement->ExecuteStep(&hasRows);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!hasRows)
|
||||
return NS_ERROR_CACHE_KEY_NOT_FOUND;
|
||||
|
||||
*typeBits = statement->AsInt32(0);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::GatherEntries(const nsCString &clientID,
|
||||
PRUint32 typeBits,
|
||||
PRUint32 *count,
|
||||
char ***keys)
|
||||
{
|
||||
LOG(("nsOfflineCacheDevice::GatherEntries [cid=%s, typeBits=%X]\n",
|
||||
clientID.get(), typeBits));
|
||||
|
||||
AutoResetStatement statement(mStatement_GatherEntries);
|
||||
nsresult rv = statement->BindUTF8StringParameter(0, clientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->BindInt32Parameter(1, typeBits);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return RunSimpleQuery(mStatement_GatherEntries, 0, count, keys);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::RunSimpleQuery(mozIStorageStatement * statement,
|
||||
PRUint32 resultIndex,
|
||||
|
@ -1312,312 +1644,190 @@ nsOfflineCacheDevice::RunSimpleQuery(mozIStorageStatement * statement,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::GetOwnerDomains(const char * clientID,
|
||||
PRUint32 * count,
|
||||
char *** domains)
|
||||
NS_IMETHODIMP
|
||||
nsOfflineCacheDevice::CreateApplicationCache(const nsACString &group,
|
||||
nsIApplicationCache **out)
|
||||
{
|
||||
LOG(("nsOfflineCacheDevice::GetOwnerDomains [cid=%s]\n", clientID));
|
||||
*out = nsnull;
|
||||
|
||||
AutoResetStatement statement(mStatement_ListOwnerDomains);
|
||||
nsresult rv = statement->BindUTF8StringParameter(
|
||||
0, nsDependentCString(clientID));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return RunSimpleQuery(mStatement_ListOwnerDomains, 0, count, domains);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::GetOwnerURIs(const char * clientID,
|
||||
const nsACString & ownerDomain,
|
||||
PRUint32 * count,
|
||||
char *** domains)
|
||||
{
|
||||
LOG(("nsOfflineCacheDevice::GetOwnerURIs [cid=%s]\n", clientID));
|
||||
|
||||
AutoResetStatement statement(mStatement_ListOwnerURIs);
|
||||
nsresult rv = statement->BindUTF8StringParameter(
|
||||
0, nsDependentCString(clientID));
|
||||
rv = statement->BindUTF8StringParameter(
|
||||
1, ownerDomain);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return RunSimpleQuery(mStatement_ListOwnerURIs, 0, count, domains);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::SetOwnedKeys(const char * clientID,
|
||||
const nsACString & ownerDomain,
|
||||
const nsACString & ownerURI,
|
||||
PRUint32 count,
|
||||
const char ** keys)
|
||||
{
|
||||
LOG(("nsOfflineCacheDevice::SetOwnedKeys [cid=%s]\n", clientID));
|
||||
mozStorageTransaction transaction(mDB, PR_FALSE);
|
||||
|
||||
nsDependentCString clientIDStr(clientID);
|
||||
|
||||
AutoResetStatement clearStatement(mStatement_ClearOwnership);
|
||||
nsresult rv = clearStatement->BindUTF8StringParameter(
|
||||
0, clientIDStr);
|
||||
rv |= clearStatement->BindUTF8StringParameter(1, ownerDomain);
|
||||
rv |= clearStatement->BindUTF8StringParameter(2, ownerURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = clearStatement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRUint32 i = 0; i < count; i++)
|
||||
{
|
||||
AutoResetStatement insertStatement(mStatement_AddOwnership);
|
||||
rv = insertStatement->BindUTF8StringParameter(0, clientIDStr);
|
||||
rv |= insertStatement->BindUTF8StringParameter(1, ownerDomain);
|
||||
rv |= insertStatement->BindUTF8StringParameter(2, ownerURI);
|
||||
rv |= insertStatement->BindUTF8StringParameter(3, nsDependentCString(keys[i]));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = insertStatement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCString clientID;
|
||||
// Some characters are special in the clientID. Escape the groupID
|
||||
// before putting it in to the client key.
|
||||
if (!NS_Escape(nsCString(group), clientID, url_Path)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
return transaction.Commit();
|
||||
PRTime now = PR_Now();
|
||||
|
||||
// Include the timestamp to guarantee uniqueness across runs, and
|
||||
// the gNextTemporaryClientID for uniqueness within a second.
|
||||
clientID.Append(nsPrintfCString(64, "|%016lld|%d",
|
||||
now / PR_USEC_PER_SEC,
|
||||
gNextTemporaryClientID++));
|
||||
|
||||
nsCOMPtr<nsIApplicationCache> cache = new nsApplicationCache(this,
|
||||
group,
|
||||
clientID);
|
||||
if (!cache)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
nsCOMPtr<nsIWeakReference> weak = do_GetWeakReference(cache);
|
||||
if (!weak)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mCaches.Put(clientID, weak);
|
||||
|
||||
cache.swap(*out);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::GetOwnedKeys(const char * clientID,
|
||||
const nsACString & ownerDomain,
|
||||
const nsACString & ownerURI,
|
||||
PRUint32 * count,
|
||||
char *** keys)
|
||||
NS_IMETHODIMP
|
||||
nsOfflineCacheDevice::GetApplicationCache(const nsACString &clientID,
|
||||
nsIApplicationCache **out)
|
||||
{
|
||||
LOG(("nsOfflineCacheDevice::GetOwnedKeys [cid=%s]\n", clientID));
|
||||
*out = nsnull;
|
||||
|
||||
AutoResetStatement statement(mStatement_ListOwned);
|
||||
nsCOMPtr<nsIApplicationCache> cache;
|
||||
|
||||
nsWeakPtr weak;
|
||||
if (mCaches.Get(clientID, getter_AddRefs(weak)))
|
||||
cache = do_QueryReferent(weak);
|
||||
|
||||
if (!cache)
|
||||
{
|
||||
nsCString group;
|
||||
nsresult rv = GetGroupForCache(clientID, group);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (group.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
cache = new nsApplicationCache(this, group, clientID);
|
||||
weak = do_GetWeakReference(cache);
|
||||
if (!weak)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mCaches.Put(clientID, weak);
|
||||
}
|
||||
|
||||
cache.swap(*out);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOfflineCacheDevice::GetActiveCache(const nsACString &group,
|
||||
nsIApplicationCache **out)
|
||||
{
|
||||
*out = nsnull;
|
||||
|
||||
nsCString *clientID;
|
||||
if (mActiveCachesByGroup.Get(group, &clientID))
|
||||
return GetApplicationCache(*clientID, out);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOfflineCacheDevice::ChooseApplicationCache(const nsACString &key,
|
||||
nsIApplicationCache **out)
|
||||
{
|
||||
*out = nsnull;
|
||||
|
||||
AutoResetStatement statement(mStatement_FindClient);
|
||||
nsresult rv = statement->BindUTF8StringParameter(
|
||||
0, nsDependentCString(clientID));
|
||||
rv |= statement->BindUTF8StringParameter(1, ownerDomain);
|
||||
rv |= statement->BindUTF8StringParameter(2, ownerURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return RunSimpleQuery(mStatement_ListOwned, 0, count, keys);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::AddOwnedKey(const char * clientID,
|
||||
const nsACString & ownerDomain,
|
||||
const nsACString & ownerURI,
|
||||
const nsACString & key)
|
||||
{
|
||||
LOG(("nsOfflineCacheDevice::AddOwnedKey [cid=%s]\n", clientID));
|
||||
|
||||
PRBool isOwned;
|
||||
nsresult rv = KeyIsOwned(clientID, ownerDomain, ownerURI, key, &isOwned);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (isOwned) return NS_OK;
|
||||
|
||||
AutoResetStatement statement(mStatement_AddOwnership);
|
||||
rv = statement->BindUTF8StringParameter(0, nsDependentCString(clientID));
|
||||
rv |= statement->BindUTF8StringParameter(1, ownerDomain);
|
||||
rv |= statement->BindUTF8StringParameter(2, ownerURI);
|
||||
rv |= statement->BindUTF8StringParameter(3, key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return statement->Execute();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::RemoveOwnedKey(const char * clientID,
|
||||
const nsACString & ownerDomain,
|
||||
const nsACString & ownerURI,
|
||||
const nsACString & key)
|
||||
{
|
||||
LOG(("nsOfflineCacheDevice::RemoveOwnedKey [cid=%s]\n", clientID));
|
||||
|
||||
PRBool isOwned;
|
||||
nsresult rv = KeyIsOwned(clientID, ownerDomain, ownerURI, key, &isOwned);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!isOwned) return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
AutoResetStatement statement(mStatement_RemoveOwnership);
|
||||
rv = statement->BindUTF8StringParameter(0, nsDependentCString(clientID));
|
||||
rv |= statement->BindUTF8StringParameter(1, ownerDomain);
|
||||
rv |= statement->BindUTF8StringParameter(2, ownerURI);
|
||||
rv |= statement->BindUTF8StringParameter(3, key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return statement->Execute();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::KeyIsOwned(const char * clientID,
|
||||
const nsACString & ownerDomain,
|
||||
const nsACString & ownerURI,
|
||||
const nsACString & key,
|
||||
PRBool * isOwned)
|
||||
{
|
||||
AutoResetStatement statement(mStatement_CheckOwnership);
|
||||
nsresult rv = statement->BindUTF8StringParameter(
|
||||
0, nsDependentCString(clientID));
|
||||
rv |= statement->BindUTF8StringParameter(1, ownerDomain);
|
||||
rv |= statement->BindUTF8StringParameter(2, ownerURI);
|
||||
rv |= statement->BindUTF8StringParameter(3, key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return statement->ExecuteStep(isOwned);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::ClearKeysOwnedByDomain(const char *clientID,
|
||||
const nsACString &domain)
|
||||
{
|
||||
LOG(("nsOfflineCacheDevice::ClearKeysOwnedByDomain [cid=%s]\n", clientID));
|
||||
|
||||
AutoResetStatement statement(mStatement_ClearDomain);
|
||||
nsresult rv = statement->BindUTF8StringParameter(
|
||||
0, nsDependentCString(clientID));
|
||||
rv |= statement->BindUTF8StringParameter(1, domain);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return statement->Execute();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::GetDomainUsage(const char *clientID,
|
||||
const nsACString &domain,
|
||||
PRUint32 *usage)
|
||||
{
|
||||
LOG(("nsOfflineCacheDevice::GetDomainUsage [cid=%s]\n", clientID));
|
||||
|
||||
*usage = 0;
|
||||
|
||||
AutoResetStatement statement(mStatement_DomainSize);
|
||||
nsresult rv;
|
||||
|
||||
rv = statement->BindUTF8StringParameter(0, nsDependentCString(clientID));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->BindUTF8StringParameter(1, domain);
|
||||
0, key);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool hasRows;
|
||||
rv = statement->ExecuteStep(&hasRows);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!hasRows)
|
||||
return NS_OK;
|
||||
while (hasRows) {
|
||||
nsCString clientID;
|
||||
rv = statement->GetUTF8String(0, clientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*usage = statement->AsInt32(0);
|
||||
if (mActiveCaches.Contains(clientID))
|
||||
return GetApplicationCache(clientID, out);
|
||||
|
||||
rv = statement->ExecuteStep(&hasRows);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::EvictUnownedEntries(const char *clientID)
|
||||
nsOfflineCacheDevice::ActivateCache(const nsCSubstring &group,
|
||||
const nsCSubstring &clientID)
|
||||
{
|
||||
LOG(("nsOfflineCacheDevice::EvictUnownedEntries [cid=%s]\n", clientID));
|
||||
EvictionObserver evictionObserver(mDB, mEvictionFunction);
|
||||
|
||||
AutoResetStatement statement(mStatement_DeleteUnowned);
|
||||
nsresult rv = statement->BindUTF8StringParameter(
|
||||
0, nsDependentCString(clientID));
|
||||
AutoResetStatement statement(mStatement_ActivateClient);
|
||||
nsresult rv = statement->BindUTF8StringParameter(0, group);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindUTF8StringParameter(1, clientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
evictionObserver.Apply();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
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)
|
||||
nsCString *active;
|
||||
if (mActiveCachesByGroup.Get(group, &active))
|
||||
{
|
||||
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);
|
||||
mActiveCaches.Remove(*active);
|
||||
mActiveCachesByGroup.Remove(group);
|
||||
active = nsnull;
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (!clientID.IsEmpty())
|
||||
{
|
||||
mActiveCaches.Put(clientID);
|
||||
mActiveCachesByGroup.Put(group, new nsCString(clientID));
|
||||
}
|
||||
|
||||
EvictionObserver evictionObserver(mDB, mEvictionFunction);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
AutoResetStatement deleteStatement(mStatement_DeleteConflicts);
|
||||
rv = deleteStatement->BindUTF8StringParameter(
|
||||
0, nsDependentCString(clientID));
|
||||
rv |= deleteStatement->BindUTF8StringParameter(
|
||||
1, nsDependentCString(fromClientID));
|
||||
PRBool
|
||||
nsOfflineCacheDevice::IsActiveCache(const nsCSubstring &group,
|
||||
const nsCSubstring &clientID)
|
||||
{
|
||||
nsCString *active = nsnull;
|
||||
return mActiveCachesByGroup.Get(group, &active) && *active == clientID;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheDevice::DeactivateGroup(const nsCSubstring &group)
|
||||
{
|
||||
nsCString *active = nsnull;
|
||||
|
||||
AutoResetStatement statement(mStatement_DeactivateGroup);
|
||||
nsresult rv = statement->BindUTF8StringParameter(
|
||||
0, group);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = deleteStatement->Execute();
|
||||
rv = statement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
AutoResetStatement swapStatement(mStatement_SwapClientID);
|
||||
rv = swapStatement->BindUTF8StringParameter(
|
||||
0, nsDependentCString(clientID));
|
||||
rv |= swapStatement->BindUTF8StringParameter(
|
||||
1, nsDependentCString(fromClientID));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (mActiveCachesByGroup.Get(group, &active))
|
||||
{
|
||||
mActiveCaches.Remove(*active);
|
||||
mActiveCachesByGroup.Remove(group);
|
||||
active = nsnull;
|
||||
}
|
||||
|
||||
rv = swapStatement->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
evictionObserver.Apply();
|
||||
nsresult
|
||||
nsOfflineCacheDevice::GetGroupForCache(const nsACString &clientID,
|
||||
nsCString &out)
|
||||
{
|
||||
out.Assign(clientID);
|
||||
out.Truncate(out.FindChar('|'));
|
||||
NS_UnescapeURL(out);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
#define nsOfflineCacheDevice_h__
|
||||
|
||||
#include "nsCacheDevice.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsIApplicationCacheService.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "mozIStorageConnection.h"
|
||||
|
@ -48,6 +50,10 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsInterfaceHashtable.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsHashSets.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
class nsOfflineCacheDevice;
|
||||
|
||||
|
@ -70,16 +76,22 @@ private:
|
|||
};
|
||||
|
||||
class nsOfflineCacheDevice : public nsCacheDevice
|
||||
, public nsIApplicationCacheService
|
||||
{
|
||||
public:
|
||||
nsOfflineCacheDevice();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIAPPLICATIONCACHESERVICE
|
||||
|
||||
/**
|
||||
* nsCacheDevice methods
|
||||
*/
|
||||
|
||||
virtual ~nsOfflineCacheDevice();
|
||||
|
||||
static nsOfflineCacheDevice *GetInstance();
|
||||
|
||||
virtual nsresult Init();
|
||||
virtual nsresult Shutdown();
|
||||
|
||||
|
@ -143,15 +155,15 @@ public:
|
|||
|
||||
nsresult ClearKeysOwnedByDomain(const char *clientID,
|
||||
const nsACString &ownerDomain);
|
||||
nsresult GetDomainUsage(const char *clientID,
|
||||
const nsACString &ownerDomain,
|
||||
PRUint32 *usage);
|
||||
nsresult EvictUnownedEntries(const char *clientID);
|
||||
|
||||
nsresult CreateTemporaryClientID(nsACString &clientID);
|
||||
nsresult MergeTemporaryClientID(const char *clientID,
|
||||
const char *fromClientID);
|
||||
|
||||
nsresult ActivateCache(const nsCSubstring &group,
|
||||
const nsCSubstring &clientID);
|
||||
PRBool IsActiveCache(const nsCSubstring &group,
|
||||
const nsCSubstring &clientID);
|
||||
nsresult DeactivateGroup(const nsCSubstring &group);
|
||||
nsresult GetGroupForCache(const nsCSubstring &clientID,
|
||||
nsCString &out);
|
||||
|
||||
/**
|
||||
* Preference accessors
|
||||
|
@ -166,13 +178,36 @@ public:
|
|||
PRUint32 EntryCount();
|
||||
|
||||
private:
|
||||
friend class nsApplicationCache;
|
||||
|
||||
static PLDHashOperator ShutdownApplicationCache(const nsACString &key,
|
||||
nsIWeakReference *weakRef,
|
||||
void *ctx);
|
||||
|
||||
PRBool Initialized() { return mDB != nsnull; }
|
||||
|
||||
nsresult InitActiveCaches();
|
||||
nsresult UpdateEntry(nsCacheEntry *entry);
|
||||
nsresult UpdateEntrySize(nsCacheEntry *entry, PRUint32 newSize);
|
||||
nsresult DeleteEntry(nsCacheEntry *entry, PRBool deleteData);
|
||||
nsresult DeleteData(nsCacheEntry *entry);
|
||||
nsresult EnableEvictionObserver();
|
||||
nsresult DisableEvictionObserver();
|
||||
|
||||
nsresult MarkEntry(const nsCString &clientID,
|
||||
const nsACString &key,
|
||||
PRUint32 typeBits);
|
||||
nsresult UnmarkEntry(const nsCString &clientID,
|
||||
const nsACString &key,
|
||||
PRUint32 typeBits);
|
||||
nsresult GetTypes(const nsCString &clientID,
|
||||
const nsACString &key,
|
||||
PRUint32 *typeBits);
|
||||
nsresult GatherEntries(const nsCString &clientID,
|
||||
PRUint32 typeBits,
|
||||
PRUint32 *count,
|
||||
char *** values);
|
||||
|
||||
nsresult RunSimpleQuery(mozIStorageStatement *statment,
|
||||
PRUint32 resultIndex,
|
||||
PRUint32 * count,
|
||||
|
@ -190,22 +225,23 @@ private:
|
|||
nsCOMPtr<mozIStorageStatement> mStatement_DeleteEntry;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_FindEntry;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_BindEntry;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_ClearOwnership;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_RemoveOwnership;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_ClearDomain;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_AddOwnership;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_CheckOwnership;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_DeleteConflicts;
|
||||
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<mozIStorageStatement> mStatement_MarkEntry;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_UnmarkEntry;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_GetTypes;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_CleanupUnmarked;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_GatherEntries;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_ActivateClient;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_DeactivateGroup;
|
||||
nsCOMPtr<mozIStorageStatement> mStatement_FindClient;
|
||||
|
||||
nsCOMPtr<nsILocalFile> mCacheDirectory;
|
||||
PRUint32 mCacheCapacity;
|
||||
PRInt32 mDeltaCounter;
|
||||
|
||||
nsInterfaceHashtable<nsCStringHashKey, nsIWeakReference> mCaches;
|
||||
nsClassHashtable<nsCStringHashKey, nsCString> mActiveCachesByGroup;
|
||||
nsCStringHashSet mActiveCaches;
|
||||
};
|
||||
|
||||
#endif // nsOfflineCacheDevice_h__
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "nsHttpResponseHead.h"
|
||||
#include "nsHttp.h"
|
||||
#include "nsIHttpAuthenticator.h"
|
||||
#include "nsIApplicationCacheService.h"
|
||||
#include "nsIAuthInformation.h"
|
||||
#include "nsIAuthPrompt2.h"
|
||||
#include "nsIAuthPromptProvider.h"
|
||||
|
@ -1371,26 +1372,61 @@ nsHttpChannel::OpenCacheEntry(PRBool offline, PRBool *delayed)
|
|||
else
|
||||
accessRequested = nsICache::ACCESS_READ_WRITE; // normal browsing
|
||||
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
if (mLoadFlags & LOAD_CHECK_OFFLINE_CACHE) {
|
||||
// when LOAD_CHECK_OFFLINE_CACHE set prefer the offline cache
|
||||
rv = gHttpHandler->GetCacheSession(nsICache::STORE_OFFLINE,
|
||||
getter_AddRefs(session));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!mApplicationCache) {
|
||||
// Pick up an application cache from the load group if available
|
||||
nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer;
|
||||
GetCallback(appCacheContainer);
|
||||
|
||||
// we'll try to synchronously open the cache entry... however, it may be
|
||||
// in use and not yet validated, in which case we'll try asynchronously
|
||||
// opening the cache entry.
|
||||
if (appCacheContainer) {
|
||||
appCacheContainer->GetApplicationCache(getter_AddRefs(mApplicationCache));
|
||||
}
|
||||
|
||||
if ((mLoadFlags & LOAD_CHECK_OFFLINE_CACHE) && !mApplicationCache) {
|
||||
// We're supposed to load from an application cache, but
|
||||
// one was not supplied by the load group. Ask the
|
||||
// application cache service to choose one for us.
|
||||
nsCOMPtr<nsIApplicationCacheService> appCacheService =
|
||||
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID);
|
||||
if (appCacheService) {
|
||||
nsresult rv = appCacheService->ChooseApplicationCache
|
||||
(cacheKey, getter_AddRefs(mApplicationCache));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
|
||||
// If we have an application cache, we check it first.
|
||||
if (mApplicationCache) {
|
||||
nsCAutoString appCacheClientID;
|
||||
mApplicationCache->GetClientID(appCacheClientID);
|
||||
|
||||
nsCOMPtr<nsICacheService> serv =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = serv->CreateSession(appCacheClientID.get(),
|
||||
nsICache::STORE_OFFLINE,
|
||||
nsICache::STREAM_BASED,
|
||||
getter_AddRefs(session));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// we'll try to synchronously open the cache entry... however,
|
||||
// it may be in use and not yet validated, in which case we'll
|
||||
// try asynchronously opening the cache entry.
|
||||
//
|
||||
// we need open in ACCESS_READ only because we don't want to overwrite
|
||||
// the offline cache entry non-atomically so ACCESS_READ
|
||||
// will prevent us from writing to the HTTP-offline cache as a
|
||||
// normal cache entry.
|
||||
rv = session->OpenCacheEntry(cacheKey, nsICache::ACCESS_READ, PR_FALSE,
|
||||
// we need open in ACCESS_READ only because we don't want to
|
||||
// overwrite the offline cache entry non-atomically so
|
||||
// ACCESS_READ will prevent us from writing to the
|
||||
// HTTP-offline cache as a normal cache entry. XXX: this
|
||||
// needs to be checked.
|
||||
rv = session->OpenCacheEntry(cacheKey,
|
||||
nsICache::ACCESS_READ, PR_FALSE,
|
||||
getter_AddRefs(mCacheEntry));
|
||||
}
|
||||
|
||||
if (!(mLoadFlags & LOAD_CHECK_OFFLINE_CACHE) ||
|
||||
if (!mApplicationCache ||
|
||||
(NS_FAILED(rv) && rv != NS_ERROR_CACHE_WAIT_FOR_VALIDATION))
|
||||
{
|
||||
rv = gHttpHandler->GetCacheSession(storagePolicy,
|
||||
|
@ -1457,20 +1493,18 @@ nsHttpChannel::OpenOfflineCacheEntryForWriting()
|
|||
nsCAutoString cacheKey;
|
||||
GenerateCacheKey(cacheKey);
|
||||
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
if (!mOfflineCacheClientID.IsEmpty()) {
|
||||
nsCOMPtr<nsICacheService> serv =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ENSURE_TRUE(!mOfflineCacheClientID.IsEmpty(),
|
||||
NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
rv = serv->CreateSession(mOfflineCacheClientID.get(),
|
||||
nsICache::STORE_OFFLINE,
|
||||
nsICache::STREAM_BASED,
|
||||
getter_AddRefs(session));
|
||||
} else {
|
||||
rv = gHttpHandler->GetCacheSession(nsICache::STORE_OFFLINE,
|
||||
getter_AddRefs(session));
|
||||
}
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
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));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = session->OpenCacheEntry(cacheKey, nsICache::ACCESS_READ_WRITE,
|
||||
|
@ -3387,6 +3421,7 @@ NS_INTERFACE_MAP_BEGIN(nsHttpChannel)
|
|||
NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyCallback)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIApplicationCacheContainer)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsHashPropertyBag)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -4876,6 +4911,24 @@ nsHttpChannel::DoAuthRetry(nsAHttpConnection *conn)
|
|||
return mTransactionPump->AsyncRead(this, nsnull);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel::nsIApplicationCacheContainer
|
||||
//-----------------------------------------------------------------------------
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::GetApplicationCache(nsIApplicationCache **out)
|
||||
{
|
||||
NS_IF_ADDREF(*out = mApplicationCache);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::SetApplicationCache(nsIApplicationCache *appCache)
|
||||
{
|
||||
mApplicationCache = appCache;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel::nsContentEncodings <public>
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -66,8 +66,11 @@
|
|||
#include "nsIInputStream.h"
|
||||
#include "nsIProgressEventSink.h"
|
||||
#include "nsICachingChannel.h"
|
||||
#include "nsICacheSession.h"
|
||||
#include "nsICacheEntryDescriptor.h"
|
||||
#include "nsICacheListener.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsIApplicationCacheContainer.h"
|
||||
#include "nsIEncodedChannel.h"
|
||||
#include "nsITransport.h"
|
||||
#include "nsIUploadChannel.h"
|
||||
|
@ -103,6 +106,7 @@ class nsHttpChannel : public nsHashPropertyBag
|
|||
, public nsISupportsPriority
|
||||
, public nsIProtocolProxyCallback
|
||||
, public nsIProxiedChannel
|
||||
, public nsIApplicationCacheContainer
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -121,6 +125,7 @@ public:
|
|||
NS_DECL_NSISUPPORTSPRIORITY
|
||||
NS_DECL_NSIPROTOCOLPROXYCALLBACK
|
||||
NS_DECL_NSIPROXIEDCHANNEL
|
||||
NS_DECL_NSIAPPLICATIONCACHECONTAINER
|
||||
|
||||
nsHttpChannel();
|
||||
virtual ~nsHttpChannel();
|
||||
|
@ -263,6 +268,8 @@ private:
|
|||
nsCacheAccessMode mOfflineCacheAccess;
|
||||
nsCString mOfflineCacheClientID;
|
||||
|
||||
nsCOMPtr<nsIApplicationCache> mApplicationCache;
|
||||
|
||||
// auth specific data
|
||||
nsISupports *mProxyAuthContinuationState;
|
||||
nsCString mProxyAuthType;
|
||||
|
|
|
@ -115,7 +115,7 @@ interface nsIOfflineCacheUpdateObserver : nsISupports {
|
|||
* load its items one by one, sending itemCompleted() to any registered
|
||||
* observers.
|
||||
*/
|
||||
[scriptable, uuid(7dc06ede-1098-4384-b95e-65525ab254c9)]
|
||||
[scriptable, uuid(4b206247-82ee-46cf-a8b7-f7284e753bc2)]
|
||||
interface nsIOfflineCacheUpdate : nsISupports {
|
||||
/**
|
||||
* Fetch the status of the running update. This will return a value
|
||||
|
@ -129,6 +129,12 @@ interface nsIOfflineCacheUpdate : nsISupports {
|
|||
*/
|
||||
readonly attribute boolean partial;
|
||||
|
||||
/**
|
||||
* TRUE if this is an upgrade attempt, FALSE if it is a new cache
|
||||
* attempt.
|
||||
*/
|
||||
readonly attribute boolean isUpgrade;
|
||||
|
||||
/**
|
||||
* The domain being updated, and the domain that will own any URIs added
|
||||
* with this update.
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
|
||||
#include "nsCPrefetchService.h"
|
||||
#include "nsCURILoader.h"
|
||||
#include "nsIApplicationCacheContainer.h"
|
||||
#include "nsIApplicationCacheService.h"
|
||||
#include "nsICache.h"
|
||||
#include "nsICacheService.h"
|
||||
#include "nsICacheSession.h"
|
||||
|
@ -47,7 +49,7 @@
|
|||
#include "nsIDOMWindow.h"
|
||||
#include "nsIDOMOfflineResourceList.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIOfflineCacheSession.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIWebProgress.h"
|
||||
#include "nsICryptoHash.h"
|
||||
#include "nsICacheEntryDescriptor.h"
|
||||
|
@ -104,10 +106,14 @@ NS_IMPL_ISUPPORTS6(nsOfflineCacheUpdateItem,
|
|||
nsOfflineCacheUpdateItem::nsOfflineCacheUpdateItem(nsOfflineCacheUpdate *aUpdate,
|
||||
nsIURI *aURI,
|
||||
nsIURI *aReferrerURI,
|
||||
const nsACString &aClientID)
|
||||
nsIApplicationCache *aPreviousApplicationCache,
|
||||
const nsACString &aClientID,
|
||||
PRUint32 type)
|
||||
: mURI(aURI)
|
||||
, mReferrerURI(aReferrerURI)
|
||||
, mPreviousApplicationCache(aPreviousApplicationCache)
|
||||
, mClientID(aClientID)
|
||||
, mItemType(type)
|
||||
, mUpdate(aUpdate)
|
||||
, mChannel(nsnull)
|
||||
, mState(nsIDOMLoadStatus::UNINITIALIZED)
|
||||
|
@ -122,12 +128,33 @@ nsOfflineCacheUpdateItem::~nsOfflineCacheUpdateItem()
|
|||
nsresult
|
||||
nsOfflineCacheUpdateItem::OpenChannel()
|
||||
{
|
||||
nsresult rv = NS_NewChannel(getter_AddRefs(mChannel),
|
||||
mURI,
|
||||
nsnull, nsnull, this,
|
||||
nsIRequest::LOAD_BACKGROUND |
|
||||
nsICachingChannel::LOAD_ONLY_IF_MODIFIED |
|
||||
nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE);
|
||||
#if defined(PR_LOGGING)
|
||||
if (LOG_ENABLED()) {
|
||||
nsCAutoString spec;
|
||||
mURI->GetSpec(spec);
|
||||
LOG(("%p: Opening channel for %s", this, spec.get()));
|
||||
}
|
||||
#endif
|
||||
|
||||
nsresult rv = nsOfflineCacheUpdate::GetCacheKey(mURI, mCacheKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = NS_NewChannel(getter_AddRefs(mChannel),
|
||||
mURI,
|
||||
nsnull, nsnull, this,
|
||||
nsIRequest::LOAD_BACKGROUND |
|
||||
nsICachingChannel::LOAD_ONLY_IF_MODIFIED |
|
||||
nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer =
|
||||
do_QueryInterface(mChannel, &rv);
|
||||
|
||||
// Support for nsIApplicationCacheContainer is required.
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Use the existing application cache as the cache to check.
|
||||
rv = appCacheContainer->SetApplicationCache(mPreviousApplicationCache);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// configure HTTP specific stuff
|
||||
|
@ -392,8 +419,11 @@ nsOfflineCacheUpdateItem::GetStatus(PRUint16 *aStatus)
|
|||
nsOfflineManifestItem::nsOfflineManifestItem(nsOfflineCacheUpdate *aUpdate,
|
||||
nsIURI *aURI,
|
||||
nsIURI *aReferrerURI,
|
||||
nsIApplicationCache *aPreviousApplicationCache,
|
||||
const nsACString &aClientID)
|
||||
: nsOfflineCacheUpdateItem(aUpdate, aURI, aReferrerURI, aClientID)
|
||||
: nsOfflineCacheUpdateItem(aUpdate, aURI, aReferrerURI,
|
||||
aPreviousApplicationCache, aClientID,
|
||||
nsIApplicationCache::ITEM_MANIFEST)
|
||||
, mParserState(PARSE_INIT)
|
||||
, mNeedsUpdate(PR_TRUE)
|
||||
, mManifestHashInitialized(PR_FALSE)
|
||||
|
@ -757,6 +787,28 @@ nsOfflineCacheUpdate::~nsOfflineCacheUpdate()
|
|||
LOG(("nsOfflineCacheUpdate::~nsOfflineCacheUpdate [%p]", this));
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsOfflineCacheUpdate::GetCacheKey(nsIURI *aURI, nsACString &aKey)
|
||||
{
|
||||
aKey.Truncate();
|
||||
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
nsresult rv = aURI->Clone(getter_AddRefs(newURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURL> newURL;
|
||||
newURL = do_QueryInterface(newURI);
|
||||
if (newURL) {
|
||||
newURL->SetRef(EmptyCString());
|
||||
}
|
||||
|
||||
rv = newURI->GetAsciiSpec(aKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheUpdate::Init(PRBool aPartialUpdate,
|
||||
nsIURI *aManifestURI,
|
||||
|
@ -770,7 +822,7 @@ nsOfflineCacheUpdate::Init(PRBool aPartialUpdate,
|
|||
if (!service)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
LOG(("nsOfflineCacheUpdate::Init [%p]", this));
|
||||
LOG(("nsOfflineCacheUpdate::Init [%p, %d]", this, aPartialUpdate));
|
||||
|
||||
mPartialUpdate = aPartialUpdate;
|
||||
|
||||
|
@ -793,58 +845,31 @@ nsOfflineCacheUpdate::Init(PRBool aPartialUpdate,
|
|||
|
||||
nsCAutoString manifestSpec;
|
||||
|
||||
rv = mManifestURI->GetAsciiSpec(manifestSpec);
|
||||
rv = GetCacheKey(mManifestURI, manifestSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 ref = manifestSpec.FindChar('#');
|
||||
if (ref != kNotFound)
|
||||
manifestSpec.Truncate(ref);
|
||||
|
||||
mManifestOwnerSpec = manifestSpec;
|
||||
mManifestOwnerSpec.AppendLiteral("#manifest");
|
||||
|
||||
mDynamicOwnerSpec = manifestSpec;
|
||||
mDynamicOwnerSpec.AppendLiteral("#dynamic");
|
||||
|
||||
mDocumentURI = aDocumentURI;
|
||||
|
||||
nsCOMPtr<nsICacheService> cacheService =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
nsCOMPtr<nsIApplicationCacheService> cacheService =
|
||||
do_GetService(NS_APPLICATIONCACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
rv = cacheService->CreateSession("HTTP-offline",
|
||||
nsICache::STORE_OFFLINE,
|
||||
nsICache::STREAM_BASED,
|
||||
getter_AddRefs(session));
|
||||
rv = cacheService->GetActiveCache(manifestSpec,
|
||||
getter_AddRefs(mPreviousApplicationCache));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mMainCacheSession = do_QueryInterface(session, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Partial updates don't use temporary cache sessions
|
||||
if (aPartialUpdate) {
|
||||
mCacheSession = mMainCacheSession;
|
||||
// Partial updates to existing application caches don't need a new cache.
|
||||
if (aPartialUpdate && mPreviousApplicationCache) {
|
||||
mApplicationCache = mPreviousApplicationCache;
|
||||
} 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);
|
||||
|
||||
// The manifest implicitly owns itself.
|
||||
rv = mCacheSession->AddOwnedKey(mUpdateDomain, mManifestOwnerSpec,
|
||||
manifestSpec);
|
||||
rv = cacheService->CreateApplicationCache(manifestSpec,
|
||||
getter_AddRefs(mApplicationCache));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = mApplicationCache->GetClientID(mClientID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mState = STATE_INITIALIZED;
|
||||
|
||||
return NS_OK;
|
||||
|
@ -871,17 +896,21 @@ nsOfflineCacheUpdate::HandleManifest(PRBool *aDoUpdate)
|
|||
// Add items requested by the manifest.
|
||||
const nsCOMArray<nsIURI> &manifestURIs = mManifestItem->GetExplicitURIs();
|
||||
for (PRInt32 i = 0; i < manifestURIs.Count(); i++) {
|
||||
rv = AddURI(manifestURIs[i], mManifestOwnerSpec);
|
||||
rv = AddURI(manifestURIs[i], nsIApplicationCache::ITEM_EXPLICIT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// The document that requested the manifest is implicitly included
|
||||
// as part of that manifest update.
|
||||
rv = AddURI(mDocumentURI, mManifestOwnerSpec);
|
||||
rv = AddURI(mDocumentURI, nsIApplicationCache::ITEM_IMPLICIT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Add items previously cached implicitly
|
||||
rv = AddExistingItems(nsIApplicationCache::ITEM_IMPLICIT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Add items requested by the script API
|
||||
rv = AddOwnedItems(mDynamicOwnerSpec);
|
||||
rv = AddExistingItems(nsIApplicationCache::ITEM_DYNAMIC);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aDoUpdate = PR_TRUE;
|
||||
|
@ -922,6 +951,15 @@ nsOfflineCacheUpdate::LoadCompleted()
|
|||
return;
|
||||
}
|
||||
|
||||
rv = mApplicationCache->MarkEntry(mManifestItem->mCacheKey,
|
||||
mManifestItem->mItemType);
|
||||
if (NS_FAILED(rv)) {
|
||||
mSucceeded = PR_FALSE;
|
||||
NotifyError();
|
||||
Finish();
|
||||
return;
|
||||
}
|
||||
|
||||
mState = STATE_DOWNLOADING;
|
||||
NotifyDownloading();
|
||||
|
||||
|
@ -947,6 +985,14 @@ nsOfflineCacheUpdate::LoadCompleted()
|
|||
return;
|
||||
}
|
||||
|
||||
rv = mApplicationCache->MarkEntry(item->mCacheKey, item->mItemType);
|
||||
if (NS_FAILED(rv)) {
|
||||
mSucceeded = PR_FALSE;
|
||||
NotifyError();
|
||||
Finish();
|
||||
return;
|
||||
}
|
||||
|
||||
rv = NotifyCompleted(item);
|
||||
if (NS_FAILED(rv)) return;
|
||||
|
||||
|
@ -971,7 +1017,9 @@ nsOfflineCacheUpdate::Begin()
|
|||
nsCOMPtr<nsIURI> uri;
|
||||
|
||||
mManifestItem = new nsOfflineManifestItem(this, mManifestURI,
|
||||
mDocumentURI, mClientID);
|
||||
mDocumentURI,
|
||||
mPreviousApplicationCache,
|
||||
mClientID);
|
||||
if (!mManifestItem) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -1009,12 +1057,16 @@ nsOfflineCacheUpdate::Cancel()
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheUpdate::AddOwnedItems(const nsACString &aOwnerURI)
|
||||
nsOfflineCacheUpdate::AddExistingItems(PRUint32 aType)
|
||||
{
|
||||
PRUint32 count;
|
||||
char **keys;
|
||||
nsresult rv = mMainCacheSession->GetOwnedKeys(mUpdateDomain, aOwnerURI,
|
||||
&count, &keys);
|
||||
if (!mPreviousApplicationCache) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint32 count = 0;
|
||||
char **keys = nsnull;
|
||||
nsresult rv = mPreviousApplicationCache->GatherEntries(aType,
|
||||
&count, &keys);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
AutoFreeArray autoFree(count, keys);
|
||||
|
@ -1022,12 +1074,8 @@ nsOfflineCacheUpdate::AddOwnedItems(const nsACString &aOwnerURI)
|
|||
for (PRUint32 i = 0; i < count; i++) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), keys[i]))) {
|
||||
nsRefPtr<nsOfflineCacheUpdateItem> item =
|
||||
new nsOfflineCacheUpdateItem(this, uri, mDocumentURI,
|
||||
mClientID);
|
||||
if (!item) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mItems.AppendElement(item);
|
||||
rv = AddURI(uri, aType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1090,6 +1138,8 @@ nsOfflineCacheUpdate::NotifyError()
|
|||
{
|
||||
LOG(("nsOfflineCacheUpdate::NotifyError [%p]", this));
|
||||
|
||||
mState = STATE_FINISHED;
|
||||
|
||||
nsCOMArray<nsIOfflineCacheUpdateObserver> observers;
|
||||
nsresult rv = GatherObservers(observers);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -1122,6 +1172,8 @@ nsOfflineCacheUpdate::NotifyNoUpdate()
|
|||
{
|
||||
LOG(("nsOfflineCacheUpdate::NotifyNoUpdate [%p]", this));
|
||||
|
||||
mState = STATE_FINISHED;
|
||||
|
||||
nsCOMArray<nsIOfflineCacheUpdateObserver> observers;
|
||||
nsresult rv = GatherObservers(observers);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -1196,7 +1248,7 @@ nsOfflineCacheUpdate::Finish()
|
|||
|
||||
if (!mPartialUpdate) {
|
||||
if (mSucceeded) {
|
||||
nsresult rv = mMainCacheSession->MergeTemporaryClientID(mClientID);
|
||||
nsresult rv = mApplicationCache->Activate();
|
||||
if (NS_FAILED(rv)) {
|
||||
NotifyError();
|
||||
mSucceeded = PR_FALSE;
|
||||
|
@ -1208,6 +1260,8 @@ nsOfflineCacheUpdate::Finish()
|
|||
for (PRUint32 i = 0; i < mItems.Length(); i++) {
|
||||
mItems[i]->Cancel();
|
||||
}
|
||||
|
||||
mApplicationCache->Discard();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1271,15 +1325,25 @@ nsOfflineCacheUpdate::GetSucceeded(PRBool *aSucceeded)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOfflineCacheUpdate::GetIsUpgrade(PRBool *aIsUpgrade)
|
||||
{
|
||||
NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
*aIsUpgrade = (mPreviousApplicationCache != nsnull);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsOfflineCacheUpdate::AddURI(nsIURI *aURI, const nsACString &aOwnerSpec)
|
||||
nsOfflineCacheUpdate::AddURI(nsIURI *aURI, PRUint32 aType)
|
||||
{
|
||||
NS_ENSURE_TRUE(mState >= STATE_INITIALIZED, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
if (mState >= STATE_DOWNLOADING)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
// Manifest URIs must have the same scheme as the manifest.
|
||||
// Resource URIs must have the same scheme as the manifest.
|
||||
nsCAutoString scheme;
|
||||
aURI->GetScheme(scheme);
|
||||
|
||||
|
@ -1287,35 +1351,20 @@ nsOfflineCacheUpdate::AddURI(nsIURI *aURI, const nsACString &aOwnerSpec)
|
|||
if (NS_FAILED(mManifestURI->SchemeIs(scheme.get(), &match)) || !match)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Save the cache key as an owned URI
|
||||
nsCAutoString spec;
|
||||
nsresult rv = aURI->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// url fragments aren't used in cache keys
|
||||
nsCAutoString::const_iterator specStart, specEnd;
|
||||
spec.BeginReading(specStart);
|
||||
spec.EndReading(specEnd);
|
||||
if (FindCharInReadable('#', specStart, specEnd)) {
|
||||
spec.BeginReading(specEnd);
|
||||
rv = mCacheSession->AddOwnedKey(mUpdateDomain, aOwnerSpec,
|
||||
Substring(specEnd, specStart));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
rv = mCacheSession->AddOwnedKey(mUpdateDomain, aOwnerSpec, spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Don't fetch the same URI twice.
|
||||
for (PRUint32 i = 0; i < mItems.Length(); i++) {
|
||||
PRBool equals;
|
||||
if (NS_SUCCEEDED(mItems[i]->mURI->Equals(aURI, &equals)) && equals) {
|
||||
// retain both types.
|
||||
mItems[i]->mItemType |= aType;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<nsOfflineCacheUpdateItem> item =
|
||||
new nsOfflineCacheUpdateItem(this, aURI, mDocumentURI, mClientID);
|
||||
new nsOfflineCacheUpdateItem(this, aURI, mDocumentURI,
|
||||
mPreviousApplicationCache, mClientID,
|
||||
aType);
|
||||
if (!item) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mItems.AppendElement(item);
|
||||
|
@ -1327,7 +1376,24 @@ nsOfflineCacheUpdate::AddURI(nsIURI *aURI, const nsACString &aOwnerSpec)
|
|||
NS_IMETHODIMP
|
||||
nsOfflineCacheUpdate::AddDynamicURI(nsIURI *aURI)
|
||||
{
|
||||
return AddURI(aURI, mDynamicOwnerSpec);
|
||||
// If this is a partial update and the resource is already in the
|
||||
// cache, we should only mark the entry, not fetch it again.
|
||||
if (mPartialUpdate) {
|
||||
nsCAutoString key;
|
||||
GetCacheKey(aURI, key);
|
||||
|
||||
PRUint32 types;
|
||||
nsresult rv = mApplicationCache->GetTypes(key, &types);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (!(types & nsIApplicationCache::ITEM_DYNAMIC)) {
|
||||
mApplicationCache->MarkEntry
|
||||
(key, nsIApplicationCache::ITEM_DYNAMIC);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return AddURI(aURI, nsIApplicationCache::ITEM_DYNAMIC);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -52,8 +52,7 @@
|
|||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIOfflineCacheSession.h"
|
||||
#include "nsIPrefetchService.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsIRequestObserver.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIStreamListener.h"
|
||||
|
@ -87,12 +86,17 @@ public:
|
|||
nsOfflineCacheUpdateItem(nsOfflineCacheUpdate *aUpdate,
|
||||
nsIURI *aURI,
|
||||
nsIURI *aReferrerURI,
|
||||
const nsACString &aClientID);
|
||||
nsIApplicationCache *aPreviousApplicationCache,
|
||||
const nsACString &aClientID,
|
||||
PRUint32 aType);
|
||||
virtual ~nsOfflineCacheUpdateItem();
|
||||
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
nsCOMPtr<nsIURI> mReferrerURI;
|
||||
nsCOMPtr<nsIApplicationCache> mPreviousApplicationCache;
|
||||
nsCString mClientID;
|
||||
nsCString mCacheKey;
|
||||
PRUint32 mItemType;
|
||||
|
||||
nsresult OpenChannel();
|
||||
nsresult Cancel();
|
||||
|
@ -116,6 +120,7 @@ public:
|
|||
nsOfflineManifestItem(nsOfflineCacheUpdate *aUpdate,
|
||||
nsIURI *aURI,
|
||||
nsIURI *aReferrerURI,
|
||||
nsIApplicationCache *aPreviousApplicationCache,
|
||||
const nsACString &aClientID);
|
||||
virtual ~nsOfflineManifestItem();
|
||||
|
||||
|
@ -177,19 +182,22 @@ public:
|
|||
nsOfflineCacheUpdate();
|
||||
~nsOfflineCacheUpdate();
|
||||
|
||||
static nsresult GetCacheKey(nsIURI *aURI, nsACString &aKey);
|
||||
|
||||
nsresult Init();
|
||||
|
||||
nsresult Begin();
|
||||
nsresult Cancel();
|
||||
|
||||
void LoadCompleted();
|
||||
|
||||
private:
|
||||
nsresult HandleManifest(PRBool *aDoUpdate);
|
||||
nsresult AddURI(nsIURI *aURI, const nsACString &aOwnerSpec);
|
||||
nsresult AddURI(nsIURI *aURI, PRUint32 aItemType);
|
||||
|
||||
nsresult ProcessNextURI();
|
||||
|
||||
nsresult AddOwnedItems(const nsACString &aOwnerURI);
|
||||
nsresult AddExistingItems(PRUint32 aType);
|
||||
|
||||
nsresult GatherObservers(nsCOMArray<nsIOfflineCacheUpdateObserver> &aObservers);
|
||||
nsresult NotifyError();
|
||||
|
@ -214,14 +222,12 @@ private:
|
|||
PRBool mSucceeded;
|
||||
nsCString mUpdateDomain;
|
||||
nsCOMPtr<nsIURI> mManifestURI;
|
||||
nsCString mManifestOwnerSpec;
|
||||
nsCString mDynamicOwnerSpec;
|
||||
|
||||
nsCOMPtr<nsIURI> mDocumentURI;
|
||||
|
||||
nsCString mClientID;
|
||||
nsCOMPtr<nsIOfflineCacheSession> mCacheSession;
|
||||
nsCOMPtr<nsIOfflineCacheSession> mMainCacheSession;
|
||||
nsCOMPtr<nsIApplicationCache> mApplicationCache;
|
||||
nsCOMPtr<nsIApplicationCache> mPreviousApplicationCache;
|
||||
|
||||
nsCOMPtr<nsIObserverService> mObserverService;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче