mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 916052 - Adapt about:cache to the HTTP cache v2 API, r=michal+MattN
This commit is contained in:
parent
56adb37c03
commit
f58519de04
@ -20,10 +20,11 @@ function test() {
|
||||
{
|
||||
info("disk storage contains " + num + " entries");
|
||||
},
|
||||
onCacheEntryInfo: function(entry)
|
||||
onCacheEntryInfo: function(uri)
|
||||
{
|
||||
info(entry.key);
|
||||
is(entry.key.contains(filename), false, "web content present in disk cache");
|
||||
var urispec = uri.asciiSpec;
|
||||
info(urispec);
|
||||
is(urispec.contains(filename), false, "web content present in disk cache");
|
||||
},
|
||||
onCacheEntryVisitCompleted: function()
|
||||
{
|
||||
|
@ -87,10 +87,11 @@ function getStorageEntryCount(device, goon) {
|
||||
entryCount: 0,
|
||||
onCacheStorageInfo: function (aEntryCount, aConsumption) {
|
||||
},
|
||||
onCacheEntryInfo: function(entry)
|
||||
onCacheEntryInfo: function(uri)
|
||||
{
|
||||
info(device + ":" + entry.key + "\n");
|
||||
if (entry.key.match(/^http:\/\/example.org\//))
|
||||
var urispec = uri.asciiSpec;
|
||||
info(device + ":" + urispec + "\n");
|
||||
if (urispec.match(/^http:\/\/example.org\//))
|
||||
++this.entryCount;
|
||||
},
|
||||
onCacheEntryVisitCompleted: function()
|
||||
|
@ -85,10 +85,11 @@ function checkDiskCacheFor(host, done)
|
||||
{
|
||||
info("disk storage contains " + num + " entries");
|
||||
},
|
||||
onCacheEntryInfo: function(entry)
|
||||
onCacheEntryInfo: function(uri)
|
||||
{
|
||||
info(entry.key);
|
||||
foundPrivateData |= entry.key.contains(host);
|
||||
var urispec = uri.asciiSpec;
|
||||
info(urispec);
|
||||
foundPrivateData |= urispec.contains(host);
|
||||
},
|
||||
onCacheEntryVisitCompleted: function()
|
||||
{
|
||||
|
@ -153,7 +153,18 @@ NS_IMETHODIMP AppCacheStorage::AsyncVisitStorage(nsICacheStorageVisitor* aVisito
|
||||
|
||||
LOG(("AppCacheStorage::AsyncVisitStorage [this=%p, cb=%p]", this, aVisitor));
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsICacheService> serv =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<_OldVisitCallbackWrapper> cb = new _OldVisitCallbackWrapper(
|
||||
"offline", aVisitor, aVisitEntries, LoadInfo());
|
||||
rv = serv->VisitEntries(cb);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // net
|
||||
|
@ -1165,6 +1165,13 @@ NS_IMETHODIMP CacheEntry::SetMetaDataElement(const char * aKey, const char * aVa
|
||||
return mFile->SetElement(aKey, aValue);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP CacheEntry::VisitMetaData(nsICacheEntryMetaDataVisitor *aVisitor)
|
||||
{
|
||||
NS_ENSURE_SUCCESS(mFileStatus, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
return mFile->VisitMetaData(aVisitor);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP CacheEntry::MetaDataReady()
|
||||
{
|
||||
mozilla::MutexAutoLock lock(mLock);
|
||||
@ -1467,7 +1474,7 @@ void CacheEntry::BackgroundOp(uint32_t aOperations, bool aForceAsync)
|
||||
#endif
|
||||
|
||||
// Half-life is dynamic, in seconds.
|
||||
static double half_life = CacheObserver::HalfLifeSeconds();
|
||||
static double half_life = CacheObserver::HalfLifeSeconds();
|
||||
// Must convert from seconds to milliseconds since PR_Now() gives usecs.
|
||||
static double const decay = (M_LN2 / half_life) / static_cast<double>(PR_USEC_PER_SEC);
|
||||
|
||||
|
@ -839,6 +839,17 @@ CacheFile::SetElement(const char *aKey, const char *aValue)
|
||||
return mMetadata->SetElement(aKey, aValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
CacheFile::VisitMetaData(nsICacheEntryMetaDataVisitor *aVisitor)
|
||||
{
|
||||
CacheFileAutoLock lock(this);
|
||||
MOZ_ASSERT(mMetadata);
|
||||
MOZ_ASSERT(mReady);
|
||||
NS_ENSURE_TRUE(mMetadata, NS_ERROR_UNEXPECTED);
|
||||
|
||||
return mMetadata->Visit(aVisitor);
|
||||
}
|
||||
|
||||
nsresult
|
||||
CacheFile::ElementsSize(uint32_t *_retval)
|
||||
{
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
class nsIInputStream;
|
||||
class nsIOutputStream;
|
||||
class nsICacheEntryMetaDataVisitor;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
@ -85,6 +86,7 @@ public:
|
||||
// metadata forwarders
|
||||
nsresult GetElement(const char *aKey, char **_retval);
|
||||
nsresult SetElement(const char *aKey, const char *aValue);
|
||||
nsresult VisitMetaData(nsICacheEntryMetaDataVisitor *aVisitor);
|
||||
nsresult ElementsSize(uint32_t *_retval);
|
||||
nsresult SetExpirationTime(uint32_t aExpirationTime);
|
||||
nsresult GetExpirationTime(uint32_t *_retval);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIDirectoryEnumerator.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsICacheStorageVisitor.h"
|
||||
#include "nsISizeOf.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
@ -28,6 +29,7 @@
|
||||
#include "private/pprio.h"
|
||||
#include "mozilla/VisualEventTracer.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
// include files for ftruncate (or equivalent)
|
||||
#if defined(XP_UNIX)
|
||||
@ -2212,6 +2214,92 @@ void CacheFileIOManager::GetCacheDirectory(nsIFile** result)
|
||||
file.forget(result);
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
CacheFileIOManager::GetEntryInfo(const SHA1Sum::Hash *aHash,
|
||||
CacheStorageService::EntryInfoCallback *aCallback)
|
||||
{
|
||||
MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
if (!ioMan) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
nsAutoCString enhanceId;
|
||||
nsAutoCString uriSpec;
|
||||
|
||||
nsRefPtr<CacheFileHandle> handle;
|
||||
ioMan->mHandles.GetHandle(aHash, false, getter_AddRefs(handle));
|
||||
if (handle) {
|
||||
nsRefPtr<nsILoadContextInfo> info =
|
||||
CacheFileUtils::ParseKey(handle->Key(), &enhanceId, &uriSpec);
|
||||
|
||||
MOZ_ASSERT(info);
|
||||
if (!info) {
|
||||
return NS_OK; // ignore
|
||||
}
|
||||
|
||||
nsRefPtr<CacheStorageService> service = CacheStorageService::Self();
|
||||
if (!service) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
// Invokes OnCacheEntryInfo when an existing entry is found
|
||||
if (service->GetCacheEntryInfo(info, enhanceId, uriSpec, aCallback)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// When we are here, there is no existing entry and we need
|
||||
// to synchrnously load metadata from a disk file.
|
||||
}
|
||||
|
||||
// Locate the actual file
|
||||
nsCOMPtr<nsIFile> file;
|
||||
ioMan->GetFile(aHash, getter_AddRefs(file));
|
||||
|
||||
// Read metadata from the file synchronously
|
||||
nsRefPtr<CacheFileMetadata> metadata = new CacheFileMetadata();
|
||||
rv = metadata->SyncReadMetadata(file);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Now get the context + enhance id + URL from the key.
|
||||
nsAutoCString key;
|
||||
metadata->GetKey(key);
|
||||
|
||||
nsRefPtr<nsILoadContextInfo> info =
|
||||
CacheFileUtils::ParseKey(key, &enhanceId, &uriSpec);
|
||||
MOZ_ASSERT(info);
|
||||
if (!info) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Pick all data to pass to the callback.
|
||||
int64_t dataSize = metadata->Offset();
|
||||
uint32_t fetchCount;
|
||||
if (NS_FAILED(metadata->GetFetchCount(&fetchCount))) {
|
||||
fetchCount = 0;
|
||||
}
|
||||
uint32_t expirationTime;
|
||||
if (NS_FAILED(metadata->GetExpirationTime(&expirationTime))) {
|
||||
expirationTime = 0;
|
||||
}
|
||||
uint32_t lastModified;
|
||||
if (NS_FAILED(metadata->GetLastModified(&lastModified))) {
|
||||
lastModified = 0;
|
||||
}
|
||||
|
||||
// Call directly on the callback.
|
||||
aCallback->OnEntryInfo(uriSpec, enhanceId, dataSize, fetchCount,
|
||||
lastModified, expirationTime);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
TruncFile(PRFileDesc *aFD, uint32_t aEOF)
|
||||
{
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define CacheFileIOManager__h__
|
||||
|
||||
#include "CacheIOThread.h"
|
||||
#include "CacheStorageService.h"
|
||||
#include "nsIEventTarget.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsCOMPtr.h"
|
||||
@ -22,6 +23,7 @@ class nsIFile;
|
||||
class nsITimer;
|
||||
class nsIDirectoryEnumerator;
|
||||
class nsILoadContextInfo;
|
||||
class nsICacheStorageVisitor;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
@ -278,6 +280,13 @@ public:
|
||||
|
||||
static void GetCacheDirectory(nsIFile** result);
|
||||
|
||||
// Calls synchronously OnEntryInfo for an entry with the given hash.
|
||||
// Tries to find an existing entry in the service hashtables first, if not
|
||||
// found, loads synchronously from disk file.
|
||||
// Callable on the IO thread only.
|
||||
static nsresult GetEntryInfo(const SHA1Sum::Hash *aHash,
|
||||
CacheStorageService::EntryInfoCallback *aCallback);
|
||||
|
||||
// Memory reporting
|
||||
static size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||
static size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "CacheFileChunk.h"
|
||||
#include "CacheFileUtils.h"
|
||||
#include "nsILoadContextInfo.h"
|
||||
#include "nsICacheEntry.h" // for nsICacheEntryMetaDataVisitor
|
||||
#include "../cache/nsCacheUtils.h"
|
||||
#include "nsIFile.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
@ -304,7 +305,10 @@ CacheFileMetadata::SyncReadMetadata(nsIFile *aFile)
|
||||
|
||||
int64_t fileSize;
|
||||
rv = aFile->GetFileSize(&fileSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Don't bloat the console
|
||||
return rv;
|
||||
}
|
||||
|
||||
PRFileDesc *fd;
|
||||
rv = aFile->OpenNSPRFileDesc(PR_RDONLY, 0600, &fd);
|
||||
@ -433,6 +437,28 @@ CacheFileMetadata::SetElement(const char *aKey, const char *aValue)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CacheFileMetadata::Visit(nsICacheEntryMetaDataVisitor *aVisitor)
|
||||
{
|
||||
const char *data = mBuf;
|
||||
const char *limit = mBuf + mElementsSize;
|
||||
|
||||
while (data < limit) {
|
||||
// Point to the value part
|
||||
const char *value = data + strlen(data) + 1;
|
||||
MOZ_ASSERT(value < limit, "Metadata elements corrupted");
|
||||
|
||||
aVisitor->OnMetaDataElement(data, value);
|
||||
|
||||
// Skip value part
|
||||
data = value + strlen(value) + 1;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(data == limit, "Metadata elements corrupted");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
CacheHash::Hash16_t
|
||||
CacheFileMetadata::GetHash(uint32_t aIndex)
|
||||
{
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsICacheEntryMetaDataVisitor;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
@ -22,7 +24,7 @@ namespace net {
|
||||
// the frecency value to a correct internal representation again.
|
||||
// It might not be 100% accurate, but for the purpose it suffice.
|
||||
#define FRECENCY2INT(aFrecency) \
|
||||
((uint32_t)(aFrecency * CacheObserver::HalfLifeSeconds()))
|
||||
((uint32_t)((aFrecency) * CacheObserver::HalfLifeSeconds()))
|
||||
#define INT2FRECENCY(aInt) \
|
||||
((double)(aInt) / (double)CacheObserver::HalfLifeSeconds())
|
||||
|
||||
@ -129,6 +131,7 @@ public:
|
||||
|
||||
const char * GetElement(const char *aKey);
|
||||
nsresult SetElement(const char *aKey, const char *aValue);
|
||||
nsresult Visit(nsICacheEntryMetaDataVisitor *aVisitor);
|
||||
|
||||
CacheHash::Hash16_t GetHash(uint32_t aIndex);
|
||||
nsresult SetHash(uint32_t aIndex, CacheHash::Hash16_t aHash);
|
||||
|
@ -1205,6 +1205,43 @@ CacheIndex::GetCacheSize(uint32_t *_retval)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
CacheIndex::GetCacheStats(nsILoadContextInfo *aInfo, uint32_t *aSize, uint32_t *aCount)
|
||||
{
|
||||
LOG(("CacheIndex::GetCacheStats() [info=%p]", aInfo));
|
||||
|
||||
nsRefPtr<CacheIndex> index = gInstance;
|
||||
|
||||
if (!index) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
CacheIndexAutoLock lock(index);
|
||||
|
||||
if (!index->IsIndexUsable()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (!aInfo) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
*aSize = 0;
|
||||
*aCount = 0;
|
||||
|
||||
for (uint32_t i = 0; i < index->mFrecencyArray.Length(); ++i) {
|
||||
CacheIndexRecord* record = index->mFrecencyArray[i];
|
||||
if (!CacheIndexEntry::RecordMatchesLoadContextInfo(record, aInfo))
|
||||
continue;
|
||||
|
||||
*aSize += CacheIndexEntry::GetFileSize(record);
|
||||
++*aCount;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
CacheIndex::AsyncGetDiskConsumption(nsICacheStorageConsumptionObserver* aObserver)
|
||||
|
@ -205,7 +205,11 @@ public:
|
||||
mRec->mFlags |= aFileSize;
|
||||
}
|
||||
// Returns filesize in kilobytes.
|
||||
uint32_t GetFileSize() { return mRec->mFlags & kFileSizeMask; }
|
||||
uint32_t GetFileSize() { return GetFileSize(mRec); }
|
||||
static uint32_t GetFileSize(CacheIndexRecord *aRec)
|
||||
{
|
||||
return aRec->mFlags & kFileSizeMask;
|
||||
}
|
||||
bool IsFileEmpty() { return GetFileSize() == 0; }
|
||||
|
||||
void WriteToBuf(void *aBuf)
|
||||
@ -563,6 +567,10 @@ public:
|
||||
// Returns cache size in kB.
|
||||
static nsresult GetCacheSize(uint32_t *_retval);
|
||||
|
||||
// Synchronously returns the disk occupation and number of entries per-context.
|
||||
// Callable on any thread.
|
||||
static nsresult GetCacheStats(nsILoadContextInfo *aInfo, uint32_t *aSize, uint32_t *aCount);
|
||||
|
||||
// Asynchronously gets the disk cache size, used for display in the UI.
|
||||
static nsresult AsyncGetDiskConsumption(nsICacheStorageConsumptionObserver* aObserver);
|
||||
|
||||
|
@ -2,8 +2,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef CacheLog__h__
|
||||
#define CacheLog__h__
|
||||
#ifndef Cache2Log__h__
|
||||
#define Cache2Log__h__
|
||||
|
||||
#if defined(MOZ_LOGGING)
|
||||
#define FORCE_PR_LOG
|
||||
|
@ -7,9 +7,7 @@
|
||||
#include "CacheFileIOManager.h"
|
||||
#include "CacheObserver.h"
|
||||
#include "CacheIndex.h"
|
||||
|
||||
#include "nsICacheStorageVisitor.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "CacheIndexIterator.h"
|
||||
#include "CacheStorage.h"
|
||||
#include "AppCacheStorage.h"
|
||||
#include "CacheEntry.h"
|
||||
@ -19,12 +17,16 @@
|
||||
#include "nsCacheService.h"
|
||||
#include "nsDeleteDir.h"
|
||||
|
||||
#include "nsICacheStorageVisitor.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/VisualEventTracer.h"
|
||||
@ -163,35 +165,57 @@ void CacheStorageService::ShutdownBackground()
|
||||
|
||||
namespace { // anon
|
||||
|
||||
// WalkRunnable
|
||||
// Responsible to visit the storage and walk all entries on it asynchronously
|
||||
|
||||
class WalkRunnable : public nsRunnable
|
||||
// WalkCacheRunnable
|
||||
// Base class for particular storage entries visiting
|
||||
class WalkCacheRunnable : public nsRunnable
|
||||
, public CacheStorageService::EntryInfoCallback
|
||||
{
|
||||
public:
|
||||
WalkRunnable(nsCSubstring const & aContextKey, bool aVisitEntries,
|
||||
bool aUsingDisk,
|
||||
nsICacheStorageVisitor* aVisitor)
|
||||
: mContextKey(aContextKey)
|
||||
protected:
|
||||
WalkCacheRunnable(nsICacheStorageVisitor* aVisitor,
|
||||
bool aVisitEntries)
|
||||
: mService(CacheStorageService::Self())
|
||||
, mCallback(aVisitor)
|
||||
, mSize(0)
|
||||
, mNotifyStorage(true)
|
||||
, mVisitEntries(aVisitEntries)
|
||||
, mUsingDisk(aUsingDisk)
|
||||
{
|
||||
}
|
||||
|
||||
nsRefPtr<CacheStorageService> mService;
|
||||
nsCOMPtr<nsICacheStorageVisitor> mCallback;
|
||||
|
||||
uint64_t mSize;
|
||||
|
||||
bool mNotifyStorage : 1;
|
||||
bool mVisitEntries : 1;
|
||||
};
|
||||
|
||||
// WalkMemoryCacheRunnable
|
||||
// Responsible to visit memory storage and walk
|
||||
// all entries on it asynchronously.
|
||||
class WalkMemoryCacheRunnable : public WalkCacheRunnable
|
||||
{
|
||||
public:
|
||||
WalkMemoryCacheRunnable(nsILoadContextInfo *aLoadInfo,
|
||||
bool aVisitEntries,
|
||||
nsICacheStorageVisitor* aVisitor)
|
||||
: WalkCacheRunnable(aVisitor, aVisitEntries)
|
||||
{
|
||||
CacheFileUtils::AppendKeyPrefix(aLoadInfo, mContextKey);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
nsresult Walk()
|
||||
{
|
||||
return mService->Dispatch(this);
|
||||
}
|
||||
|
||||
private:
|
||||
NS_IMETHODIMP Run()
|
||||
{
|
||||
if (CacheStorageService::IsOnManagementThread()) {
|
||||
LOG(("WalkRunnable::Run - collecting [this=%p, disk=%d]", this, (bool)mUsingDisk));
|
||||
LOG(("WalkMemoryCacheRunnable::Run - collecting [this=%p]", this));
|
||||
// First, walk, count and grab all entries from the storage
|
||||
// TODO
|
||||
// - walk files on disk, when the storage is not private
|
||||
// - should create representative entries only for the time
|
||||
// of need
|
||||
|
||||
mozilla::MutexAutoLock lock(CacheStorageService::Self()->Lock());
|
||||
|
||||
@ -200,37 +224,42 @@ private:
|
||||
|
||||
CacheEntryTable* entries;
|
||||
if (sGlobalEntryTables->Get(mContextKey, &entries))
|
||||
entries->EnumerateRead(&WalkRunnable::WalkStorage, this);
|
||||
entries->EnumerateRead(&WalkMemoryCacheRunnable::WalkStorage, this);
|
||||
|
||||
// Next, we dispatch to the main thread
|
||||
}
|
||||
else if (NS_IsMainThread()) {
|
||||
LOG(("WalkRunnable::Run - notifying [this=%p, disk=%d]", this, (bool)mUsingDisk));
|
||||
} else if (NS_IsMainThread()) {
|
||||
LOG(("WalkMemoryCacheRunnable::Run - notifying [this=%p]", this));
|
||||
|
||||
if (mNotifyStorage) {
|
||||
LOG((" storage"));
|
||||
|
||||
// Second, notify overall storage info
|
||||
mCallback->OnCacheStorageInfo(mEntryArray.Length(), mSize);
|
||||
mCallback->OnCacheStorageInfo(mEntryArray.Length(), mSize,
|
||||
CacheObserver::MemoryCacheCapacity(), nullptr);
|
||||
if (!mVisitEntries)
|
||||
return NS_OK; // done
|
||||
|
||||
mNotifyStorage = false;
|
||||
}
|
||||
else {
|
||||
|
||||
} else {
|
||||
LOG((" entry [left=%d]", mEntryArray.Length()));
|
||||
// Third, notify each entry until depleted.
|
||||
|
||||
// Third, notify each entry until depleted
|
||||
if (!mEntryArray.Length()) {
|
||||
mCallback->OnCacheEntryVisitCompleted();
|
||||
return NS_OK; // done
|
||||
}
|
||||
|
||||
mCallback->OnCacheEntryInfo(mEntryArray[0]);
|
||||
// Grab the next entry
|
||||
nsRefPtr<CacheEntry> entry = mEntryArray[0];
|
||||
mEntryArray.RemoveElementAt(0);
|
||||
|
||||
// Dispatch to the main thread again
|
||||
// Invokes this->OnEntryInfo, that calls the callback with all
|
||||
// information of the entry.
|
||||
CacheStorageService::GetCacheEntryInfo(entry, this);
|
||||
}
|
||||
}
|
||||
else {
|
||||
MOZ_ASSERT(false);
|
||||
} else {
|
||||
MOZ_CRASH("Bad thread");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -238,7 +267,7 @@ private:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
virtual ~WalkRunnable()
|
||||
virtual ~WalkMemoryCacheRunnable()
|
||||
{
|
||||
if (mCallback)
|
||||
ProxyReleaseMainThread(mCallback);
|
||||
@ -249,9 +278,11 @@ private:
|
||||
CacheEntry* aEntry,
|
||||
void* aClosure)
|
||||
{
|
||||
WalkRunnable* walker = static_cast<WalkRunnable*>(aClosure);
|
||||
WalkMemoryCacheRunnable* walker =
|
||||
static_cast<WalkMemoryCacheRunnable*>(aClosure);
|
||||
|
||||
if (!walker->mUsingDisk && aEntry->IsUsingDiskLocked())
|
||||
// Ignore disk entries
|
||||
if (aEntry->IsUsingDiskLocked())
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
walker->mSize += aEntry->GetMetadataMemoryConsumption();
|
||||
@ -264,15 +295,196 @@ private:
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
virtual void OnEntryInfo(const nsACString & aURISpec, const nsACString & aIdEnhance,
|
||||
int64_t aDataSize, int32_t aFetchCount,
|
||||
uint32_t aLastModifiedTime, uint32_t aExpirationTime)
|
||||
{
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), aURISpec);
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
mCallback->OnCacheEntryInfo(uri, aIdEnhance, aDataSize, aFetchCount,
|
||||
aLastModifiedTime, aExpirationTime);
|
||||
}
|
||||
|
||||
private:
|
||||
nsCString mContextKey;
|
||||
nsCOMPtr<nsICacheStorageVisitor> mCallback;
|
||||
nsTArray<nsRefPtr<CacheEntry> > mEntryArray;
|
||||
};
|
||||
|
||||
uint64_t mSize;
|
||||
// WalkDiskCacheRunnable
|
||||
// Using the cache index information to get the list of files per context.
|
||||
class WalkDiskCacheRunnable : public WalkCacheRunnable
|
||||
{
|
||||
public:
|
||||
WalkDiskCacheRunnable(nsILoadContextInfo *aLoadInfo,
|
||||
bool aVisitEntries,
|
||||
nsICacheStorageVisitor* aVisitor)
|
||||
: WalkCacheRunnable(aVisitor, aVisitEntries)
|
||||
, mLoadInfo(aLoadInfo)
|
||||
, mPass(COLLECT_STATS)
|
||||
{
|
||||
}
|
||||
|
||||
bool mNotifyStorage : 1;
|
||||
bool mVisitEntries : 1;
|
||||
bool mUsingDisk : 1;
|
||||
nsresult Walk()
|
||||
{
|
||||
// TODO, bug 998693
|
||||
// Initial index build should be forced here so that about:cache soon
|
||||
// after startup gives some meaningfull results.
|
||||
|
||||
// Dispatch to the INDEX level in hope that very recent cache entries
|
||||
// information gets to the index list before we grab the index iterator
|
||||
// for the first time. This tries to avoid miss of entries that has
|
||||
// been created right before the visit is required.
|
||||
nsRefPtr<CacheIOThread> thread = CacheFileIOManager::IOThread();
|
||||
NS_ENSURE_TRUE(thread, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
return thread->Dispatch(this, CacheIOThread::INDEX);
|
||||
}
|
||||
|
||||
private:
|
||||
// Invokes OnCacheEntryInfo callback for each single found entry.
|
||||
// There is one instance of this class per one entry.
|
||||
class OnCacheEntryInfoRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
OnCacheEntryInfoRunnable(WalkDiskCacheRunnable* aWalker)
|
||||
: mWalker(aWalker)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), mURISpec);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_OK;
|
||||
|
||||
mWalker->mCallback->OnCacheEntryInfo(
|
||||
uri, mIdEnhance, mDataSize, mFetchCount,
|
||||
mLastModifiedTime, mExpirationTime);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<WalkDiskCacheRunnable> mWalker;
|
||||
|
||||
nsCString mURISpec;
|
||||
nsCString mIdEnhance;
|
||||
int64_t mDataSize;
|
||||
int32_t mFetchCount;
|
||||
uint32_t mLastModifiedTime;
|
||||
uint32_t mExpirationTime;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP Run()
|
||||
{
|
||||
// The main loop
|
||||
nsresult rv;
|
||||
|
||||
if (CacheStorageService::IsOnManagementThread()) {
|
||||
switch (mPass) {
|
||||
case COLLECT_STATS:
|
||||
// Get quickly the cache stats.
|
||||
uint32_t size;
|
||||
rv = CacheIndex::GetCacheStats(mLoadInfo, &size, &mCount);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (mVisitEntries) {
|
||||
// both onStorageInfo and onCompleted are expected
|
||||
NS_DispatchToMainThread(this);
|
||||
}
|
||||
return NS_DispatchToMainThread(this);
|
||||
}
|
||||
|
||||
mSize = size << 10;
|
||||
|
||||
// Invoke onCacheStorageInfo with valid information.
|
||||
NS_DispatchToMainThread(this);
|
||||
|
||||
if (!mVisitEntries) {
|
||||
return NS_OK; // done
|
||||
}
|
||||
|
||||
mPass = ITERATE_METADATA;
|
||||
// no break
|
||||
|
||||
case ITERATE_METADATA:
|
||||
// Now grab the context iterator.
|
||||
if (!mIter) {
|
||||
rv = CacheIndex::GetIterator(mLoadInfo, true, getter_AddRefs(mIter));
|
||||
if (NS_FAILED(rv)) {
|
||||
// Invoke onCacheEntryVisitCompleted now
|
||||
return NS_DispatchToMainThread(this);
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (CacheIOThread::YieldAndRerun())
|
||||
return NS_OK;
|
||||
|
||||
SHA1Sum::Hash hash;
|
||||
rv = mIter->GetNextHash(&hash);
|
||||
if (NS_FAILED(rv))
|
||||
break; // done (or error?)
|
||||
|
||||
// This synchronously invokes onCacheEntryInfo on this class where we
|
||||
// redispatch to the main thread for the consumer callback.
|
||||
CacheFileIOManager::GetEntryInfo(&hash, this);
|
||||
}
|
||||
|
||||
// Invoke onCacheEntryVisitCompleted on the main thread
|
||||
NS_DispatchToMainThread(this);
|
||||
}
|
||||
} else if (NS_IsMainThread()) {
|
||||
if (mNotifyStorage) {
|
||||
nsCOMPtr<nsIFile> dir;
|
||||
CacheFileIOManager::GetCacheDirectory(getter_AddRefs(dir));
|
||||
mCallback->OnCacheStorageInfo(mCount, mSize, CacheObserver::DiskCacheCapacity(), dir);
|
||||
mNotifyStorage = false;
|
||||
} else {
|
||||
mCallback->OnCacheEntryVisitCompleted();
|
||||
}
|
||||
} else {
|
||||
MOZ_CRASH("Bad thread");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
virtual void OnEntryInfo(const nsACString & aURISpec, const nsACString & aIdEnhance,
|
||||
int64_t aDataSize, int32_t aFetchCount,
|
||||
uint32_t aLastModifiedTime, uint32_t aExpirationTime)
|
||||
{
|
||||
// Called directly from CacheFileIOManager::GetEntryInfo.
|
||||
|
||||
// Invoke onCacheEntryInfo on the main thread for this entry.
|
||||
nsRefPtr<OnCacheEntryInfoRunnable> info = new OnCacheEntryInfoRunnable(this);
|
||||
info->mURISpec = aURISpec;
|
||||
info->mIdEnhance = aIdEnhance;
|
||||
info->mDataSize = aDataSize;
|
||||
info->mFetchCount = aFetchCount;
|
||||
info->mLastModifiedTime = aLastModifiedTime;
|
||||
info->mExpirationTime = aExpirationTime;
|
||||
|
||||
NS_DispatchToMainThread(info);
|
||||
}
|
||||
|
||||
nsRefPtr<nsILoadContextInfo> mLoadInfo;
|
||||
enum {
|
||||
// First, we collect stats for the load context.
|
||||
COLLECT_STATS,
|
||||
|
||||
// Second, if demanded, we iterate over the entries gethered
|
||||
// from the iterator and call CacheFileIOManager::GetEntryInfo
|
||||
// for each found entry.
|
||||
ITERATE_METADATA,
|
||||
} mPass;
|
||||
|
||||
nsRefPtr<CacheIndexIterator> mIter;
|
||||
uint32_t mCount;
|
||||
};
|
||||
|
||||
PLDHashOperator CollectPrivateContexts(const nsACString& aKey,
|
||||
@ -1264,12 +1476,15 @@ CacheStorageService::WalkStorageEntries(CacheStorage const* aStorage,
|
||||
|
||||
NS_ENSURE_ARG(aStorage);
|
||||
|
||||
nsAutoCString contextKey;
|
||||
CacheFileUtils::AppendKeyPrefix(aStorage->LoadInfo(), contextKey);
|
||||
if (aStorage->WriteToDisk()) {
|
||||
nsRefPtr<WalkDiskCacheRunnable> event =
|
||||
new WalkDiskCacheRunnable(aStorage->LoadInfo(), aVisitEntries, aVisitor);
|
||||
return event->Walk();
|
||||
}
|
||||
|
||||
nsRefPtr<WalkRunnable> event = new WalkRunnable(
|
||||
contextKey, aVisitEntries, aStorage->WriteToDisk(), aVisitor);
|
||||
return Dispatch(event);
|
||||
nsRefPtr<WalkMemoryCacheRunnable> event =
|
||||
new WalkMemoryCacheRunnable(aStorage->LoadInfo(), aVisitEntries, aVisitor);
|
||||
return event->Walk();
|
||||
}
|
||||
|
||||
void
|
||||
@ -1308,6 +1523,73 @@ CacheStorageService::CacheFileDoomed(nsILoadContextInfo* aLoadContextInfo,
|
||||
entry->DoomAlreadyRemoved();
|
||||
}
|
||||
|
||||
bool
|
||||
CacheStorageService::GetCacheEntryInfo(nsILoadContextInfo* aLoadContextInfo,
|
||||
const nsACString & aIdExtension,
|
||||
const nsACString & aURISpec,
|
||||
EntryInfoCallback *aCallback)
|
||||
{
|
||||
nsAutoCString contextKey;
|
||||
CacheFileUtils::AppendKeyPrefix(aLoadContextInfo, contextKey);
|
||||
|
||||
nsAutoCString entryKey;
|
||||
CacheEntry::HashingKey(EmptyCString(), aIdExtension, aURISpec, entryKey);
|
||||
|
||||
nsRefPtr<CacheEntry> entry;
|
||||
{
|
||||
mozilla::MutexAutoLock lock(mLock);
|
||||
|
||||
if (mShutdown) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CacheEntryTable* entries;
|
||||
if (!sGlobalEntryTables->Get(contextKey, &entries)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!entries->Get(entryKey, getter_AddRefs(entry))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
GetCacheEntryInfo(entry, aCallback);
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
CacheStorageService::GetCacheEntryInfo(CacheEntry* aEntry,
|
||||
EntryInfoCallback *aCallback)
|
||||
{
|
||||
nsIURI* uri = aEntry->GetURI();
|
||||
nsAutoCString uriSpec;
|
||||
if (uri) {
|
||||
uri->GetAsciiSpec(uriSpec);
|
||||
}
|
||||
|
||||
nsCString const enhanceId = aEntry->GetEnhanceID();
|
||||
uint32_t dataSize;
|
||||
if (NS_FAILED(aEntry->GetStorageDataSize(&dataSize))) {
|
||||
dataSize = 0;
|
||||
}
|
||||
int32_t fetchCount;
|
||||
if (NS_FAILED(aEntry->GetFetchCount(&fetchCount))) {
|
||||
fetchCount = 0;
|
||||
}
|
||||
uint32_t lastModified;
|
||||
if (NS_FAILED(aEntry->GetLastModified(&lastModified))) {
|
||||
lastModified = 0;
|
||||
}
|
||||
uint32_t expirationTime;
|
||||
if (NS_FAILED(aEntry->GetExpirationTime(&expirationTime))) {
|
||||
expirationTime = 0;
|
||||
}
|
||||
|
||||
aCallback->OnEntryInfo(uriSpec, enhanceId, dataSize,
|
||||
fetchCount, lastModified, expirationTime);
|
||||
}
|
||||
|
||||
// nsIMemoryReporter
|
||||
|
||||
size_t
|
||||
|
@ -88,6 +88,19 @@ public:
|
||||
already_AddRefed<nsIEventTarget> Thread() const;
|
||||
mozilla::Mutex& Lock() { return mLock; }
|
||||
|
||||
// Helper thread-safe interface to pass entry info, only difference from
|
||||
// nsICacheStorageVisitor is that instead of nsIURI only the uri spec is
|
||||
// passed.
|
||||
class EntryInfoCallback {
|
||||
public:
|
||||
virtual void OnEntryInfo(const nsACString & aURISpec, const nsACString & aIdEnhance,
|
||||
int64_t aDataSize, int32_t aFetchCount,
|
||||
uint32_t aLastModifiedTime, uint32_t aExpirationTime) = 0;
|
||||
};
|
||||
|
||||
// Invokes OnEntryInfo for the given aEntry, synchronously.
|
||||
static void GetCacheEntryInfo(CacheEntry* aEntry, EntryInfoCallback *aVisitor);
|
||||
|
||||
// Memory reporting
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
@ -179,6 +192,19 @@ private:
|
||||
const nsACString & aIdExtension,
|
||||
const nsACString & aURISpec);
|
||||
|
||||
/**
|
||||
* Tries to find an existing entry in the hashtables and synchronously call
|
||||
* OnCacheEntryInfo of the aVisitor callback when found.
|
||||
* @retuns
|
||||
* true, when the entry has been found that also implies the callbacks has
|
||||
* beem invoked
|
||||
* false, when an entry has not been found
|
||||
*/
|
||||
bool GetCacheEntryInfo(nsILoadContextInfo* aLoadContextInfo,
|
||||
const nsACString & aIdExtension,
|
||||
const nsACString & aURISpec,
|
||||
EntryInfoCallback *aCallback);
|
||||
|
||||
private:
|
||||
friend class CacheMemoryConsumer;
|
||||
|
||||
|
@ -5,9 +5,9 @@
|
||||
#include "CacheStorage.h"
|
||||
#include "CacheStorageService.h"
|
||||
#include "LoadContextInfo.h"
|
||||
#include "nsCacheService.h"
|
||||
|
||||
#include "nsIURI.h"
|
||||
#include "nsICacheService.h"
|
||||
#include "nsICacheSession.h"
|
||||
#include "nsIApplicationCache.h"
|
||||
#include "nsIApplicationCacheService.h"
|
||||
@ -19,6 +19,7 @@
|
||||
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
|
||||
@ -124,43 +125,31 @@ NS_IMETHODIMP DoomCallbackWrapper::OnCacheEntryDoomed(nsresult status)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // anon
|
||||
|
||||
// _OldVisitCallbackWrapper
|
||||
// Receives visit callbacks from the old API and forwards it to the new API
|
||||
|
||||
class VisitCallbackWrapper : public nsICacheVisitor
|
||||
{
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSICACHEVISITOR
|
||||
NS_IMPL_ISUPPORTS(_OldVisitCallbackWrapper, nsICacheVisitor)
|
||||
|
||||
VisitCallbackWrapper(char* const deviceID,
|
||||
nsICacheStorageVisitor* cb,
|
||||
bool visitEntries)
|
||||
: mCB(cb)
|
||||
, mVisitEntries(visitEntries)
|
||||
, mDeviceID(deviceID)
|
||||
{
|
||||
MOZ_COUNT_CTOR(VisitCallbackWrapper);
|
||||
_OldVisitCallbackWrapper::~_OldVisitCallbackWrapper()
|
||||
{
|
||||
if (!mHit) {
|
||||
// The device has not been found, to not break the chain, simulate
|
||||
// storage info callback.
|
||||
mCB->OnCacheStorageInfo(0, 0, 0, nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~VisitCallbackWrapper();
|
||||
nsCOMPtr<nsICacheStorageVisitor> mCB;
|
||||
bool mVisitEntries;
|
||||
char* const mDeviceID;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(VisitCallbackWrapper, nsICacheVisitor)
|
||||
|
||||
VisitCallbackWrapper::~VisitCallbackWrapper()
|
||||
{
|
||||
if (mVisitEntries)
|
||||
if (mVisitEntries) {
|
||||
mCB->OnCacheEntryVisitCompleted();
|
||||
}
|
||||
|
||||
MOZ_COUNT_DTOR(VisitCallbackWrapper);
|
||||
MOZ_COUNT_DTOR(_OldVisitCallbackWrapper);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP VisitCallbackWrapper::VisitDevice(const char * deviceID,
|
||||
nsICacheDeviceInfo *deviceInfo,
|
||||
bool *_retval)
|
||||
NS_IMETHODIMP _OldVisitCallbackWrapper::VisitDevice(const char * deviceID,
|
||||
nsICacheDeviceInfo *deviceInfo,
|
||||
bool *_retval)
|
||||
{
|
||||
if (!mCB)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
@ -171,38 +160,120 @@ NS_IMETHODIMP VisitCallbackWrapper::VisitDevice(const char * deviceID,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mHit = true;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
uint32_t entryCount;
|
||||
rv = deviceInfo->GetEntryCount(&entryCount);
|
||||
uint32_t capacity;
|
||||
rv = deviceInfo->GetMaximumSize(&capacity);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t totalSize;
|
||||
rv = deviceInfo->GetTotalSize(&totalSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIFile> dir;
|
||||
if (!strcmp(mDeviceID, "disk")) {
|
||||
nsCacheService::GetDiskCacheDirectory(getter_AddRefs(dir));
|
||||
} else if (!strcmp(mDeviceID, "offline")) {
|
||||
nsCacheService::GetAppCacheDirectory(getter_AddRefs(dir));
|
||||
}
|
||||
|
||||
if (mLoadInfo->IsAnonymous()) {
|
||||
// Anonymous visiting reports 0, 0 since we cannot count that
|
||||
// early the number of anon entries.
|
||||
mCB->OnCacheStorageInfo(0, 0, capacity, dir);
|
||||
} else {
|
||||
// Non-anon visitor counts all non-anon + ALL ANON entries,
|
||||
// there is no way to determine the number of entries when
|
||||
// using the old cache APIs - there is no concept of anonymous
|
||||
// storage.
|
||||
uint32_t entryCount;
|
||||
rv = deviceInfo->GetEntryCount(&entryCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t totalSize;
|
||||
rv = deviceInfo->GetTotalSize(&totalSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCB->OnCacheStorageInfo(entryCount, totalSize, capacity, dir);
|
||||
}
|
||||
|
||||
mCB->OnCacheStorageInfo(entryCount, totalSize);
|
||||
*_retval = mVisitEntries;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP VisitCallbackWrapper::VisitEntry(const char * deviceID,
|
||||
nsICacheEntryInfo *entryInfo,
|
||||
bool *_retval)
|
||||
NS_IMETHODIMP _OldVisitCallbackWrapper::VisitEntry(const char * deviceID,
|
||||
nsICacheEntryInfo *entryInfo,
|
||||
bool *_retval)
|
||||
{
|
||||
MOZ_ASSERT(!strcmp(deviceID, mDeviceID));
|
||||
|
||||
nsRefPtr<_OldCacheEntryWrapper> wrapper = new _OldCacheEntryWrapper(entryInfo);
|
||||
nsresult rv = mCB->OnCacheEntryInfo(wrapper);
|
||||
*_retval = NS_SUCCEEDED(rv);
|
||||
nsresult rv;
|
||||
|
||||
*_retval = true;
|
||||
|
||||
// Read all informative properties from the entry.
|
||||
nsXPIDLCString clientId;
|
||||
rv = entryInfo->GetClientID(getter_Copies(clientId));
|
||||
if (NS_FAILED(rv))
|
||||
return NS_OK;
|
||||
|
||||
if (mLoadInfo->IsPrivate() !=
|
||||
StringBeginsWith(clientId, NS_LITERAL_CSTRING("HTTP-memory-only-PB"))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoCString cacheKey, enhanceId;
|
||||
rv = entryInfo->GetKey(cacheKey);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_OK;
|
||||
|
||||
if (StringBeginsWith(cacheKey, NS_LITERAL_CSTRING("anon&"))) {
|
||||
if (!mLoadInfo->IsAnonymous())
|
||||
return NS_OK;
|
||||
|
||||
cacheKey = Substring(cacheKey, 5, cacheKey.Length());
|
||||
} else if (mLoadInfo->IsAnonymous()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (StringBeginsWith(cacheKey, NS_LITERAL_CSTRING("id="))) {
|
||||
int32_t uriSpecEnd = cacheKey.Find("&uri=");
|
||||
if (uriSpecEnd == kNotFound) // Corrupted, ignore
|
||||
return NS_OK;
|
||||
|
||||
enhanceId = Substring(cacheKey, 3, uriSpecEnd - 3);
|
||||
cacheKey = Substring(cacheKey, uriSpecEnd + 1, cacheKey.Length());
|
||||
}
|
||||
|
||||
if (StringBeginsWith(cacheKey, NS_LITERAL_CSTRING("uri="))) {
|
||||
cacheKey = Substring(cacheKey, 4, cacheKey.Length());
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
// cacheKey is strip of any prefixes
|
||||
rv = NS_NewURI(getter_AddRefs(uri), cacheKey);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_OK;
|
||||
|
||||
uint32_t dataSize;
|
||||
if (NS_FAILED(entryInfo->GetDataSize(&dataSize)))
|
||||
dataSize = 0;
|
||||
int32_t fetchCount;
|
||||
if (NS_FAILED(entryInfo->GetFetchCount(&fetchCount)))
|
||||
fetchCount = 0;
|
||||
uint32_t expirationTime;
|
||||
if (NS_FAILED(entryInfo->GetExpirationTime(&expirationTime)))
|
||||
expirationTime = 0;
|
||||
uint32_t lastModified;
|
||||
if (NS_FAILED(entryInfo->GetLastModified(&lastModified)))
|
||||
lastModified = 0;
|
||||
|
||||
// Send them to the consumer.
|
||||
rv = mCB->OnCacheEntryInfo(
|
||||
uri, enhanceId, (int64_t)dataSize, fetchCount, lastModified, expirationTime);
|
||||
|
||||
*_retval = NS_SUCCEEDED(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // anon
|
||||
|
||||
|
||||
// _OldGetDiskConsumption
|
||||
|
||||
//static
|
||||
@ -407,6 +478,35 @@ NS_IMETHODIMP _OldCacheEntryWrapper::HasWriteAccess(bool aWriteAllowed_unused, b
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
namespace { // anon
|
||||
|
||||
class MetaDataVisitorWrapper : public nsICacheMetaDataVisitor
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICACHEMETADATAVISITOR
|
||||
MetaDataVisitorWrapper(nsICacheEntryMetaDataVisitor* cb) : mCB(cb) {}
|
||||
virtual ~MetaDataVisitorWrapper() {}
|
||||
nsCOMPtr<nsICacheEntryMetaDataVisitor> mCB;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(MetaDataVisitorWrapper, nsICacheMetaDataVisitor)
|
||||
|
||||
NS_IMETHODIMP
|
||||
MetaDataVisitorWrapper::VisitMetaDataElement(char const * key,
|
||||
char const * value,
|
||||
bool *goon)
|
||||
{
|
||||
*goon = true;
|
||||
return mCB->OnMetaDataElement(key, value);
|
||||
}
|
||||
|
||||
} // anon
|
||||
|
||||
NS_IMETHODIMP _OldCacheEntryWrapper::VisitMetaData(nsICacheEntryMetaDataVisitor* cb)
|
||||
{
|
||||
nsRefPtr<MetaDataVisitorWrapper> w = new MetaDataVisitorWrapper(cb);
|
||||
return mOldDesc->VisitMetaData(w);
|
||||
}
|
||||
|
||||
namespace { // anon
|
||||
|
||||
@ -956,23 +1056,10 @@ NS_IMETHODIMP _OldStorage::AsyncVisitStorage(nsICacheStorageVisitor* aVisitor,
|
||||
|
||||
NS_ENSURE_ARG(aVisitor);
|
||||
|
||||
if (mLoadInfo->IsAnonymous()) {
|
||||
// There is no concept of 'anonymous' storage in the old cache
|
||||
// since anon cache entries are stored in 'non-anon' storage
|
||||
// with a special prefix.
|
||||
// Just fake we have 0 items with 0 consumption. This at least
|
||||
// prevents displaying double size in the advanced section of
|
||||
// the Options dialog.
|
||||
aVisitor->OnCacheStorageInfo(0, 0);
|
||||
if (aVisitEntries)
|
||||
aVisitor->OnCacheEntryVisitCompleted();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsICacheService> serv =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
char* deviceID;
|
||||
@ -984,8 +1071,8 @@ NS_IMETHODIMP _OldStorage::AsyncVisitStorage(nsICacheStorageVisitor* aVisitor,
|
||||
deviceID = const_cast<char*>("disk");
|
||||
}
|
||||
|
||||
nsRefPtr<VisitCallbackWrapper> cb = new VisitCallbackWrapper(
|
||||
deviceID, aVisitor, aVisitEntries);
|
||||
nsRefPtr<_OldVisitCallbackWrapper> cb = new _OldVisitCallbackWrapper(
|
||||
deviceID, aVisitor, aVisitEntries, mLoadInfo);
|
||||
rv = serv->VisitEntries(cb);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsICacheEntryOpenCallback.h"
|
||||
#include "nsICacheEntryDescriptor.h"
|
||||
#include "nsICacheStorageVisitor.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
@ -40,6 +41,7 @@ public:
|
||||
NS_IMETHOD OpenOutputStream(int64_t offset, nsIOutputStream * *_retval);
|
||||
NS_IMETHOD MaybeMarkValid();
|
||||
NS_IMETHOD HasWriteAccess(bool aWriteOnly, bool *aWriteAccess);
|
||||
NS_IMETHOD VisitMetaData(nsICacheEntryMetaDataVisitor*);
|
||||
|
||||
_OldCacheEntryWrapper(nsICacheEntryDescriptor* desc);
|
||||
_OldCacheEntryWrapper(nsICacheEntryInfo* info);
|
||||
@ -122,6 +124,33 @@ private:
|
||||
bool const mOfflineStorage : 1;
|
||||
};
|
||||
|
||||
class _OldVisitCallbackWrapper : public nsICacheVisitor
|
||||
{
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSICACHEVISITOR
|
||||
|
||||
_OldVisitCallbackWrapper(char const * deviceID,
|
||||
nsICacheStorageVisitor * cb,
|
||||
bool visitEntries,
|
||||
nsILoadContextInfo * aInfo)
|
||||
: mCB(cb)
|
||||
, mVisitEntries(visitEntries)
|
||||
, mDeviceID(deviceID)
|
||||
, mLoadInfo(aInfo)
|
||||
, mHit(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(_OldVisitCallbackWrapper);
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~_OldVisitCallbackWrapper();
|
||||
nsCOMPtr<nsICacheStorageVisitor> mCB;
|
||||
bool mVisitEntries;
|
||||
char const * mDeviceID;
|
||||
nsCOMPtr<nsILoadContextInfo> mLoadInfo;
|
||||
bool mHit; // set to true when the device was found
|
||||
};
|
||||
|
||||
class _OldGetDiskConsumption : public nsRunnable,
|
||||
public nsICacheVisitor
|
||||
{
|
||||
|
@ -14,9 +14,9 @@ typedef long nsCacheStoragePolicy;
|
||||
|
||||
interface nsICacheListener;
|
||||
interface nsIFile;
|
||||
interface nsICacheMetaDataVisitor;
|
||||
interface nsICacheEntryMetaDataVisitor;
|
||||
|
||||
[scriptable, uuid(3058bf1e-5116-41cf-826b-e6981308d414)]
|
||||
[scriptable, uuid(972dc51d-df01-4b1e-b7f3-76dbcc603b1e)]
|
||||
interface nsICacheEntry : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -124,6 +124,16 @@ interface nsICacheEntry : nsISupports
|
||||
string getMetaDataElement(in string key);
|
||||
void setMetaDataElement(in string key, in string value);
|
||||
|
||||
/**
|
||||
* Obtain the list of metadata keys this entry keeps.
|
||||
*
|
||||
* NOTE: The callback is invoked under the CacheFile's lock. It means
|
||||
* there should not be made any calls to the entry from the visitor and
|
||||
* if the values need to be processed somehow, it's better to cache them
|
||||
* and process outside the callback.
|
||||
*/
|
||||
void visitMetaData(in nsICacheEntryMetaDataVisitor visitor);
|
||||
|
||||
/**
|
||||
* Claims that all metadata on this entry are up-to-date and this entry
|
||||
* now can be delivered to other waiting consumers.
|
||||
@ -207,3 +217,16 @@ interface nsICacheEntry : nsISupports
|
||||
*/
|
||||
boolean hasWriteAccess(in boolean aWriteAllowed);
|
||||
};
|
||||
|
||||
/**
|
||||
* Argument for nsICacheEntry.visitMetaData, provides access to all metadata
|
||||
* keys and values stored on the entry.
|
||||
*/
|
||||
[scriptable, uuid(fea3e276-6ba5-4ceb-a581-807d1f43f6d0)]
|
||||
interface nsICacheEntryMetaDataVisitor : nsISupports
|
||||
{
|
||||
/**
|
||||
* Called over each key / value pair.
|
||||
*/
|
||||
void onMetaDataElement(in string key, in string value);
|
||||
};
|
||||
|
@ -4,18 +4,27 @@
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsICacheEntry;
|
||||
interface nsIURI;
|
||||
interface nsIFile;
|
||||
|
||||
[scriptable, uuid(692dda47-3b21-4d0d-853a-f4d27cc324d0)]
|
||||
[scriptable, uuid(946bd799-9410-4945-9085-79c7fe019e83)]
|
||||
interface nsICacheStorageVisitor : nsISupports
|
||||
{
|
||||
/**
|
||||
*/
|
||||
void onCacheStorageInfo(in uint32_t aEntryCount, in uint64_t aConsumption);
|
||||
void onCacheStorageInfo(in uint32_t aEntryCount,
|
||||
in uint64_t aConsumption,
|
||||
in uint64_t aCapacity,
|
||||
in nsIFile aDiskDirectory);
|
||||
|
||||
/**
|
||||
*/
|
||||
void onCacheEntryInfo(in nsICacheEntry aEntry);
|
||||
void onCacheEntryInfo(in nsIURI aURI,
|
||||
in ACString aIdEnhance,
|
||||
in int64_t aDataSize,
|
||||
in long aFetchCount,
|
||||
in uint32_t aLastModifiedTime,
|
||||
in uint32_t aExpirationTime);
|
||||
|
||||
/**
|
||||
*/
|
||||
|
@ -30,4 +30,5 @@ FINAL_LIBRARY = 'necko'
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../../base/src',
|
||||
'../../cache2',
|
||||
]
|
||||
|
@ -11,275 +11,423 @@
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsAboutProtocolUtils.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
||||
#include "nsICacheService.h"
|
||||
#include "nsICacheStorageService.h"
|
||||
#include "nsICacheStorage.h"
|
||||
#include "CacheFileUtils.h"
|
||||
#include "CacheObserver.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAboutCache, nsIAboutModule, nsICacheVisitor)
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
using namespace mozilla::net;
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAboutCache, nsIAboutModule, nsICacheStorageVisitor)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAboutCache::NewChannel(nsIURI *aURI, nsIChannel **result)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aURI);
|
||||
|
||||
nsresult rv;
|
||||
uint32_t bytesWritten;
|
||||
|
||||
*result = nullptr;
|
||||
// Get the cache manager service
|
||||
nsCOMPtr<nsICacheService> cacheService =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
|
||||
nsCOMPtr<nsIInputStream> inputStream;
|
||||
rv = NS_NewPipe(getter_AddRefs(inputStream), getter_AddRefs(mStream),
|
||||
16384, (uint32_t)-1,
|
||||
true, // non-blocking input
|
||||
false // blocking output
|
||||
);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIStorageStream> storageStream;
|
||||
nsCOMPtr<nsIOutputStream> outputStream;
|
||||
|
||||
// Init: (block size, maximum length)
|
||||
rv = NS_NewStorageStream(256, (uint32_t)-1, getter_AddRefs(storageStream));
|
||||
nsAutoCString storageName;
|
||||
rv = ParseURI(aURI, storageName);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = storageStream->GetOutputStream(0, getter_AddRefs(outputStream));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mBuffer.AssignLiteral(
|
||||
"<!DOCTYPE html>\n"
|
||||
"<html>\n"
|
||||
"<head>\n"
|
||||
" <title>Information about the Cache Service</title>\n"
|
||||
" <link rel=\"stylesheet\" "
|
||||
"href=\"chrome://global/skin/about.css\" type=\"text/css\"/>\n"
|
||||
" <link rel=\"stylesheet\" "
|
||||
"href=\"chrome://global/skin/aboutCache.css\" type=\"text/css\"/>\n"
|
||||
"</head>\n"
|
||||
"<body class=\"aboutPageWideContainer\">\n"
|
||||
"<h1>Information about the Cache Service</h1>\n");
|
||||
|
||||
outputStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
|
||||
|
||||
rv = ParseURI(aURI, mDeviceID);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mStream = outputStream;
|
||||
|
||||
// nsCacheService::VisitEntries calls nsMemoryCacheDevice::Visit,
|
||||
// nsDiskCacheDevice::Visit and nsOfflineCacheDevice::Visit,
|
||||
// each of which call
|
||||
// 1. VisitDevice (for about:cache),
|
||||
// 2. VisitEntry in a loop (for about:cache?device=disk etc.)
|
||||
rv = cacheService->VisitEntries(this);
|
||||
mBuffer.Truncate();
|
||||
if (rv == NS_ERROR_NOT_AVAILABLE) {
|
||||
mBuffer.AppendLiteral("<h2>The cache is disabled.</h2>\n");
|
||||
}
|
||||
else if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
mOverview = storageName.IsEmpty();
|
||||
if (mOverview) {
|
||||
// ...and visit all we can
|
||||
mStorageList.AppendElement(NS_LITERAL_CSTRING("memory"));
|
||||
mStorageList.AppendElement(NS_LITERAL_CSTRING("disk"));
|
||||
mStorageList.AppendElement(NS_LITERAL_CSTRING("appcache"));
|
||||
} else {
|
||||
// ...and visit just the specified storage, entries will output too
|
||||
mStorageList.AppendElement(storageName);
|
||||
}
|
||||
|
||||
if (!mDeviceID.IsEmpty()) {
|
||||
mBuffer.AppendLiteral("</table>\n");
|
||||
}
|
||||
mBuffer.AppendLiteral("</body>\n"
|
||||
"</html>\n");
|
||||
outputStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
|
||||
|
||||
nsCOMPtr<nsIInputStream> inStr;
|
||||
|
||||
rv = storageStream->NewInputStream(0, getter_AddRefs(inStr));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// The entries header is added on encounter of the first entry
|
||||
mEntriesHeaderAdded = false;
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_NewInputStreamChannel(getter_AddRefs(channel), aURI, inStr,
|
||||
rv = NS_NewInputStreamChannel(getter_AddRefs(channel), aURI, inputStream,
|
||||
NS_LITERAL_CSTRING("text/html"),
|
||||
NS_LITERAL_CSTRING("utf-8"));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mBuffer.AssignLiteral(
|
||||
"<!DOCTYPE html>\n"
|
||||
"<html>\n"
|
||||
"<head>\n"
|
||||
" <title>Network Cache Storage Information</title>\n"
|
||||
" <meta charset=\"utf-8\">\n"
|
||||
" <link rel=\"stylesheet\" href=\"chrome://global/skin/about.css\"/>\n"
|
||||
" <link rel=\"stylesheet\" href=\"chrome://global/skin/aboutCache.css\"/>\n"
|
||||
" <script src=\"chrome://global/content/aboutCache.js\"></script>"
|
||||
"</head>\n"
|
||||
"<body class=\"aboutPageWideContainer\">\n"
|
||||
"<h1>Information about the Network Cache Storage Service</h1>\n");
|
||||
|
||||
// Add the context switch controls
|
||||
mBuffer.AppendLiteral(
|
||||
"<label><input id='priv' type='checkbox'/> Private</label>\n"
|
||||
"<label><input id='anon' type='checkbox'/> Anonymous</label>\n"
|
||||
);
|
||||
|
||||
if (CacheObserver::UseNewCache()) {
|
||||
// Visit scoping by browser and appid is not implemented for
|
||||
// the old cache, simply don't add these controls.
|
||||
// The appid/inbrowser entries are already mixed in the default
|
||||
// view anyway.
|
||||
mBuffer.AppendLiteral(
|
||||
"<label><input id='appid' type='text' size='6'/> AppID</label>\n"
|
||||
"<label><input id='inbrowser' type='checkbox'/> In Browser Element</label>\n"
|
||||
);
|
||||
}
|
||||
|
||||
mBuffer.AppendLiteral(
|
||||
"<label><input id='submit' type='button' value='Update' onclick='navigate()'/></label>\n"
|
||||
);
|
||||
|
||||
if (!mOverview) {
|
||||
mBuffer.AppendLiteral("<a href=\"about:cache?storage=&context=");
|
||||
char* escapedContext = nsEscapeHTML(mContextString.get());
|
||||
mBuffer.Append(escapedContext);
|
||||
nsMemory::Free(escapedContext);
|
||||
mBuffer.AppendLiteral("\">Back to overview</a>");
|
||||
}
|
||||
|
||||
FlushBuffer();
|
||||
|
||||
// Kick it, this goes async.
|
||||
rv = VisitNextStorage();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
channel.forget(result);
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAboutCache::GetURIFlags(nsIURI *aURI, uint32_t *result)
|
||||
nsresult
|
||||
nsAboutCache::ParseURI(nsIURI * uri, nsACString & storage)
|
||||
{
|
||||
*result = 0;
|
||||
//
|
||||
// about:cache[?storage=<storage-name>[&context=<context-key>]]
|
||||
//
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString path;
|
||||
rv = uri->GetPath(path);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mContextString.Truncate();
|
||||
mLoadInfo = CacheFileUtils::ParseKey(NS_LITERAL_CSTRING(""));
|
||||
storage.Truncate();
|
||||
|
||||
nsACString::const_iterator start, valueStart, end;
|
||||
path.BeginReading(start);
|
||||
path.EndReading(end);
|
||||
|
||||
valueStart = end;
|
||||
if (!FindInReadable(NS_LITERAL_CSTRING("?storage="), start, valueStart)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsACString::const_iterator storageNameBegin = valueStart;
|
||||
|
||||
start = valueStart;
|
||||
valueStart = end;
|
||||
if (!FindInReadable(NS_LITERAL_CSTRING("&context="), start, valueStart))
|
||||
start = end;
|
||||
|
||||
nsACString::const_iterator storageNameEnd = start;
|
||||
|
||||
mContextString = Substring(valueStart, end);
|
||||
mLoadInfo = CacheFileUtils::ParseKey(mContextString);
|
||||
storage.Assign(Substring(storageNameBegin, storageNameEnd));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAboutCache::VisitNextStorage()
|
||||
{
|
||||
if (!mStorageList.Length())
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
mStorageName = mStorageList[0];
|
||||
mStorageList.RemoveElementAt(0);
|
||||
|
||||
// Must re-dispatch since we cannot start another visit cycle
|
||||
// from visitor callback. The cache v1 service doesn't like it.
|
||||
// TODO - mayhemer, bug 913828, remove this dispatch and call
|
||||
// directly.
|
||||
nsCOMPtr<nsRunnableMethod<nsAboutCache> > event =
|
||||
NS_NewRunnableMethod(this, &nsAboutCache::FireVisitStorage);
|
||||
return NS_DispatchToMainThread(event);
|
||||
}
|
||||
|
||||
void
|
||||
nsAboutCache::FireVisitStorage()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = VisitStorage(mStorageName);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (mLoadInfo) {
|
||||
mBuffer.Append(
|
||||
nsPrintfCString("<p>Unrecognized storage name '%s' in about:cache URL</p>",
|
||||
mStorageName.get()));
|
||||
} else {
|
||||
mBuffer.Append(
|
||||
nsPrintfCString("<p>Unrecognized context key '%s' in about:cache URL</p>",
|
||||
mContextString.get()));
|
||||
}
|
||||
|
||||
FlushBuffer();
|
||||
|
||||
// Simulate finish of a visit cycle, this tries the next storage
|
||||
// or closes the output stream (i.e. the UI loader will stop spinning)
|
||||
OnCacheEntryVisitCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAboutCache::VisitStorage(nsACString const & storageName)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = GetStorage(storageName, mLoadInfo, getter_AddRefs(mStorage));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mStorage->AsyncVisitStorage(this, !mOverview);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//static
|
||||
nsresult
|
||||
nsAboutCache::GetStorage(nsACString const & storageName,
|
||||
nsILoadContextInfo* loadInfo,
|
||||
nsICacheStorage **storage)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsICacheStorageService> cacheService =
|
||||
do_GetService("@mozilla.org/netwerk/cache-storage-service;1", &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsICacheStorage> cacheStorage;
|
||||
if (storageName == "disk") {
|
||||
rv = cacheService->DiskCacheStorage(
|
||||
loadInfo, false, getter_AddRefs(cacheStorage));
|
||||
} else if (storageName == "memory") {
|
||||
rv = cacheService->MemoryCacheStorage(
|
||||
loadInfo, getter_AddRefs(cacheStorage));
|
||||
} else if (storageName == "appcache") {
|
||||
rv = cacheService->AppCacheStorage(
|
||||
loadInfo, nullptr, getter_AddRefs(cacheStorage));
|
||||
} else {
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
cacheStorage.forget(storage);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAboutCache::VisitDevice(const char *deviceID,
|
||||
nsICacheDeviceInfo *deviceInfo,
|
||||
bool *visitEntries)
|
||||
nsAboutCache::OnCacheStorageInfo(uint32_t aEntryCount, uint64_t aConsumption,
|
||||
uint64_t aCapacity, nsIFile * aDirectory)
|
||||
{
|
||||
uint32_t bytesWritten, value, entryCount;
|
||||
nsXPIDLCString str;
|
||||
// We need mStream for this
|
||||
if (!mStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*visitEntries = false;
|
||||
mBuffer.AssignLiteral("<h2>");
|
||||
mBuffer.Append(mStorageName);
|
||||
mBuffer.AppendLiteral("</h2>\n"
|
||||
"<table id=\"");
|
||||
mBuffer.AppendLiteral("\">\n");
|
||||
|
||||
if (mDeviceID.IsEmpty() || mDeviceID.Equals(deviceID)) {
|
||||
// Write out cache info
|
||||
// Number of entries
|
||||
mBuffer.AppendLiteral(" <tr>\n"
|
||||
" <th>Number of entries:</th>\n"
|
||||
" <td>");
|
||||
mBuffer.AppendInt(aEntryCount);
|
||||
mBuffer.AppendLiteral("</td>\n"
|
||||
" </tr>\n");
|
||||
|
||||
// We need mStream for this
|
||||
if (!mStream)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Write out the Cache Name
|
||||
deviceInfo->GetDescription(getter_Copies(str));
|
||||
// Maximum storage size
|
||||
mBuffer.AppendLiteral(" <tr>\n"
|
||||
" <th>Maximum storage size:</th>\n"
|
||||
" <td>");
|
||||
mBuffer.AppendInt(aCapacity / 1024);
|
||||
mBuffer.AppendLiteral(" KiB</td>\n"
|
||||
" </tr>\n");
|
||||
|
||||
mBuffer.AssignLiteral("<h2>");
|
||||
mBuffer.Append(str);
|
||||
mBuffer.AppendLiteral("</h2>\n"
|
||||
"<table id=\"");
|
||||
mBuffer.Append(deviceID);
|
||||
mBuffer.AppendLiteral("\">\n");
|
||||
// Storage in use
|
||||
mBuffer.AppendLiteral(" <tr>\n"
|
||||
" <th>Storage in use:</th>\n"
|
||||
" <td>");
|
||||
mBuffer.AppendInt(aConsumption / 1024);
|
||||
mBuffer.AppendLiteral(" KiB</td>\n"
|
||||
" </tr>\n");
|
||||
|
||||
// Write out cache info
|
||||
// Number of entries
|
||||
mBuffer.AppendLiteral(" <tr>\n"
|
||||
" <th>Number of entries:</th>\n"
|
||||
" <td>");
|
||||
entryCount = 0;
|
||||
deviceInfo->GetEntryCount(&entryCount);
|
||||
mBuffer.AppendInt(entryCount);
|
||||
mBuffer.AppendLiteral("</td>\n"
|
||||
" </tr>\n");
|
||||
// Storage disk location
|
||||
mBuffer.AppendLiteral(" <tr>\n"
|
||||
" <th>Storage disk location:</th>\n"
|
||||
" <td>");
|
||||
if (aDirectory) {
|
||||
nsAutoString path;
|
||||
aDirectory->GetPath(path);
|
||||
mBuffer.Append(NS_ConvertUTF16toUTF8(path));
|
||||
} else {
|
||||
mBuffer.AppendLiteral("none, only stored in memory");
|
||||
}
|
||||
mBuffer.AppendLiteral(" </td>\n"
|
||||
" </tr>\n");
|
||||
|
||||
// Maximum storage size
|
||||
mBuffer.AppendLiteral(" <tr>\n"
|
||||
" <th>Maximum storage size:</th>\n"
|
||||
" <td>");
|
||||
value = 0;
|
||||
deviceInfo->GetMaximumSize(&value);
|
||||
mBuffer.AppendInt(value/1024);
|
||||
mBuffer.AppendLiteral(" KiB</td>\n"
|
||||
" </tr>\n");
|
||||
|
||||
// Storage in use
|
||||
mBuffer.AppendLiteral(" <tr>\n"
|
||||
" <th>Storage in use:</th>\n"
|
||||
" <td>");
|
||||
value = 0;
|
||||
deviceInfo->GetTotalSize(&value);
|
||||
mBuffer.AppendInt(value/1024);
|
||||
mBuffer.AppendLiteral(" KiB</td>\n"
|
||||
" </tr>\n");
|
||||
|
||||
deviceInfo->GetUsageReport(getter_Copies(str));
|
||||
mBuffer.Append(str);
|
||||
|
||||
if (mDeviceID.IsEmpty()) { // The about:cache case
|
||||
if (entryCount != 0) { // Add the "List Cache Entries" link
|
||||
mBuffer.AppendLiteral(" <tr>\n"
|
||||
" <th><a href=\"about:cache?device=");
|
||||
mBuffer.Append(deviceID);
|
||||
mBuffer.AppendLiteral("\">List Cache Entries</a></th>\n"
|
||||
" </tr>\n");
|
||||
}
|
||||
mBuffer.AppendLiteral("</table>\n");
|
||||
} else { // The about:cache?device=disk etc. case
|
||||
mBuffer.AppendLiteral("</table>\n");
|
||||
if (entryCount != 0) {
|
||||
*visitEntries = true;
|
||||
mBuffer.AppendLiteral("<hr/>\n"
|
||||
"<table id=\"entries\">\n"
|
||||
" <colgroup>\n"
|
||||
" <col id=\"col-key\">\n"
|
||||
" <col id=\"col-dataSize\">\n"
|
||||
" <col id=\"col-fetchCount\">\n"
|
||||
" <col id=\"col-lastModified\">\n"
|
||||
" <col id=\"col-expires\">\n"
|
||||
" </colgroup>\n"
|
||||
" <thead>\n"
|
||||
" <tr>\n"
|
||||
" <th>Key</th>\n"
|
||||
" <th>Data size</th>\n"
|
||||
" <th>Fetch count</th>\n"
|
||||
" <th>Last modified</th>\n"
|
||||
" <th>Expires</th>\n"
|
||||
" </tr>\n"
|
||||
" </thead>\n");
|
||||
}
|
||||
if (mOverview) { // The about:cache case
|
||||
if (aEntryCount != 0) { // Add the "List Cache Entries" link
|
||||
mBuffer.AppendLiteral(" <tr>\n"
|
||||
" <th><a href=\"about:cache?storage=");
|
||||
mBuffer.Append(mStorageName);
|
||||
mBuffer.AppendLiteral("&context=");
|
||||
char* escapedContext = nsEscapeHTML(mContextString.get());
|
||||
mBuffer.Append(escapedContext);
|
||||
nsMemory::Free(escapedContext);
|
||||
mBuffer.AppendLiteral("\">List Cache Entries</a></th>\n"
|
||||
" </tr>\n");
|
||||
}
|
||||
}
|
||||
|
||||
mStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
|
||||
mBuffer.AppendLiteral("</table>\n");
|
||||
|
||||
// The entries header is added on encounter of the first entry
|
||||
mEntriesHeaderAdded = false;
|
||||
|
||||
FlushBuffer();
|
||||
|
||||
if (mOverview) {
|
||||
// OnCacheEntryVisitCompleted() is not called when we do not iterate
|
||||
// cache entries. Since this moves forward to the next storage in
|
||||
// the list we want to visit, artificially call it here.
|
||||
OnCacheEntryVisitCompleted();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAboutCache::VisitEntry(const char *deviceID,
|
||||
nsICacheEntryInfo *entryInfo,
|
||||
bool *visitNext)
|
||||
nsAboutCache::OnCacheEntryInfo(nsIURI *aURI, const nsACString & aIdEnhance,
|
||||
int64_t aDataSize, int32_t aFetchCount,
|
||||
uint32_t aLastModified, uint32_t aExpirationTime)
|
||||
{
|
||||
// We need mStream for this
|
||||
if (!mStream)
|
||||
return NS_ERROR_FAILURE;
|
||||
if (!mStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
uint32_t bytesWritten;
|
||||
nsAutoCString key;
|
||||
nsXPIDLCString clientID;
|
||||
bool streamBased;
|
||||
|
||||
rv = entryInfo->GetKey(key);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = entryInfo->GetClientID(getter_Copies(clientID));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = entryInfo->IsStreamBased(&streamBased);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!mEntriesHeaderAdded) {
|
||||
mBuffer.AppendLiteral("<hr/>\n"
|
||||
"<table id=\"entries\">\n"
|
||||
" <colgroup>\n"
|
||||
" <col id=\"col-key\">\n"
|
||||
" <col id=\"col-dataSize\">\n"
|
||||
" <col id=\"col-fetchCount\">\n"
|
||||
" <col id=\"col-lastModified\">\n"
|
||||
" <col id=\"col-expires\">\n"
|
||||
" </colgroup>\n"
|
||||
" <thead>\n"
|
||||
" <tr>\n"
|
||||
" <th>Key</th>\n"
|
||||
" <th>Data size</th>\n"
|
||||
" <th>Fetch count</th>\n"
|
||||
" <th>Last Modifed</th>\n"
|
||||
" <th>Expires</th>\n"
|
||||
" </tr>\n"
|
||||
" </thead>\n");
|
||||
mEntriesHeaderAdded = true;
|
||||
}
|
||||
|
||||
// Generate a about:cache-entry URL for this entry...
|
||||
|
||||
nsAutoCString url;
|
||||
url.AssignLiteral("about:cache-entry?client=");
|
||||
url += clientID;
|
||||
url.AppendLiteral("&sb=");
|
||||
url += streamBased ? '1' : '0';
|
||||
url.AppendLiteral("&key=");
|
||||
char* escapedKey = nsEscapeHTML(key.get());
|
||||
url += escapedKey; // key
|
||||
url.AssignLiteral("about:cache-entry?storage=");
|
||||
url.Append(mStorageName);
|
||||
|
||||
url.AppendLiteral("&context=");
|
||||
char* escapedContext = nsEscapeHTML(mContextString.get());
|
||||
url += escapedContext;
|
||||
nsMemory::Free(escapedContext);
|
||||
|
||||
url.AppendLiteral("&eid=");
|
||||
char* escapedEID = nsEscapeHTML(aIdEnhance.BeginReading());
|
||||
url += escapedEID;
|
||||
nsMemory::Free(escapedEID);
|
||||
|
||||
nsAutoCString cacheUriSpec;
|
||||
aURI->GetAsciiSpec(cacheUriSpec);
|
||||
char* escapedCacheURI = nsEscapeHTML(cacheUriSpec.get());
|
||||
url.AppendLiteral("&uri=");
|
||||
url += escapedCacheURI;
|
||||
|
||||
// Entry start...
|
||||
mBuffer.AssignLiteral(" <tr>\n");
|
||||
mBuffer.AppendLiteral(" <tr>\n");
|
||||
|
||||
// URI
|
||||
mBuffer.AppendLiteral(" <td><a href=\"");
|
||||
mBuffer.Append(url);
|
||||
mBuffer.AppendLiteral("\">");
|
||||
mBuffer.Append(escapedKey);
|
||||
nsMemory::Free(escapedKey);
|
||||
if (!aIdEnhance.IsEmpty()) {
|
||||
mBuffer.Append(aIdEnhance);
|
||||
mBuffer.Append(':');
|
||||
}
|
||||
mBuffer.Append(escapedCacheURI);
|
||||
mBuffer.AppendLiteral("</a></td>\n");
|
||||
|
||||
nsMemory::Free(escapedCacheURI);
|
||||
|
||||
// Content length
|
||||
uint32_t length = 0;
|
||||
entryInfo->GetDataSize(&length);
|
||||
mBuffer.AppendLiteral(" <td>");
|
||||
mBuffer.AppendInt(length);
|
||||
mBuffer.AppendInt(aDataSize);
|
||||
mBuffer.AppendLiteral(" bytes</td>\n");
|
||||
|
||||
// Number of accesses
|
||||
int32_t fetchCount = 0;
|
||||
entryInfo->GetFetchCount(&fetchCount);
|
||||
mBuffer.AppendLiteral(" <td>");
|
||||
mBuffer.AppendInt(fetchCount);
|
||||
mBuffer.AppendInt(aFetchCount);
|
||||
mBuffer.AppendLiteral("</td>\n");
|
||||
|
||||
// vars for reporting time
|
||||
char buf[255];
|
||||
uint32_t t;
|
||||
|
||||
// Last modified time
|
||||
mBuffer.AppendLiteral(" <td>");
|
||||
entryInfo->GetLastModified(&t);
|
||||
if (t) {
|
||||
PrintTimeString(buf, sizeof(buf), t);
|
||||
if (aLastModified) {
|
||||
PrintTimeString(buf, sizeof(buf), aLastModified);
|
||||
mBuffer.Append(buf);
|
||||
} else
|
||||
mBuffer.AppendLiteral("No last modified time");
|
||||
} else {
|
||||
mBuffer.AppendLiteral("No last modified time (bug 1000338)");
|
||||
}
|
||||
mBuffer.AppendLiteral("</td>\n");
|
||||
|
||||
// Expires time
|
||||
mBuffer.AppendLiteral(" <td>");
|
||||
entryInfo->GetExpirationTime(&t);
|
||||
if (t < 0xFFFFFFFF) {
|
||||
PrintTimeString(buf, sizeof(buf), t);
|
||||
if (aExpirationTime < 0xFFFFFFFF) {
|
||||
PrintTimeString(buf, sizeof(buf), aExpirationTime);
|
||||
mBuffer.Append(buf);
|
||||
} else {
|
||||
mBuffer.AppendLiteral("No expiration time");
|
||||
@ -289,40 +437,55 @@ nsAboutCache::VisitEntry(const char *deviceID,
|
||||
// Entry is done...
|
||||
mBuffer.AppendLiteral(" </tr>\n");
|
||||
|
||||
mStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
|
||||
|
||||
*visitNext = true;
|
||||
FlushBuffer();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsAboutCache::ParseURI(nsIURI * uri, nsCString &deviceID)
|
||||
NS_IMETHODIMP
|
||||
nsAboutCache::OnCacheEntryVisitCompleted()
|
||||
{
|
||||
//
|
||||
// about:cache[?device=string]
|
||||
//
|
||||
nsresult rv;
|
||||
if (!mStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
deviceID.Truncate();
|
||||
if (mEntriesHeaderAdded) {
|
||||
mBuffer.AppendLiteral("</table>\n");
|
||||
}
|
||||
|
||||
nsAutoCString path;
|
||||
rv = uri->GetPath(path);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// Kick another storage visiting (from a storage that allows us.)
|
||||
while (mStorageList.Length()) {
|
||||
nsresult rv = VisitNextStorage();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Expecting new round of OnCache* calls.
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
nsACString::const_iterator start, valueStart, end;
|
||||
path.BeginReading(start);
|
||||
path.EndReading(end);
|
||||
// We are done!
|
||||
mBuffer.AppendLiteral("</body>\n"
|
||||
"</html>\n");
|
||||
FlushBuffer();
|
||||
mStream->Close();
|
||||
|
||||
valueStart = end;
|
||||
if (!FindInReadable(NS_LITERAL_CSTRING("?device="), start, valueStart))
|
||||
return NS_OK;
|
||||
|
||||
deviceID.Assign(Substring(valueStart, end));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsAboutCache::FlushBuffer()
|
||||
{
|
||||
uint32_t bytesWritten;
|
||||
mStream->Write(mBuffer.get(), mBuffer.Length(), &bytesWritten);
|
||||
mBuffer.Truncate();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAboutCache::GetURIFlags(nsIURI *aURI, uint32_t *result)
|
||||
{
|
||||
*result = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsAboutCache::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
@ -335,6 +498,4 @@ nsAboutCache::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -7,20 +7,23 @@
|
||||
#define nsAboutCache_h__
|
||||
|
||||
#include "nsIAboutModule.h"
|
||||
#include "nsICacheStorageVisitor.h"
|
||||
#include "nsICacheStorage.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsILoadContextInfo.h"
|
||||
|
||||
#include "nsICacheVisitor.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsAboutCache : public nsIAboutModule
|
||||
, public nsICacheVisitor
|
||||
, public nsICacheStorageVisitor
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABOUTMODULE
|
||||
NS_DECL_NSICACHEVISITOR
|
||||
NS_DECL_NSICACHESTORAGEVISITOR
|
||||
|
||||
nsAboutCache() {}
|
||||
virtual ~nsAboutCache() {}
|
||||
@ -28,12 +31,50 @@ public:
|
||||
static nsresult
|
||||
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
|
||||
protected:
|
||||
nsresult ParseURI(nsIURI * uri, nsCString &deviceID);
|
||||
static nsresult
|
||||
GetStorage(nsACString const & storageName, nsILoadContextInfo* loadInfo,
|
||||
nsICacheStorage **storage);
|
||||
|
||||
nsCOMPtr<nsIOutputStream> mStream;
|
||||
nsCString mDeviceID;
|
||||
protected:
|
||||
nsresult ParseURI(nsIURI * uri, nsACString & storage);
|
||||
|
||||
// Finds a next storage we wish to visit (we use this method
|
||||
// even there is a specified storage name, which is the only
|
||||
// one in the list then.) Posts FireVisitStorage() when found.
|
||||
nsresult VisitNextStorage();
|
||||
// Helper method that calls VisitStorage() for the current storage.
|
||||
// When it fails, OnCacheEntryVisitCompleted is simlated to close
|
||||
// the output stream and thus the about:cache channel.
|
||||
void FireVisitStorage();
|
||||
// Kiks the visit cycle for the given storage, names can be:
|
||||
// "disk", "memory", "appcache"
|
||||
// Note: any newly added storage type has to be manually handled here.
|
||||
nsresult VisitStorage(nsACString const & storageName);
|
||||
|
||||
// Writes content of mBuffer to mStream and truncates
|
||||
// the buffer.
|
||||
void FlushBuffer();
|
||||
|
||||
// Whether we are showing overview status of all available
|
||||
// storages.
|
||||
bool mOverview;
|
||||
|
||||
// Flag initially false, that indicates the entries header has
|
||||
// been added to the output HTML.
|
||||
bool mEntriesHeaderAdded;
|
||||
|
||||
// The context we are working with.
|
||||
nsCOMPtr<nsILoadContextInfo> mLoadInfo;
|
||||
nsCString mContextString;
|
||||
|
||||
// The list of all storage names we want to visit
|
||||
nsTArray<nsCString> mStorageList;
|
||||
nsCString mStorageName;
|
||||
nsCOMPtr<nsICacheStorage> mStorage;
|
||||
|
||||
// Output data buffering and streaming output
|
||||
nsCString mBuffer;
|
||||
nsCOMPtr<nsIOutputStream> mStream;
|
||||
};
|
||||
|
||||
#define NS_ABOUT_CACHE_MODULE_CID \
|
||||
|
@ -4,16 +4,21 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsAboutCacheEntry.h"
|
||||
#include "nsICacheService.h"
|
||||
#include "nsICacheSession.h"
|
||||
#include "nsAboutCache.h"
|
||||
#include "nsICacheStorage.h"
|
||||
#include "CacheObserver.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "prprf.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsIAsyncInputStream.h"
|
||||
#include "nsIAsyncOutputStream.h"
|
||||
#include "nsAboutProtocolUtils.h"
|
||||
#include "nsInputStreamPump.h"
|
||||
#include "CacheFileUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace mozilla::net;
|
||||
|
||||
#define HEXDUMP_MAX_ROWS 16
|
||||
|
||||
static void
|
||||
@ -74,7 +79,9 @@ HexDump(uint32_t *state, const char *buf, int32_t n, nsCString &result)
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsAboutCacheEntry,
|
||||
nsIAboutModule,
|
||||
nsICacheMetaDataVisitor)
|
||||
nsICacheEntryOpenCallback,
|
||||
nsICacheEntryMetaDataVisitor,
|
||||
nsIStreamListener)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsAboutCacheEntry::nsIAboutModule
|
||||
@ -146,32 +153,158 @@ nsresult
|
||||
nsAboutCacheEntry::OpenCacheEntry(nsIURI *uri)
|
||||
{
|
||||
nsresult rv;
|
||||
nsAutoCString clientID, key;
|
||||
bool streamBased = true;
|
||||
|
||||
rv = ParseURI(uri, clientID, streamBased, key);
|
||||
rv = ParseURI(uri, mStorageName, getter_AddRefs(mLoadInfo),
|
||||
mEnhanceId, getter_AddRefs(mCacheURI));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsICacheService> serv =
|
||||
do_GetService(NS_CACHESERVICE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (!CacheObserver::UseNewCache() &&
|
||||
mLoadInfo->IsPrivate() &&
|
||||
mStorageName == NS_LITERAL_CSTRING("disk")) {
|
||||
// The cache v1 is storing all private entries in the memory-only
|
||||
// cache, so it would not be found in the v1 disk cache.
|
||||
mStorageName = NS_LITERAL_CSTRING("memory");
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICacheSession> session;
|
||||
rv = serv->CreateSession(clientID.get(),
|
||||
nsICache::STORE_ANYWHERE,
|
||||
streamBased,
|
||||
getter_AddRefs(session));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = session->SetDoomEntriesIfExpired(false);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return session->AsyncOpenCacheEntry(key, nsICache::ACCESS_READ, this, true);
|
||||
return OpenCacheEntry();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAboutCacheEntry::OpenCacheEntry()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsICacheStorage> storage;
|
||||
rv = nsAboutCache::GetStorage(mStorageName, mLoadInfo, getter_AddRefs(storage));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Invokes OnCacheEntryAvailable()
|
||||
rv = storage->AsyncOpenURI(mCacheURI, mEnhanceId,
|
||||
nsICacheStorage::OPEN_READONLY, this);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAboutCacheEntry::ParseURI(nsIURI *uri,
|
||||
nsACString &storageName,
|
||||
nsILoadContextInfo **loadInfo,
|
||||
nsCString &enahnceID,
|
||||
nsIURI **cacheUri)
|
||||
{
|
||||
//
|
||||
// about:cache-entry?storage=[string]&contenxt=[string]&eid=[string]&uri=[string]
|
||||
//
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString path;
|
||||
rv = uri->GetPath(path);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsACString::const_iterator keyBegin, keyEnd, valBegin, begin, end;
|
||||
path.BeginReading(begin);
|
||||
path.EndReading(end);
|
||||
|
||||
keyBegin = begin; keyEnd = end;
|
||||
if (!FindInReadable(NS_LITERAL_CSTRING("?storage="), keyBegin, keyEnd))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
valBegin = keyEnd; // the value of the storage key starts after the key
|
||||
|
||||
keyBegin = keyEnd; keyEnd = end;
|
||||
if (!FindInReadable(NS_LITERAL_CSTRING("&context="), keyBegin, keyEnd))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
storageName.Assign(Substring(valBegin, keyBegin));
|
||||
valBegin = keyEnd; // the value of the context key starts after the key
|
||||
|
||||
keyBegin = keyEnd; keyEnd = end;
|
||||
if (!FindInReadable(NS_LITERAL_CSTRING("&eid="), keyBegin, keyEnd))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsAutoCString contextKey(Substring(valBegin, keyBegin));
|
||||
valBegin = keyEnd; // the value of the eid key starts after the key
|
||||
|
||||
keyBegin = keyEnd; keyEnd = end;
|
||||
if (!FindInReadable(NS_LITERAL_CSTRING("&uri="), keyBegin, keyEnd))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
enahnceID.Assign(Substring(valBegin, keyBegin));
|
||||
|
||||
valBegin = keyEnd; // the value of the uri key starts after the key
|
||||
nsAutoCString uriSpec(Substring(valBegin, end)); // uri is the last one
|
||||
|
||||
// Uf... parsing done, now get some objects from it...
|
||||
|
||||
nsCOMPtr<nsILoadContextInfo> info =
|
||||
CacheFileUtils::ParseKey(contextKey);
|
||||
if (!info)
|
||||
return NS_ERROR_FAILURE;
|
||||
info.forget(loadInfo);
|
||||
|
||||
rv = NS_NewURI(cacheUri, uriSpec);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// helper methods
|
||||
// nsICacheEntryOpenCallback implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAboutCacheEntry::OnCacheEntryCheck(nsICacheEntry *aEntry,
|
||||
nsIApplicationCache *aApplicationCache,
|
||||
uint32_t *result)
|
||||
{
|
||||
*result = nsICacheEntryOpenCallback::ENTRY_WANTED;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAboutCacheEntry::OnCacheEntryAvailable(nsICacheEntry *entry,
|
||||
bool isNew,
|
||||
nsIApplicationCache *aApplicationCache,
|
||||
nsresult status)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
mWaitingForData = false;
|
||||
if (entry) {
|
||||
rv = WriteCacheEntryDescription(entry);
|
||||
} else if (!CacheObserver::UseNewCache() &&
|
||||
!mLoadInfo->IsPrivate() &&
|
||||
mStorageName == NS_LITERAL_CSTRING("memory")) {
|
||||
// If we were not able to find the entry in the memory storage
|
||||
// try again in the disk storage.
|
||||
// This is a workaround for cache v1: when an originally disk
|
||||
// cache entry is recreated as memory-only, it's clientID doesn't
|
||||
// change and we cannot find it in "HTTP-memory-only" session.
|
||||
// "Disk" cache storage looks at "HTTP".
|
||||
mStorageName = NS_LITERAL_CSTRING("disk");
|
||||
rv = OpenCacheEntry();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return NS_OK;
|
||||
}
|
||||
} else {
|
||||
rv = WriteCacheEntryUnavailable();
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
||||
if (!mWaitingForData) {
|
||||
// Data is not expected, close the output of content now.
|
||||
CloseContent();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Print-out helper methods
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define APPEND_ROW(label, value) \
|
||||
@ -187,7 +320,7 @@ nsAboutCacheEntry::OpenCacheEntry(nsIURI *uri)
|
||||
PR_END_MACRO
|
||||
|
||||
nsresult
|
||||
nsAboutCacheEntry::WriteCacheEntryDescription(nsICacheEntryDescriptor *descriptor)
|
||||
nsAboutCacheEntry::WriteCacheEntryDescription(nsICacheEntry *entry)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCString buffer;
|
||||
@ -195,7 +328,7 @@ nsAboutCacheEntry::WriteCacheEntryDescription(nsICacheEntryDescriptor *descripto
|
||||
|
||||
nsAutoCString str;
|
||||
|
||||
rv = descriptor->GetKey(str);
|
||||
rv = entry->GetKey(str);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
buffer.SetCapacity(4096);
|
||||
@ -224,9 +357,9 @@ nsAboutCacheEntry::WriteCacheEntryDescription(nsICacheEntryDescriptor *descripto
|
||||
buffer.Append(escapedStr);
|
||||
buffer.AppendLiteral("</a>");
|
||||
uri = 0;
|
||||
}
|
||||
else
|
||||
} else {
|
||||
buffer.Append(escapedStr);
|
||||
}
|
||||
nsMemory::Free(escapedStr);
|
||||
buffer.AppendLiteral("</td>\n"
|
||||
" </tr>\n");
|
||||
@ -239,30 +372,30 @@ nsAboutCacheEntry::WriteCacheEntryDescription(nsICacheEntryDescriptor *descripto
|
||||
|
||||
// Fetch Count
|
||||
s.Truncate();
|
||||
descriptor->GetFetchCount(&i);
|
||||
entry->GetFetchCount(&i);
|
||||
s.AppendInt(i);
|
||||
APPEND_ROW("fetch count", s);
|
||||
|
||||
// Last Fetched
|
||||
descriptor->GetLastFetched(&u);
|
||||
entry->GetLastFetched(&u);
|
||||
if (u) {
|
||||
PrintTimeString(timeBuf, sizeof(timeBuf), u);
|
||||
APPEND_ROW("last fetched", timeBuf);
|
||||
} else {
|
||||
APPEND_ROW("last fetched", "No last fetch time");
|
||||
APPEND_ROW("last fetched", "No last fetch time (bug 1000338)");
|
||||
}
|
||||
|
||||
// Last Modified
|
||||
descriptor->GetLastModified(&u);
|
||||
entry->GetLastModified(&u);
|
||||
if (u) {
|
||||
PrintTimeString(timeBuf, sizeof(timeBuf), u);
|
||||
APPEND_ROW("last modified", timeBuf);
|
||||
} else {
|
||||
APPEND_ROW("last modified", "No last modified time");
|
||||
APPEND_ROW("last modified", "No last modified time (bug 1000338)");
|
||||
}
|
||||
|
||||
// Expiration Time
|
||||
descriptor->GetExpirationTime(&u);
|
||||
entry->GetExpirationTime(&u);
|
||||
if (u < 0xFFFFFFFF) {
|
||||
PrintTimeString(timeBuf, sizeof(timeBuf), u);
|
||||
APPEND_ROW("expires", timeBuf);
|
||||
@ -273,29 +406,24 @@ nsAboutCacheEntry::WriteCacheEntryDescription(nsICacheEntryDescriptor *descripto
|
||||
// Data Size
|
||||
s.Truncate();
|
||||
uint32_t dataSize;
|
||||
descriptor->GetStorageDataSize(&dataSize);
|
||||
if (NS_FAILED(entry->GetStorageDataSize(&dataSize)))
|
||||
dataSize = 0;
|
||||
s.AppendInt((int32_t)dataSize); // XXX nsICacheEntryInfo interfaces should be fixed.
|
||||
s.Append(NS_LITERAL_CSTRING(" B"));
|
||||
APPEND_ROW("Data size", s);
|
||||
|
||||
// Storage Policy
|
||||
|
||||
// XXX Stream Based?
|
||||
|
||||
// XXX Cache Device
|
||||
// File on disk
|
||||
nsCOMPtr<nsIFile> cacheFile;
|
||||
rv = descriptor->GetFile(getter_AddRefs(cacheFile));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsAutoString filePath;
|
||||
cacheFile->GetPath(filePath);
|
||||
APPEND_ROW("file on disk", NS_ConvertUTF16toUTF8(filePath));
|
||||
}
|
||||
else
|
||||
APPEND_ROW("file on disk", "none");
|
||||
// TODO - mayhemer
|
||||
// Here used to be a link to the disk file (in the old cache for entries that
|
||||
// did not fit any of the block files, in the new cache every time).
|
||||
// I'd rather have a small set of buttons here to action on the entry:
|
||||
// 1. save the content
|
||||
// 2. save as a complete HTTP response (response head, headers, content)
|
||||
// 3. doom the entry
|
||||
// A new bug(s) should be filed here.
|
||||
|
||||
// Security Info
|
||||
nsCOMPtr<nsISupports> securityInfo;
|
||||
descriptor->GetSecurityInfo(getter_AddRefs(securityInfo));
|
||||
entry->GetSecurityInfo(getter_AddRefs(securityInfo));
|
||||
if (securityInfo) {
|
||||
APPEND_ROW("Security", "This is a secure document.");
|
||||
} else {
|
||||
@ -306,47 +434,38 @@ nsAboutCacheEntry::WriteCacheEntryDescription(nsICacheEntryDescriptor *descripto
|
||||
buffer.AppendLiteral("</table>\n"
|
||||
"<hr/>\n"
|
||||
"<table>\n");
|
||||
// Meta Data
|
||||
// let's just look for some well known (HTTP) meta data tags, for now.
|
||||
|
||||
// Client ID
|
||||
nsXPIDLCString str2;
|
||||
descriptor->GetClientID(getter_Copies(str2));
|
||||
if (!str2.IsEmpty()) APPEND_ROW("Client", str2);
|
||||
|
||||
|
||||
mBuffer = &buffer; // make it available for VisitMetaDataElement().
|
||||
// nsCacheEntryDescriptor::VisitMetaData calls
|
||||
// nsCacheEntry.h VisitMetaDataElements, which returns
|
||||
// nsCacheMetaData::VisitElements, which calls
|
||||
// nsAboutCacheEntry::VisitMetaDataElement (below) in a loop.
|
||||
descriptor->VisitMetaData(this);
|
||||
mBuffer = &buffer; // make it available for OnMetaDataElement().
|
||||
entry->VisitMetaData(this);
|
||||
mBuffer = nullptr;
|
||||
|
||||
buffer.AppendLiteral("</table>\n");
|
||||
mOutputStream->Write(buffer.get(), buffer.Length(), &n);
|
||||
|
||||
buffer.Truncate();
|
||||
|
||||
// Provide a hexdump of the data
|
||||
if (dataSize) { // don't draw an <hr> if the Data Size is 0.
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
descriptor->OpenInputStream(0, getter_AddRefs(stream));
|
||||
if (stream) {
|
||||
buffer.AssignLiteral("<hr/>\n"
|
||||
"<pre>");
|
||||
uint32_t hexDumpState = 0;
|
||||
char chunk[4096];
|
||||
while(NS_SUCCEEDED(stream->Read(chunk, sizeof(chunk), &n)) &&
|
||||
n > 0) {
|
||||
HexDump(&hexDumpState, chunk, n, buffer);
|
||||
mOutputStream->Write(buffer.get(), buffer.Length(), &n);
|
||||
buffer.Truncate();
|
||||
}
|
||||
buffer.AssignLiteral("</pre>\n");
|
||||
mOutputStream->Write(buffer.get(), buffer.Length(), &n);
|
||||
}
|
||||
if (!dataSize) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
entry->OpenInputStream(0, getter_AddRefs(stream));
|
||||
if (!stream) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsInputStreamPump> pump;
|
||||
rv = nsInputStreamPump::Create(getter_AddRefs(pump), stream);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_OK; // just ignore
|
||||
}
|
||||
|
||||
rv = pump->AsyncRead(this, nullptr);
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_OK; // just ignore
|
||||
}
|
||||
|
||||
mWaitingForData = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -360,59 +479,12 @@ nsAboutCacheEntry::WriteCacheEntryUnavailable()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAboutCacheEntry::ParseURI(nsIURI *uri, nsCString &clientID,
|
||||
bool &streamBased, nsCString &key)
|
||||
{
|
||||
//
|
||||
// about:cache-entry?client=[string]&sb=[boolean]&key=[string]
|
||||
//
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString path;
|
||||
rv = uri->GetPath(path);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsACString::const_iterator i1, i2, i3, end;
|
||||
path.BeginReading(i1);
|
||||
path.EndReading(end);
|
||||
|
||||
i2 = end;
|
||||
if (!FindInReadable(NS_LITERAL_CSTRING("?client="), i1, i2))
|
||||
return NS_ERROR_FAILURE;
|
||||
// i2 points to the start of clientID
|
||||
|
||||
i1 = i2;
|
||||
i3 = end;
|
||||
if (!FindInReadable(NS_LITERAL_CSTRING("&sb="), i1, i3))
|
||||
return NS_ERROR_FAILURE;
|
||||
// i1 points to the end of clientID
|
||||
// i3 points to the start of isStreamBased
|
||||
|
||||
clientID.Assign(Substring(i2, i1));
|
||||
|
||||
i1 = i3;
|
||||
i2 = end;
|
||||
if (!FindInReadable(NS_LITERAL_CSTRING("&key="), i1, i2))
|
||||
return NS_ERROR_FAILURE;
|
||||
// i1 points to the end of isStreamBased
|
||||
// i2 points to the start of key
|
||||
|
||||
streamBased = FindCharInReadable('1', i3, i1);
|
||||
key.Assign(Substring(i2, end));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsICacheMetaDataVisitor implementation
|
||||
// nsICacheEntryMetaDataVisitor implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAboutCacheEntry::VisitMetaDataElement(const char * key,
|
||||
const char * value,
|
||||
bool * keepGoing)
|
||||
nsAboutCacheEntry::OnMetaDataElement(char const * key, char const * value)
|
||||
{
|
||||
mBuffer->AppendLiteral(" <tr>\n"
|
||||
" <th>");
|
||||
@ -425,38 +497,76 @@ nsAboutCacheEntry::VisitMetaDataElement(const char * key,
|
||||
mBuffer->AppendLiteral("</td>\n"
|
||||
" </tr>\n");
|
||||
|
||||
*keepGoing = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsICacheListener implementation
|
||||
// nsIStreamListener implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAboutCacheEntry::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry,
|
||||
nsCacheAccessMode access,
|
||||
nsresult status)
|
||||
nsAboutCacheEntry::OnStartRequest(nsIRequest *request, nsISupports *ctx)
|
||||
{
|
||||
nsresult rv;
|
||||
mHexDumpState = 0;
|
||||
|
||||
if (entry)
|
||||
rv = WriteCacheEntryDescription(entry);
|
||||
else
|
||||
rv = WriteCacheEntryUnavailable();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_NAMED_LITERAL_CSTRING(buffer, "<hr/>\n<pre>");
|
||||
uint32_t n;
|
||||
return mOutputStream->Write(buffer.get(), buffer.Length(), &n);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAboutCacheEntry::OnDataAvailable(nsIRequest *request, nsISupports *ctx,
|
||||
nsIInputStream *aInputStream,
|
||||
uint64_t aOffset,
|
||||
uint32_t aCount)
|
||||
{
|
||||
uint32_t n;
|
||||
return aInputStream->ReadSegments(
|
||||
&nsAboutCacheEntry::PrintCacheData, this, aCount, &n);
|
||||
}
|
||||
|
||||
// static
|
||||
NS_METHOD
|
||||
nsAboutCacheEntry::PrintCacheData(nsIInputStream *aInStream,
|
||||
void *aClosure,
|
||||
const char *aFromSegment,
|
||||
uint32_t aToOffset,
|
||||
uint32_t aCount,
|
||||
uint32_t *aWriteCount)
|
||||
{
|
||||
nsAboutCacheEntry *a = static_cast<nsAboutCacheEntry*>(aClosure);
|
||||
|
||||
nsCString buffer;
|
||||
HexDump(&a->mHexDumpState, aFromSegment, aCount, buffer);
|
||||
|
||||
uint32_t n;
|
||||
NS_NAMED_LITERAL_CSTRING(buffer, "</body>\n</html>\n");
|
||||
mOutputStream->Write(buffer.get(), buffer.Length(), &n);
|
||||
mOutputStream->Close();
|
||||
mOutputStream = nullptr;
|
||||
a->mOutputStream->Write(buffer.get(), buffer.Length(), &n);
|
||||
|
||||
*aWriteCount = aCount;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAboutCacheEntry::OnCacheEntryDoomed(nsresult status)
|
||||
nsAboutCacheEntry::OnStopRequest(nsIRequest *request, nsISupports *ctx,
|
||||
nsresult result)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
NS_NAMED_LITERAL_CSTRING(buffer, "</pre>\n");
|
||||
uint32_t n;
|
||||
mOutputStream->Write(buffer.get(), buffer.Length(), &n);
|
||||
|
||||
CloseContent();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsAboutCacheEntry::CloseContent()
|
||||
{
|
||||
NS_NAMED_LITERAL_CSTRING(buffer, "</body>\n</html>\n");
|
||||
uint32_t n;
|
||||
mOutputStream->Write(buffer.get(), buffer.Length(), &n);
|
||||
|
||||
mOutputStream->Close();
|
||||
mOutputStream = nullptr;
|
||||
}
|
||||
|
@ -7,27 +7,35 @@
|
||||
#define nsAboutCacheEntry_h__
|
||||
|
||||
#include "nsIAboutModule.h"
|
||||
#include "nsICacheListener.h"
|
||||
#include "nsICacheEntryDescriptor.h"
|
||||
#include "nsICacheEntryOpenCallback.h"
|
||||
#include "nsICacheEntry.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsIAsyncOutputStream;
|
||||
class nsIInputStream;
|
||||
class nsILoadContextInfo;
|
||||
class nsIURI;
|
||||
class nsCString;
|
||||
|
||||
class nsAboutCacheEntry : public nsIAboutModule
|
||||
, public nsICacheMetaDataVisitor
|
||||
, public nsICacheListener
|
||||
, public nsICacheEntryOpenCallback
|
||||
, public nsICacheEntryMetaDataVisitor
|
||||
, public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIABOUTMODULE
|
||||
NS_DECL_NSICACHEMETADATAVISITOR
|
||||
NS_DECL_NSICACHELISTENER
|
||||
NS_DECL_NSICACHEENTRYOPENCALLBACK
|
||||
NS_DECL_NSICACHEENTRYMETADATAVISITOR
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
||||
nsAboutCacheEntry()
|
||||
: mBuffer(nullptr)
|
||||
, mWaitingForData(false)
|
||||
, mHexDumpState(0)
|
||||
{}
|
||||
|
||||
virtual ~nsAboutCacheEntry() {}
|
||||
@ -35,13 +43,31 @@ public:
|
||||
private:
|
||||
nsresult GetContentStream(nsIURI *, nsIInputStream **);
|
||||
nsresult OpenCacheEntry(nsIURI *);
|
||||
nsresult WriteCacheEntryDescription(nsICacheEntryDescriptor *);
|
||||
nsresult OpenCacheEntry();
|
||||
nsresult WriteCacheEntryDescription(nsICacheEntry *);
|
||||
nsresult WriteCacheEntryUnavailable();
|
||||
nsresult ParseURI(nsIURI *, nsCString &, bool &, nsCString &);
|
||||
nsresult ParseURI(nsIURI *uri, nsACString &storageName,
|
||||
nsILoadContextInfo **loadInfo,
|
||||
nsCString &enahnceID, nsIURI **cacheUri);
|
||||
void CloseContent();
|
||||
|
||||
static NS_METHOD
|
||||
PrintCacheData(nsIInputStream *aInStream,
|
||||
void *aClosure,
|
||||
const char *aFromSegment,
|
||||
uint32_t aToOffset,
|
||||
uint32_t aCount,
|
||||
uint32_t *aWriteCount);
|
||||
|
||||
private:
|
||||
nsAutoCString mStorageName, mEnhanceId;
|
||||
nsCOMPtr<nsILoadContextInfo> mLoadInfo;
|
||||
nsCOMPtr<nsIURI> mCacheURI;
|
||||
|
||||
nsCString *mBuffer;
|
||||
nsCOMPtr<nsIAsyncOutputStream> mOutputStream;
|
||||
bool mWaitingForData;
|
||||
uint32_t mHexDumpState;
|
||||
};
|
||||
|
||||
#define NS_ABOUT_CACHE_ENTRY_MODULE_CID \
|
||||
|
@ -289,9 +289,9 @@ VisitCallback.prototype =
|
||||
if (!this.entries)
|
||||
this.notify();
|
||||
},
|
||||
onCacheEntryInfo: function(entry)
|
||||
onCacheEntryInfo: function(aURI, aIdEnhance, aDataSize, aFetchCount, aLastModifiedTime, aExpirationTime)
|
||||
{
|
||||
var key = entry.key;
|
||||
var key = (aIdEnhance ? (aIdEnhance + ":") : "") + aURI.asciiSpec;
|
||||
LOG_C2(this, "onCacheEntryInfo: key=" + key);
|
||||
|
||||
do_check_true(!!this.entries);
|
||||
|
@ -5,12 +5,17 @@ function run_test()
|
||||
var storage = getCacheStorage("disk");
|
||||
var mc = new MultipleCallbacks(4, function() {
|
||||
syncWithCacheIOThread(function() {
|
||||
|
||||
var expectedConsumption = newCacheBackEndUsed()
|
||||
? 4096
|
||||
: 48;
|
||||
|
||||
storage.asyncVisitStorage(
|
||||
// Test should store 4 entries
|
||||
new VisitCallback(4, 48, ["http://a/", "http://b/", "http://c/", "http://d/"], function() {
|
||||
new VisitCallback(4, expectedConsumption, ["http://a/", "http://b/", "http://c/", "http://d/"], function() {
|
||||
storage.asyncVisitStorage(
|
||||
// Still 4 entries expected, now don't walk them
|
||||
new VisitCallback(4, 48, null, function() {
|
||||
new VisitCallback(4, expectedConsumption, null, function() {
|
||||
finish_cache2_test();
|
||||
}),
|
||||
false
|
||||
|
@ -16,8 +16,8 @@ function run_test()
|
||||
new VisitCallback(1, 12, ["http://mem1/"], function() {
|
||||
storage = getCacheStorage("disk");
|
||||
storage.asyncVisitStorage(
|
||||
// Previous tests should store 4 disk entries + 1 memory entry
|
||||
new VisitCallback(5, 60, ["http://a/", "http://b/", "http://c/", "http://d/", "http://mem1/"], function() {
|
||||
// Previous tests should store 4 disk entries
|
||||
new VisitCallback(4, 4096, ["http://a/", "http://b/", "http://c/", "http://d/"], function() {
|
||||
finish_cache2_test();
|
||||
}),
|
||||
true
|
||||
|
@ -9,8 +9,13 @@ function run_test()
|
||||
storage.asyncVisitStorage(
|
||||
new VisitCallback(0, 0, [], function() {
|
||||
var storage = getCacheStorage("disk");
|
||||
|
||||
var expectedConsumption = newCacheBackEndUsed()
|
||||
? 2048
|
||||
: 24;
|
||||
|
||||
storage.asyncVisitStorage(
|
||||
new VisitCallback(2, 24, ["http://a/", "http://b/"], function() {
|
||||
new VisitCallback(2, expectedConsumption, ["http://a/", "http://b/"], function() {
|
||||
finish_cache2_test();
|
||||
}),
|
||||
true
|
||||
|
@ -8,10 +8,10 @@ function run_test()
|
||||
{
|
||||
var storage = getCacheStorage("disk", LoadContextInfo.default);
|
||||
storage.asyncVisitStorage(
|
||||
new VisitCallback(1, 12, ["http://an2/"], function() {
|
||||
new VisitCallback(1, 1024, ["http://an2/"], function() {
|
||||
storage = getCacheStorage("disk", LoadContextInfo.anonymous);
|
||||
storage.asyncVisitStorage(
|
||||
new VisitCallback(1, 12, ["http://an2/"], function() {
|
||||
new VisitCallback(1, 1024, ["http://an2/"], function() {
|
||||
finish_cache2_test();
|
||||
}),
|
||||
true
|
||||
@ -26,10 +26,10 @@ function run_test()
|
||||
syncWithCacheIOThread(function() {
|
||||
var storage = getCacheStorage("disk", LoadContextInfo.default);
|
||||
storage.asyncVisitStorage(
|
||||
new VisitCallback(2, 24, ["http://an2/", "anon&uri=http://an2/"], function() {
|
||||
new VisitCallback(2, 24, ["http://an2/"], function() {
|
||||
storage = getCacheStorage("disk", LoadContextInfo.anonymous);
|
||||
storage.asyncVisitStorage(
|
||||
new VisitCallback(0, 0, [], function() {
|
||||
new VisitCallback(0, 0, ["http://an2/"], function() {
|
||||
finish_cache2_test();
|
||||
}),
|
||||
true
|
||||
|
43
toolkit/components/aboutcache/content/aboutCache.js
Normal file
43
toolkit/components/aboutcache/content/aboutCache.js
Normal file
@ -0,0 +1,43 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// First, parse and save the incoming arguments ("?storage=name&context=key")
|
||||
// Note: window.location.search doesn't work with nsSimpleURIs used for about:* addresses.
|
||||
var search = window.location.href.match(/^.*\?(.*)$/);
|
||||
var searchParams = new URLSearchParams(search ? search[1] : '');
|
||||
var storage = searchParams.get('storage');
|
||||
var context = searchParams.get('context');
|
||||
|
||||
// The context is in a format as used by the HTTP cache v2 back end
|
||||
var [context, isAnon, isInBrowser, appId, isPrivate] = context.match(/(a,)?(b,)?(i\d+,)?(p,)?/);
|
||||
if (appId)
|
||||
appId = appId.match(/i(\d+),/)[1];
|
||||
|
||||
|
||||
function $(id) { return document.getElementById(id) || {}; }
|
||||
|
||||
// Initialize the context UI controls at the start according what we got in the "context=" argument
|
||||
addEventListener('DOMContentLoaded', function() {
|
||||
$('anon').checked = !!isAnon;
|
||||
$('inbrowser').checked = !!isInBrowser;
|
||||
$('appid').value = appId || '';
|
||||
$('priv').checked = !!isPrivate;
|
||||
}, false);
|
||||
|
||||
// When user presses the [Update] button, we build a new context key according the UI control
|
||||
// values and navigate to a new about:cache?storage=<name>&context=<key> URL.
|
||||
function navigate()
|
||||
{
|
||||
context = '';
|
||||
if ($('anon').checked)
|
||||
context += 'a,';
|
||||
if ($('inbrowser').checked)
|
||||
context += 'b,';
|
||||
if ($('appid').value)
|
||||
context += 'i' + $('appid').value + ',';
|
||||
if ($('priv').checked)
|
||||
context += 'p,';
|
||||
|
||||
window.location.href = 'about:cache?storage=' + storage + '&context=' + context;
|
||||
}
|
6
toolkit/components/aboutcache/jar.mn
Normal file
6
toolkit/components/aboutcache/jar.mn
Normal file
@ -0,0 +1,6 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
toolkit.jar:
|
||||
+ content/global/aboutCache.js (content/aboutCache.js)
|
7
toolkit/components/aboutcache/moz.build
Normal file
7
toolkit/components/aboutcache/moz.build
Normal file
@ -0,0 +1,7 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
@ -9,6 +9,7 @@ if CONFIG['MOZ_ENABLE_XREMOTE']:
|
||||
PARALLEL_DIRS += ['remote']
|
||||
|
||||
PARALLEL_DIRS += [
|
||||
'aboutcache',
|
||||
'aboutmemory',
|
||||
'alerts',
|
||||
'apppicker',
|
||||
|
Loading…
Reference in New Issue
Block a user