Bug 370195 – sql device for the offline cache

patch by Dave Camp <dcamp@mozilla.com> r=jst (content part) r=biesi (rest)


git-svn-id: svn://10.0.0.236/trunk@226398 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
cbiesinger%web.de
2007-05-14 20:09:20 +00:00
parent 032943e6bf
commit 6e69609e46
23 changed files with 1198 additions and 464 deletions

View File

@@ -59,6 +59,7 @@ REQUIRES = xpcom \
js \
webshell \
necko \
nkcache \
mimetype \
caps \
lwbrk \

View File

@@ -68,6 +68,10 @@
#include "nsIPrincipal.h"
#include "nsIScriptGlobalObject.h"
#include "nsNetCID.h"
#include "nsICache.h"
#include "nsICacheService.h"
#include "nsICacheSession.h"
#include "nsIOfflineCacheSession.h"
#include "nsICookieService.h"
#include "nsIPrompt.h"
#include "nsServiceManagerUtils.h"
@@ -673,7 +677,9 @@ nsContentSink::ProcessLink(nsIContent* aElement,
// fetch href into the offline cache if relation is "offline-resource"
if (linkTypes.IndexOf(NS_LITERAL_STRING("offline-resource")) != -1) {
PrefetchHref(aHref, PR_TRUE, PR_TRUE);
AddOfflineResource(aHref);
if (mSaveOfflineResources)
PrefetchHref(aHref, PR_TRUE, PR_TRUE);
}
// is it a stylesheet link?
@@ -809,6 +815,115 @@ nsContentSink::PrefetchHref(const nsAString &aHref,
}
}
nsresult
nsContentSink::GetOfflineCacheSession(nsIOfflineCacheSession **aSession)
{
if (!mOfflineCacheSession) {
nsresult 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);
mOfflineCacheSession =
do_QueryInterface(session, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
NS_ADDREF(*aSession = mOfflineCacheSession);
return NS_OK;
}
nsresult
nsContentSink::AddOfflineResource(const nsAString &aHref)
{
PRBool match;
nsresult rv;
nsCAutoString ownerHost;
rv = mDocumentURI->GetHostPort(ownerHost);
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString ownerSpec;
rv = mDocumentURI->GetSpec(ownerSpec);
NS_ENSURE_SUCCESS(rv, rv);
if (!mHaveOfflineResources) {
mHaveOfflineResources = PR_TRUE;
mSaveOfflineResources = PR_FALSE;
// only let http and https urls add offline resources
nsresult rv = mDocumentURI->SchemeIs("http", &match);
NS_ENSURE_SUCCESS(rv, rv);
if (!match) {
rv = mDocumentURI->SchemeIs("https", &match);
NS_ENSURE_SUCCESS(rv, rv);
if (!match)
return NS_OK;
}
nsCOMPtr<nsIOfflineCacheSession> session;
rv = GetOfflineCacheSession(getter_AddRefs(session));
NS_ENSURE_SUCCESS(rv, rv);
// we're going to replace the list, clear it out
rv = session->SetOwnedKeys(ownerHost, ownerSpec, 0, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
mSaveOfflineResources = PR_TRUE;
}
if (!mSaveOfflineResources) return NS_OK;
const nsACString &charset = mDocument->GetDocumentCharacterSet();
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), aHref,
charset.IsEmpty() ? nsnull : PromiseFlatCString(charset).get(),
mDocumentBaseURI);
NS_ENSURE_SUCCESS(rv, rv);
// only http and https urls can be marked as offline resources
rv = uri->SchemeIs("http", &match);
NS_ENSURE_SUCCESS(rv, rv);
if (!match) {
rv = uri->SchemeIs("https", &match);
NS_ENSURE_SUCCESS(rv, rv);
if (!match)
return NS_OK;
}
nsCAutoString spec;
rv = uri->GetSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIOfflineCacheSession> offlineCacheSession;
rv = GetOfflineCacheSession(getter_AddRefs(offlineCacheSession));
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);
offlineCacheSession->AddOwnedKey(ownerHost, ownerSpec,
Substring(specEnd, specStart));
} else {
offlineCacheSession->AddOwnedKey(ownerHost, ownerSpec, spec);
}
return NS_OK;
}
void
nsContentSink::ScrollToRef()
{

View File

@@ -75,6 +75,7 @@ class nsIContent;
class nsIViewManager;
class nsNodeInfoManager;
class nsScriptLoader;
class nsIOfflineCacheSession;
#ifdef NS_DEBUG
@@ -167,6 +168,8 @@ protected:
const nsSubstring& aMedia);
void PrefetchHref(const nsAString &aHref, PRBool aExplicit, PRBool aOffline);
nsresult GetOfflineCacheSession(nsIOfflineCacheSession **aSession);
nsresult AddOfflineResource(const nsAString &aHref);
void ScrollToRef();
nsresult RefreshIfEnabled(nsIViewManager* vm);
@@ -252,6 +255,9 @@ protected:
// Do we notify based on time?
PRPackedBool mNotifyOnTimer;
// For saving <link rel="offline-resource"> links
nsCOMPtr<nsIOfflineCacheSession> mOfflineCacheSession;
// Have we already called BeginUpdate for this set of content changes?
PRUint8 mBeganUpdate : 1;
PRUint8 mLayoutStarted : 1;
@@ -264,7 +270,11 @@ protected:
PRUint8 mChangeScrollPosWhenScrollingToRef : 1;
// If true, we deferred starting layout until sheets load
PRUint8 mDeferredLayoutStart : 1;
// true if an <link rel="offline-resource"> nodes have been encountered.
PRUint8 mHaveOfflineResources : 1;
// true if offline-resource links should be saved to the offline cache
PRUint8 mSaveOfflineResources : 1;
// -- Can interrupt parsing members --
PRUint32 mDelayTimerStart;

View File

@@ -3012,7 +3012,9 @@ HTMLContentSink::ProcessLINKTag(const nsIParserNode& aNode)
nsAutoString hrefVal;
element->GetAttr(kNameSpaceID_None, nsGkAtoms::href, hrefVal);
if (!hrefVal.IsEmpty()) {
PrefetchHref(hrefVal, PR_TRUE, PR_TRUE);
AddOfflineResource(hrefVal);
if (mSaveOfflineResources)
PrefetchHref(hrefVal, PR_TRUE, PR_TRUE);
}
}
}

View File

@@ -70,7 +70,7 @@ pref("browser.cache.check_doc_frequency", 3);
pref("browser.cache.offline.enable", true);
// offline cache capacity in kilobytes
pref("browser.cache.offline.capacity", 51200);
pref("browser.cache.offline.capacity", 10240);
// Fastback caching - if this pref is negative, then we calculate the number
// of content viewers to cache based on the amount of available memory.

View File

@@ -58,6 +58,11 @@ endif
# tier "necko" - the networking library and its dependencies
#
# the offline cache uses mozStorage
ifdef MOZ_STORAGE
tier_necko_dirs += storage/public
endif
# these are only in the necko tier because libpref needs it
ifneq (1_,$(MOZ_NO_XPCOM_OBSOLETE)_$(MOZ_XPINSTALL))

View File

@@ -53,7 +53,8 @@ XPIDLSRCS = \
nsICacheService.idl \
nsICacheSession.idl \
nsICacheVisitor.idl \
$(NULL)
nsIOfflineCacheSession.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,160 @@
/* -*- 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"
[scriptable, uuid(e9581d9f-3c0c-4722-8d2b-3d18f8d41299)]
interface nsIOfflineCacheSession : nsISupports
{
/**
* The offline cache is meant to reliably store resources for
* offline use. The expected semantics are:
*
* a) Once populated, the cache will not evict an application resource
* unless explicitly asked.
*
* b) Resources no longer in use by the application should be evicted.
*
* c) If the cache fills up, new entries should be rejected rather
* than throwing out old ones.
*
* The offline cache uses domains to concretely represent an
* application. It maintains a list of resources to be pinned for
* each domain. This list is separate from actual cache
* population - the caller is still responsible for placing items
* in the cache, and ownership can be declared without a
* corresponding entry.
*
* A key can optionally be associated with a specific URI within
* the domain.
*/
/**
* 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 ownerDomain The domain that owns the resources.
* @param ownerURI The specific URI that owns the resources. This can
* be empty if no URI specifically owns the resources.
* @param count The number of keys in keys.
* @param keys The keys that the domain/URI pair own. This can be empty
* to clear ownership for the domain/URI pair.
*/
void setOwnedKeys(in ACString ownerDomain,
in ACString ownerURI,
in unsigned long count,
[array, size_is(count)]in string keys);
/**
* Gets the list of resources owned by a given domain/URI pair.
*
* @param ownerDomain The domain that owns the resources.
* @param ownerURI The specific URI that owns the resources. This can
* be empty if no URI specifically owns the resources.
* @param count The number of keys in keys.
* @param keys The keys that the domain/URI pair own.
*/
void getOwnedKeys(in ACString ownerDomain,
in ACString ownerURI,
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 ownerDomain The domain that owns the resources.
* @param ownerURI The specific URI that owns the resources. This can
* be empty if no URI specifically owns the resources.
* @param key The key to add.
*/
void addOwnedKey(in ACString ownerDomain,
in ACString ownerURI,
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 ownerDomain The domain that owns the resources.
* @param ownerURI The specific URI that owns the resources. This can
* be empty if no URI specifically owns the resources.
* @param key The key to remove.
*/
void removeOwnedKey(in ACString ownerDomain,
in ACString ownerURI,
in ACString key);
/**
* Checks whether a key is owned by a given domain/URI pair.
*
* @param ownerDomain The domain that owns the resources.
* @param ownerURI The specific URI that owns the resources. This can
* be empty if no URI specifically owns the resources.
* @param key The key to check
*/
boolean keyIsOwned(in ACString ownerDomain,
in ACString ownerURI,
in ACString key);
/**
* Remove all keys owned by a domain, including keys owned by
* a specific URI.
*
* @param domain The domain for which keys should be removed.
*/
void clearKeysOwnedByDomain(in ACString ownerDomain);
/**
* Evict all entries that are not owned by a domain.
*/
void evictUnownedEntries();
};

View File

@@ -69,13 +69,6 @@ CPPSRCS = \
$(NULL)
ifdef NECKO_DISK_CACHE
ifdef NECKO_DISK_CACHE_SQL
DEFINES += -DNECKO_DISK_CACHE_SQL
REQUIRES += storage
CPPSRCS += \
nsDiskCacheDeviceSQL.cpp \
$(NULL)
else
CPPSRCS += \
nsDiskCacheBinding.cpp \
nsDiskCacheBlockFile.cpp \
@@ -86,6 +79,14 @@ CPPSRCS += \
nsDeleteDir.cpp \
$(NULL)
endif
ifdef MOZ_STORAGE
CPPSRCS += \
nsDiskCacheDeviceSQL.cpp \
$(NULL)
REQUIRES += storage
DEFINES += -DNECKO_OFFLINE_CACHE
endif
LOCAL_INCLUDES=-I$(srcdir)/../../base/src

View File

@@ -307,8 +307,8 @@ nsCacheEntryInfo::GetDeviceID(char ** deviceID)
{
NS_ENSURE_ARG_POINTER(deviceID);
if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
*deviceID = nsCRT::strdup(mCacheEntry->GetDeviceID());
*deviceID = NS_strdup(mCacheEntry->GetDeviceID());
return *deviceID ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}

View File

@@ -95,7 +95,7 @@ nsCacheEntryDescriptor::GetDeviceID(char ** result)
nsCacheServiceAutoLock lock;
if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
*result = nsCRT::strdup(mCacheEntry->GetDeviceID());
*result = NS_strdup(mCacheEntry->GetDeviceID());
return *result ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
@@ -438,7 +438,7 @@ nsCacheEntryDescriptor::GetMetaDataElement(const char *key, char **result)
value = mCacheEntry->GetMetaDataElement(key);
if (!value) return NS_ERROR_NOT_AVAILABLE;
*result = PL_strdup(value);
*result = NS_strdup(value);
if (!*result) return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;

View File

@@ -48,11 +48,10 @@
#include "nsCacheDevice.h"
#include "nsMemoryCacheDevice.h"
#include "nsICacheVisitor.h"
#ifdef NECKO_DISK_CACHE_SQL
#include "nsDiskCacheDeviceSQL.h"
#else
#include "nsDiskCacheDevice.h"
#ifdef NECKO_OFFLINE_CACHE
#include "nsDiskCacheDeviceSQL.h"
#endif
#include "nsIObserverService.h"
@@ -86,7 +85,7 @@
#define OFFLINE_CACHE_ENABLE_PREF "browser.cache.offline.enable"
#define OFFLINE_CACHE_DIR_PREF "browser.cache.offline.parent_directory"
#define OFFLINE_CACHE_CAPACITY_PREF "browser.cache.offline.capacity"
#define OFFLINE_CACHE_CAPACITY 51200
#define OFFLINE_CACHE_CAPACITY 512000
#define MEMORY_CACHE_ENABLE_PREF "browser.cache.memory.enable"
#define MEMORY_CACHE_CAPACITY_PREF "browser.cache.memory.capacity"
@@ -662,14 +661,16 @@ nsCacheService::Shutdown()
#ifdef NECKO_DISK_CACHE
delete mDiskDevice;
mDiskDevice = nsnull;
#endif // !NECKO_DISK_CACHE
#ifdef NECKO_OFFLINE_CACHE
delete mOfflineDevice;
mOfflineDevice = nsnull;
#endif // !NECKO_OFFLINE_CACHE
#if defined(PR_LOGGING)
#if defined(NECKO_DISK_CACHE) && defined(PR_LOGGING)
LogCacheStatistics();
#endif
#endif // !NECKO_DISK_CACHE
}
}
@@ -765,7 +766,9 @@ nsCacheService::EvictEntriesForClient(const char * clientID,
if (NS_FAILED(rv)) return rv;
}
}
#endif // ! NECKO_DISK_CACHE
#ifdef NECKO_OFFLINE_CACHE
if (storagePolicy == nsICache::STORE_ANYWHERE ||
storagePolicy == nsICache::STORE_OFFLINE) {
if (mEnableOfflineDevice) {
@@ -777,7 +780,7 @@ nsCacheService::EvictEntriesForClient(const char * clientID,
if (NS_FAILED(rv)) return rv;
}
}
#endif // ! NECKO_DISK_CACHE
#endif // ! NECKO_OFFLINE_CACHE
if (storagePolicy == nsICache::STORE_ANYWHERE ||
storagePolicy == nsICache::STORE_IN_MEMORY) {
@@ -827,6 +830,162 @@ nsCacheService::IsStorageEnabledForPolicy_Locked(nsCacheStoragePolicy storagePo
return PR_FALSE;
}
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::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
}
NS_IMETHODIMP nsCacheService::VisitEntries(nsICacheVisitor *visitor)
{
@@ -856,7 +1015,9 @@ NS_IMETHODIMP nsCacheService::VisitEntries(nsICacheVisitor *visitor)
rv = mDiskDevice->Visit(visitor);
if (NS_FAILED(rv)) return rv;
}
#endif // !NECKO_DISK_CACHE
#ifdef NECKO_OFFLINE_CACHE
if (mEnableOfflineDevice) {
if (!mOfflineDevice) {
rv = CreateOfflineDevice();
@@ -865,7 +1026,7 @@ NS_IMETHODIMP nsCacheService::VisitEntries(nsICacheVisitor *visitor)
rv = mOfflineDevice->Visit(visitor);
if (NS_FAILED(rv)) return rv;
}
#endif // !NECKO_DISK_CACHE
#endif // !NECKO_OFFLINE_CACHE
// XXX notify any shutdown process that visitation is complete for THIS visitor.
// XXX keep queue of visitors
@@ -919,19 +1080,18 @@ nsCacheService::CreateDiskDevice()
nsresult
nsCacheService::CreateOfflineDevice()
{
#ifdef NECKO_DISK_CACHE
#ifdef NECKO_OFFLINE_CACHE
CACHE_LOG_ALWAYS(("Creating offline device"));
// XXX: want a sql-based device
if (!mEnableOfflineDevice) return NS_ERROR_NOT_AVAILABLE;
if (mOfflineDevice) return NS_OK;
mOfflineDevice = new nsDiskCacheDevice;
mOfflineDevice = new nsOfflineCacheDevice;
if (!mOfflineDevice) return NS_ERROR_OUT_OF_MEMORY;
// set the preferences
mOfflineDevice->SetCacheParentDirectoryAndName(mObserver->OfflineCacheParentDirectory(),
NS_LITERAL_CSTRING("OfflineCache"));
mOfflineDevice->SetCacheParentDirectory(
mObserver->OfflineCacheParentDirectory());
mOfflineDevice->SetCapacity(mObserver->OfflineCacheCapacity());
nsresult rv = mOfflineDevice->Init();
@@ -1282,7 +1442,7 @@ nsCacheService::SearchCacheDevices(nsCString * key, nsCacheStoragePolicy policy,
(policy == nsICache::STORE_ANYWHERE &&
gIOService->IsOffline()))) {
#ifdef NECKO_DISK_CACHE
#ifdef NECKO_OFFLINE_CACHE
if (mEnableOfflineDevice) {
if (!mOfflineDevice) {
nsresult rv = CreateOfflineDevice();
@@ -1292,7 +1452,7 @@ nsCacheService::SearchCacheDevices(nsCString * key, nsCacheStoragePolicy policy,
entry = mOfflineDevice->FindEntry(key, collision);
}
#endif
#endif // !NECKO_OFFLINE_CACHE
}
return entry;
@@ -1336,7 +1496,7 @@ nsCacheService::EnsureEntryHasDevice(nsCacheEntry * entry)
}
}
#ifdef NECKO_DISK_CACHE
#ifdef NECKO_OFFLINE_CACHE
if (!device && entry->IsStreamData() &&
entry->IsAllowedOffline() && mEnableOfflineDevice) {
if (!mOfflineDevice) {
@@ -1351,7 +1511,7 @@ nsCacheService::EnsureEntryHasDevice(nsCacheEntry * entry)
device = mOfflineDevice;
}
}
#endif // ! NECKO_DISK_CACHE
#endif // ! NECKO_OFFLINE_CACHE
if (device)
entry->SetCacheDevice(device);
@@ -1416,7 +1576,9 @@ nsCacheService::OnProfileShutdown(PRBool cleanse)
gService->mDiskDevice->Shutdown();
gService->mEnableDiskDevice = PR_FALSE;
}
#endif // !NECKO_DISK_CACHE
#ifdef NECKO_OFFLINE_CACHE
if (gService->mOfflineDevice && gService->mEnableOfflineDevice) {
if (cleanse)
gService->mOfflineDevice->EvictEntries(nsnull);
@@ -1424,7 +1586,7 @@ nsCacheService::OnProfileShutdown(PRBool cleanse)
gService->mOfflineDevice->Shutdown();
gService->mEnableOfflineDevice = PR_FALSE;
}
#endif // !NECKO_DISK_CACHE
#endif // !NECKO_OFFLINE_CACHE
if (gService->mMemoryDevice) {
// clear memory cache
@@ -1458,7 +1620,9 @@ nsCacheService::OnProfileChanged()
// XXX delete mDiskDevice?
}
}
#endif // !NECKO_DISK_CACHE
#ifdef NECKO_OFFLINE_CACHE
if (gService->mOfflineDevice) {
gService->mOfflineDevice->SetCacheParentDirectory(gService->mObserver->OfflineCacheParentDirectory());
gService->mOfflineDevice->SetCapacity(gService->mObserver->OfflineCacheCapacity());
@@ -1471,7 +1635,7 @@ nsCacheService::OnProfileChanged()
// XXX delete mOfflineDevice?
}
}
#endif // !NECKO_DISK_CACHE
#endif // !NECKO_OFFLINE_CACHE
// If memoryDevice exists, reset its size to the new profile
if (gService->mMemoryDevice) {
@@ -1525,11 +1689,11 @@ nsCacheService::SetOfflineCacheCapacity(PRInt32 capacity)
if (!gService) return;
nsCacheServiceAutoLock lock;
#ifdef NECKO_DISK_CACHE
#ifdef NECKO_OFFLINE_CACHE
if (gService->mOfflineDevice) {
gService->mOfflineDevice->SetCapacity(capacity);
}
#endif // !NECKO_DISK_CACHE
#endif // !NECKO_OFFLINE_CACHE
gService->mEnableOfflineDevice = gService->mObserver->OfflineCacheEnabled();
}

View File

@@ -60,6 +60,7 @@ class nsCacheRequest;
class nsCacheProfilePrefObserver;
class nsDiskCacheDevice;
class nsMemoryCacheDevice;
class nsOfflineCacheDevice;
class nsCacheServiceAutoLock;
@@ -96,6 +97,40 @@ public:
static nsresult IsStorageEnabledForPolicy(nsCacheStoragePolicy storagePolicy,
PRBool * result);
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 EvictUnownedOfflineEntries(nsCacheSession * session);
/**
* Methods called by nsCacheEntryDescriptor
*/
@@ -248,7 +283,7 @@ private:
nsMemoryCacheDevice * mMemoryDevice;
nsDiskCacheDevice * mDiskDevice;
nsDiskCacheDevice * mOfflineDevice;
nsOfflineCacheDevice * mOfflineDevice;
nsCacheEntryHashTable mActiveEntries;
PRCList mDoomedEntries;

View File

@@ -42,9 +42,17 @@
#include "nsCacheSession.h"
#include "nsCacheService.h"
#include "nsCRT.h"
NS_IMPL_ADDREF(nsCacheSession)
NS_IMPL_RELEASE(nsCacheSession)
NS_IMPL_ISUPPORTS1(nsCacheSession, nsICacheSession)
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
nsCacheSession::nsCacheSession(const char * clientID,
nsCacheStoragePolicy storagePolicy,
@@ -128,3 +136,51 @@ NS_IMETHODIMP nsCacheSession::IsStorageEnabled(PRBool *result)
return nsCacheService::IsStorageEnabledForPolicy(StoragePolicy(), result);
}
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::EvictUnownedEntries()
{
return nsCacheService::EvictUnownedOfflineEntries(this);
}

View File

@@ -46,13 +46,16 @@
#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();

View File

@@ -180,7 +180,7 @@ NS_IMPL_ISUPPORTS1(nsDiskCacheDeviceInfo, nsICacheDeviceInfo)
NS_IMETHODIMP nsDiskCacheDeviceInfo::GetDescription(char ** aDescription)
{
NS_ENSURE_ARG_POINTER(aDescription);
*aDescription = nsCRT::strdup("Disk cache device");
*aDescription = NS_strdup("Disk cache device");
return *aDescription ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
@@ -929,43 +929,6 @@ nsDiskCacheDevice::SetCacheParentDirectory(nsILocalFile * parentDir)
mCacheDirectory = do_QueryInterface(directory);
}
// XXX: This is here to support the offline cache, and can be removed
// XXX: once it has its own cache implementation
void
nsDiskCacheDevice::SetCacheParentDirectoryAndName(nsILocalFile * parentDir,
const nsACString & str)
{
nsresult rv;
PRBool exists;
if (Initialized()) {
NS_ASSERTION(PR_FALSE, "Cannot switch cache directory when initialized");
return;
}
if (!parentDir) {
mCacheDirectory = nsnull;
return;
}
// ensure parent directory exists
rv = parentDir->Exists(&exists);
if (NS_SUCCEEDED(rv) && !exists)
rv = parentDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
if (NS_FAILED(rv)) return;
// ensure cache directory exists
nsCOMPtr<nsIFile> directory;
rv = parentDir->Clone(getter_AddRefs(directory));
if (NS_FAILED(rv)) return;
rv = directory->AppendNative(str);
if (NS_FAILED(rv)) return;
mCacheDirectory = do_QueryInterface(directory);
}
void
nsDiskCacheDevice::getCacheDirectory(nsILocalFile ** result)

View File

@@ -93,11 +93,6 @@ public:
void SetCacheParentDirectory(nsILocalFile * parentDir);
void SetCapacity(PRUint32 capacity);
// XXX: This is here to support the offline cache, and can be removed
// XXX: once it has its own cache implementation
void SetCacheParentDirectoryAndName(nsILocalFile * parentDir,
const nsACString & str);
/* private: */
void getCacheDirectory(nsILocalFile ** result);

File diff suppressed because it is too large Load Diff

View File

@@ -35,25 +35,26 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsDiskCacheDeviceSQL_h__
#define nsDiskCacheDeviceSQL_h__
#ifndef nsOfflineCacheDevice_h__
#define nsOfflineCacheDevice_h__
#include "nsCacheDevice.h"
#include "nsILocalFile.h"
#include "nsIObserver.h"
#include "mozIStorageConnection.h"
#include "nsCOMPtr.h"
#include "nsVoidArray.h"
class nsDiskCacheDevice : public nsCacheDevice
class nsOfflineCacheDevice : public nsCacheDevice
{
public:
nsDiskCacheDevice();
nsOfflineCacheDevice();
/**
* nsCacheDevice methods
*/
virtual ~nsDiskCacheDevice();
virtual ~nsOfflineCacheDevice();
virtual nsresult Init();
virtual nsresult Shutdown();
@@ -84,6 +85,36 @@ public:
virtual nsresult EvictEntries(const char * clientID);
/* Entry ownership */
nsresult SetOwnedKeys(const char * clientID,
const nsACString & ownerDomain,
const nsACString & ownerUrl,
PRUint32 count,
const char ** keys);
nsresult GetOwnedKeys(const char * clientID,
const nsACString & ownerDomain,
const nsACString & ownerUrl,
PRUint32 * count,
char *** keys);
nsresult AddOwnedKey(const char * clientID,
const nsACString & ownerDomain,
const nsACString & ownerURI,
const nsACString & key);
nsresult RemoveOwnedKey(const char * clientID,
const nsACString & ownerDomain,
const nsACString & ownerURI,
const nsACString & key);
nsresult KeyIsOwned(const char * clientID,
const nsACString & ownerDomain,
const nsACString & ownerURI,
const nsACString & key,
PRBool * isOwned);
nsresult ClearKeysOwnedByDomain(const char *clientID,
const nsACString &ownerDomain);
nsresult EvictUnownedEntries(const char *clientID);
/**
* Preference accessors
*/
@@ -96,10 +127,8 @@ public:
PRUint32 CacheSize();
PRUint32 EntryCount();
private:
private:
PRBool Initialized() { return mDB != nsnull; }
nsresult EvictDiskCacheEntries(PRUint32 targetCapacity);
nsresult UpdateEntry(nsCacheEntry *entry);
nsresult UpdateEntrySize(nsCacheEntry *entry, PRUint32 newSize);
nsresult DeleteEntry(nsCacheEntry *entry, PRBool deleteData);
@@ -107,23 +136,26 @@ private:
nsresult EnableEvictionObserver();
nsresult DisableEvictionObserver();
#if 0
// sqlite function for observing DELETE events
static void EvictionObserver(struct sqlite3_context *, int, struct Mem **);
#endif
nsCOMPtr<mozIStorageConnection> mDB;
nsCOMPtr<mozIStorageStatement> mStatement_CacheSize;
nsCOMPtr<mozIStorageStatement> mStatement_EntryCount;
nsCOMPtr<mozIStorageStatement> mStatement_UpdateEntry;
nsCOMPtr<mozIStorageStatement> mStatement_UpdateEntrySize;
nsCOMPtr<mozIStorageStatement> mStatement_UpdateEntryFlags;
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_DeleteUnowned;
nsCOMPtr<mozIStorageStatement> mStatement_ListOwned;
nsCOMPtr<nsILocalFile> mCacheDirectory;
PRUint32 mCacheCapacity; // XXX need soft/hard limits, currentTotal
PRUint32 mCacheCapacity;
PRInt32 mDeltaCounter;
};
#endif // nsDiskCacheDeviceSQL_h__
#endif // nsOfflineCacheDevice_h__

View File

@@ -143,7 +143,7 @@ extern const char DISK_CACHE_DEVICE_ID[];
NS_IMETHODIMP nsDiskCacheEntryInfo::GetDeviceID(char ** deviceID)
{
NS_ENSURE_ARG_POINTER(deviceID);
*deviceID = nsCRT::strdup(mDeviceID);
*deviceID = NS_strdup(mDeviceID);
return *deviceID ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}

View File

@@ -521,7 +521,7 @@ NS_IMETHODIMP
nsMemoryCacheDeviceInfo::GetDescription(char ** result)
{
NS_ENSURE_ARG_POINTER(result);
*result = nsCRT::strdup("Memory cache device");
*result = NS_strdup("Memory cache device");
if (!*result) return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}

View File

@@ -36,6 +36,9 @@
* ***** END LICENSE BLOCK ***** */
#include "nsPrefetchService.h"
#include "nsICacheSession.h"
#include "nsIOfflineCacheSession.h"
#include "nsICacheService.h"
#include "nsIServiceManager.h"
#include "nsICategoryManager.h"
#include "nsIObserverService.h"
@@ -72,9 +75,6 @@ static PRLogModuleInfo *gPrefetchLog;
#define LOG(args) PR_LOG(gPrefetchLog, 4, args)
#define LOG_ENABLED() PR_LOG_TEST(gPrefetchLog, 4)
static NS_DEFINE_IID(kDocLoaderServiceCID, NS_DOCUMENTLOADER_SERVICE_CID);
static NS_DEFINE_IID(kPrefServiceCID, NS_PREFSERVICE_CID);
#define PREFETCH_PREF "network.prefetch-next"
//-----------------------------------------------------------------------------
@@ -285,6 +285,7 @@ nsPrefetchService::nsPrefetchService()
, mQueueTail(nsnull)
, mStopCount(0)
, mDisabled(PR_TRUE)
, mFetchedOffline(PR_FALSE)
{
}
@@ -306,7 +307,7 @@ nsPrefetchService::Init()
nsresult rv;
// read prefs and hook up pref observer
nsCOMPtr<nsIPrefBranch2> prefs(do_GetService(kPrefServiceCID, &rv));
nsCOMPtr<nsIPrefBranch2> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
if (NS_SUCCEEDED(rv)) {
PRBool enabled;
rv = prefs->GetBoolPref(PREFETCH_PREF, &enabled);
@@ -345,6 +346,19 @@ nsPrefetchService::ProcessNextURI()
PRBool offline;
rv = DequeueURI(getter_AddRefs(uri), getter_AddRefs(referrer),
&offline);
if (rv == NS_ERROR_NOT_AVAILABLE && mFetchedOffline) {
// done loading stuff, go ahead and evict unowned entries from
// the offline cache
mFetchedOffline = PR_FALSE;
nsCOMPtr<nsIOfflineCacheSession> session;
rv = GetOfflineCacheSession(getter_AddRefs(session));
if (NS_FAILED(rv)) break;
session->EvictUnownedEntries();
break;
}
if (NS_FAILED(rv)) break;
#if defined(PR_LOGGING)
@@ -385,6 +399,8 @@ nsPrefetchService::ProcessNextURI()
continue;
}
}
mFetchedOffline = PR_TRUE;
}
rv = mCurrentChannel->AsyncOpen(listener, nsnull);
@@ -400,7 +416,8 @@ void
nsPrefetchService::AddProgressListener()
{
// Register as an observer for the document loader
nsCOMPtr<nsIWebProgress> progress(do_GetService(kDocLoaderServiceCID));
nsCOMPtr<nsIWebProgress> progress =
do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID);
if (progress)
progress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_DOCUMENT);
}
@@ -409,7 +426,8 @@ void
nsPrefetchService::RemoveProgressListener()
{
// Register as an observer for the document loader
nsCOMPtr<nsIWebProgress> progress(do_GetService(kDocLoaderServiceCID));
nsCOMPtr<nsIWebProgress> progress =
do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID);
if (progress)
progress->RemoveProgressListener(this);
}
@@ -480,6 +498,31 @@ nsPrefetchService::EmptyQueue(PRBool includeOffline)
}
}
nsresult
nsPrefetchService::GetOfflineCacheSession(nsIOfflineCacheSession **aSession)
{
if (!mOfflineCacheSession) {
nsresult 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);
mOfflineCacheSession = do_QueryInterface(session, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
NS_ADDREF(*aSession = mOfflineCacheSession);
return NS_OK;
}
void
nsPrefetchService::StartPrefetching()
{

View File

@@ -47,12 +47,14 @@
#include "nsIStreamListener.h"
#include "nsIChannel.h"
#include "nsIURI.h"
#include "nsIDOMDocument.h"
#include "nsWeakReference.h"
#include "nsCOMPtr.h"
class nsPrefetchService;
class nsPrefetchListener;
class nsPrefetchNode;
class nsIOfflineCacheSession;
//-----------------------------------------------------------------------------
// nsPrefetchService
@@ -88,14 +90,21 @@ private:
nsresult EnqueueURI(nsIURI *aURI, nsIURI *aReferrerURI, PRBool aOffline);
nsresult DequeueURI(nsIURI **aURI, nsIURI **aReferrerURI, PRBool *aOffline);
void EmptyQueue(PRBool includeOffline);
nsresult SaveOfflineList(nsIURI *aDocumentUri,
nsIDOMDocument *aDoc);
nsresult GetOfflineCacheSession(nsIOfflineCacheSession **aSession);
void StartPrefetching();
void StopPrefetching();
nsPrefetchNode *mQueueHead;
nsPrefetchNode *mQueueTail;
nsCOMPtr<nsIChannel> mCurrentChannel;
PRInt32 mStopCount;
PRBool mDisabled;
nsCOMPtr<nsIOfflineCacheSession> mOfflineCacheSession;
nsPrefetchNode *mQueueHead;
nsPrefetchNode *mQueueTail;
nsCOMPtr<nsIChannel> mCurrentChannel;
PRInt32 mStopCount;
PRBool mDisabled;
PRBool mFetchedOffline;
};
//-----------------------------------------------------------------------------