mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1032254 - Provide a way to pin resources in the http cache r=honzab
This commit is contained in:
parent
49c394e147
commit
aefe552c95
@ -17,7 +17,7 @@ interface nsIFile;
|
||||
* 3) Support for uniquely identifying cached data in cases when the URL
|
||||
* is insufficient (e.g., HTTP form submission).
|
||||
*/
|
||||
[scriptable, uuid(436b939d-e391-48e5-ba64-ab0e496e3400)]
|
||||
[scriptable, uuid(dd1d6122-5ecf-4fe4-8f0f-995e7ab3121a)]
|
||||
interface nsICachingChannel : nsICacheInfoChannel
|
||||
{
|
||||
/**
|
||||
@ -53,6 +53,11 @@ interface nsICachingChannel : nsICacheInfoChannel
|
||||
*/
|
||||
attribute boolean cacheOnlyMetadata;
|
||||
|
||||
/**
|
||||
* Tells the channel to use the pinning storage.
|
||||
*/
|
||||
attribute boolean pin;
|
||||
|
||||
/**************************************************************************
|
||||
* Caching channel specific load flags:
|
||||
*/
|
||||
|
@ -163,7 +163,8 @@ NS_IMPL_ISUPPORTS(CacheEntry,
|
||||
CacheEntry::CacheEntry(const nsACString& aStorageID,
|
||||
nsIURI* aURI,
|
||||
const nsACString& aEnhanceID,
|
||||
bool aUseDisk)
|
||||
bool aUseDisk,
|
||||
uint32_t aPinningAppId)
|
||||
: mFrecency(0)
|
||||
, mSortingExpirationTime(uint32_t(-1))
|
||||
, mLock("CacheEntry")
|
||||
@ -172,6 +173,7 @@ CacheEntry::CacheEntry(const nsACString& aStorageID,
|
||||
, mEnhanceID(aEnhanceID)
|
||||
, mStorageID(aStorageID)
|
||||
, mUseDisk(aUseDisk)
|
||||
, mPinningAppId(aPinningAppId)
|
||||
, mIsDoomed(false)
|
||||
, mSecurityInfoLoaded(false)
|
||||
, mPreventCallbacks(false)
|
||||
@ -341,7 +343,8 @@ bool CacheEntry::Load(bool aTruncate, bool aPriority)
|
||||
// as a new one.
|
||||
// 2. When this is a memory-only entry, check there is a disk file.
|
||||
// If there is or could be, doom that file.
|
||||
if ((!aTruncate || !mUseDisk) && NS_SUCCEEDED(rv)) {
|
||||
if ((!aTruncate || !mUseDisk) && NS_SUCCEEDED(rv) &&
|
||||
!mPinningAppId) {
|
||||
// Check the index right now to know we have or have not the entry
|
||||
// as soon as possible.
|
||||
CacheIndex::EntryStatus status;
|
||||
@ -391,6 +394,7 @@ bool CacheEntry::Load(bool aTruncate, bool aPriority)
|
||||
rv = mFile->Init(fileKey,
|
||||
aTruncate,
|
||||
!mUseDisk,
|
||||
mPinningAppId,
|
||||
aPriority,
|
||||
directLoad ? nullptr : this);
|
||||
}
|
||||
@ -486,6 +490,7 @@ already_AddRefed<CacheEntryHandle> CacheEntry::ReopenTruncated(bool aMemoryOnly,
|
||||
nsresult rv = CacheStorageService::Self()->AddStorageEntry(
|
||||
GetStorageID(), GetURI(), GetEnhanceID(),
|
||||
mUseDisk && !aMemoryOnly,
|
||||
mPinningAppId,
|
||||
true, // always create
|
||||
true, // truncate existing (this one)
|
||||
getter_AddRefs(handle));
|
||||
|
@ -55,7 +55,7 @@ public:
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
CacheEntry(const nsACString& aStorageID, nsIURI* aURI, const nsACString& aEnhanceID,
|
||||
bool aUseDisk);
|
||||
bool aUseDisk, uint32_t aPinningAppId);
|
||||
|
||||
void AsyncOpen(nsICacheEntryOpenCallback* aCallback, uint32_t aFlags);
|
||||
|
||||
@ -276,6 +276,9 @@ private:
|
||||
// Whether it's allowed to persist the data to disk
|
||||
bool const mUseDisk;
|
||||
|
||||
// AppId of an app that wants this entry be pinned
|
||||
uint32_t const mPinningAppId;
|
||||
|
||||
// Set when entry is doomed with AsyncDoom() or DoomAlreadyRemoved().
|
||||
// Left as a standalone flag to not bother with locking (there is no need).
|
||||
bool mIsDoomed;
|
||||
|
@ -212,6 +212,7 @@ nsresult
|
||||
CacheFile::Init(const nsACString &aKey,
|
||||
bool aCreateNew,
|
||||
bool aMemoryOnly,
|
||||
uint32_t aPinningAppID,
|
||||
bool aPriority,
|
||||
CacheFileListener *aCallback)
|
||||
{
|
||||
@ -266,7 +267,7 @@ CacheFile::Init(const nsACString &aKey,
|
||||
|
||||
mOpeningFile = true;
|
||||
mListener = aCallback;
|
||||
rv = CacheFileIOManager::OpenFile(mKey, flags, this);
|
||||
rv = CacheFileIOManager::OpenFile(mKey, aPinningAppID, flags, this);
|
||||
if (NS_FAILED(rv)) {
|
||||
mListener = nullptr;
|
||||
mOpeningFile = false;
|
||||
|
@ -56,6 +56,7 @@ public:
|
||||
nsresult Init(const nsACString &aKey,
|
||||
bool aCreateNew,
|
||||
bool aMemoryOnly,
|
||||
uint32_t aPinningAppID,
|
||||
bool aPriority,
|
||||
CacheFileListener *aCallback);
|
||||
|
||||
@ -103,6 +104,10 @@ public:
|
||||
void Key(nsACString& aKey) { aKey = mKey; }
|
||||
bool IsDoomed();
|
||||
bool IsWriteInProgress();
|
||||
CacheFileIOManager* Manager()
|
||||
{
|
||||
return mHandle ? mHandle->Manager() : nullptr;
|
||||
}
|
||||
|
||||
// Memory reporting
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
|
@ -398,7 +398,7 @@ CacheFileContextEvictor::GetContextFile(nsILoadContextInfo *aLoadContextInfo,
|
||||
leafName.AssignLiteral(CONTEXT_EVICTION_PREFIX);
|
||||
|
||||
nsAutoCString keyPrefix;
|
||||
CacheFileUtils::AppendKeyPrefix(aLoadContextInfo, keyPrefix);
|
||||
CacheFileUtils::AppendKeyPrefix(aLoadContextInfo, false, keyPrefix);
|
||||
|
||||
nsAutoCString data64;
|
||||
rv = Base64Encode(keyPrefix, data64);
|
||||
|
@ -108,8 +108,9 @@ NS_INTERFACE_MAP_BEGIN(CacheFileHandle)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END_THREADSAFE
|
||||
|
||||
CacheFileHandle::CacheFileHandle(const SHA1Sum::Hash *aHash, bool aPriority)
|
||||
: mHash(aHash)
|
||||
CacheFileHandle::CacheFileHandle(CacheFileIOManager* aManager, const SHA1Sum::Hash *aHash, bool aPriority)
|
||||
: mManager(aManager)
|
||||
, mHash(aHash)
|
||||
, mIsDoomed(false)
|
||||
, mPriority(aPriority)
|
||||
, mClosed(false)
|
||||
@ -123,8 +124,9 @@ CacheFileHandle::CacheFileHandle(const SHA1Sum::Hash *aHash, bool aPriority)
|
||||
, this, LOGSHA1(aHash)));
|
||||
}
|
||||
|
||||
CacheFileHandle::CacheFileHandle(const nsACString &aKey, bool aPriority)
|
||||
: mHash(nullptr)
|
||||
CacheFileHandle::CacheFileHandle(CacheFileIOManager* aManager, const nsACString &aKey, bool aPriority)
|
||||
: mManager(aManager)
|
||||
, mHash(nullptr)
|
||||
, mIsDoomed(false)
|
||||
, mPriority(aPriority)
|
||||
, mClosed(false)
|
||||
@ -145,9 +147,8 @@ CacheFileHandle::~CacheFileHandle()
|
||||
|
||||
MOZ_ASSERT(CacheFileIOManager::IsOnIOThreadOrCeased());
|
||||
|
||||
nsRefPtr<CacheFileIOManager> ioMan = CacheFileIOManager::gInstance;
|
||||
if (!IsClosed() && ioMan) {
|
||||
ioMan->CloseHandleInternal(this);
|
||||
if (!IsClosed() && mManager) {
|
||||
mManager->CloseHandleInternal(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,7 +296,8 @@ CacheFileHandles::HandleHashKey::SizeOfExcludingThis(mozilla::MallocSizeOf mallo
|
||||
* CacheFileHandles
|
||||
*****************************************************************************/
|
||||
|
||||
CacheFileHandles::CacheFileHandles()
|
||||
CacheFileHandles::CacheFileHandles(CacheFileIOManager* aManager)
|
||||
: mManager(aManager)
|
||||
{
|
||||
LOG(("CacheFileHandles::CacheFileHandles() [this=%p]", this));
|
||||
MOZ_COUNT_CTOR(CacheFileHandles);
|
||||
@ -376,7 +378,7 @@ CacheFileHandles::NewHandle(const SHA1Sum::Hash *aHash,
|
||||
entry->AssertHandlesState();
|
||||
#endif
|
||||
|
||||
nsRefPtr<CacheFileHandle> handle = new CacheFileHandle(entry->Hash(), aPriority);
|
||||
nsRefPtr<CacheFileHandle> handle = new CacheFileHandle(mManager, entry->Hash(), aPriority);
|
||||
entry->AddHandle(handle);
|
||||
|
||||
LOG(("CacheFileHandles::NewHandle() hash=%08x%08x%08x%08x%08x "
|
||||
@ -544,14 +546,15 @@ protected:
|
||||
|
||||
class OpenFileEvent : public nsRunnable {
|
||||
public:
|
||||
OpenFileEvent(const nsACString &aKey, uint32_t aFlags,
|
||||
OpenFileEvent(CacheFileIOManager *aIOMan,
|
||||
const nsACString &aKey, uint32_t aFlags,
|
||||
CacheFileIOListener *aCallback)
|
||||
: mFlags(aFlags)
|
||||
, mCallback(aCallback)
|
||||
, mIOMan(aIOMan)
|
||||
, mKey(aKey)
|
||||
{
|
||||
MOZ_COUNT_CTOR(OpenFileEvent);
|
||||
mIOMan = CacheFileIOManager::gInstance;
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -629,7 +632,7 @@ public:
|
||||
if (mHandle->IsClosed()) {
|
||||
rv = NS_ERROR_NOT_INITIALIZED;
|
||||
} else {
|
||||
rv = CacheFileIOManager::gInstance->ReadInternal(
|
||||
rv = mHandle->Manager()->ReadInternal(
|
||||
mHandle, mOffset, mBuf, mCount);
|
||||
}
|
||||
|
||||
@ -679,11 +682,11 @@ public:
|
||||
if (mHandle->IsClosed()) {
|
||||
rv = NS_ERROR_NOT_INITIALIZED;
|
||||
} else {
|
||||
rv = CacheFileIOManager::gInstance->WriteInternal(
|
||||
rv = mHandle->Manager()->WriteInternal(
|
||||
mHandle, mOffset, mBuf, mCount, mValidate, mTruncate);
|
||||
if (NS_FAILED(rv) && !mCallback) {
|
||||
// No listener is going to handle the error, doom the file
|
||||
CacheFileIOManager::gInstance->DoomFileInternal(mHandle);
|
||||
mHandle->Manager()->DoomFileInternal(mHandle);
|
||||
}
|
||||
}
|
||||
if (mCallback) {
|
||||
@ -730,7 +733,7 @@ public:
|
||||
if (mHandle->IsClosed()) {
|
||||
rv = NS_ERROR_NOT_INITIALIZED;
|
||||
} else {
|
||||
rv = CacheFileIOManager::gInstance->DoomFileInternal(mHandle);
|
||||
rv = mHandle->Manager()->DoomFileInternal(mHandle);
|
||||
}
|
||||
|
||||
if (mCallback) {
|
||||
@ -749,8 +752,10 @@ protected:
|
||||
class DoomFileByKeyEvent : public nsRunnable {
|
||||
public:
|
||||
DoomFileByKeyEvent(const nsACString &aKey,
|
||||
CacheFileIOManager *aManager,
|
||||
CacheFileIOListener *aCallback)
|
||||
: mCallback(aCallback)
|
||||
, mIOMan(aManager)
|
||||
{
|
||||
MOZ_COUNT_CTOR(DoomFileByKeyEvent);
|
||||
|
||||
@ -758,7 +763,7 @@ public:
|
||||
sum.update(aKey.BeginReading(), aKey.Length());
|
||||
sum.finish(mHash);
|
||||
|
||||
mIOMan = CacheFileIOManager::gInstance;
|
||||
mIOMan = aManager;
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -810,7 +815,7 @@ public:
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
if (mHandle->mFD && !mHandle->IsClosed()) {
|
||||
CacheFileIOManager::gInstance->ReleaseNSPRHandleInternal(mHandle);
|
||||
mHandle->Manager()->ReleaseNSPRHandleInternal(mHandle);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -846,7 +851,7 @@ public:
|
||||
if (mHandle->IsClosed()) {
|
||||
rv = NS_ERROR_NOT_INITIALIZED;
|
||||
} else {
|
||||
rv = CacheFileIOManager::gInstance->TruncateSeekSetEOFInternal(
|
||||
rv = mHandle->Manager()->TruncateSeekSetEOFInternal(
|
||||
mHandle, mTruncatePos, mEOFPos);
|
||||
}
|
||||
|
||||
@ -889,8 +894,7 @@ public:
|
||||
if (mHandle->IsClosed()) {
|
||||
rv = NS_ERROR_NOT_INITIALIZED;
|
||||
} else {
|
||||
rv = CacheFileIOManager::gInstance->RenameFileInternal(mHandle,
|
||||
mNewName);
|
||||
rv = mHandle->Manager()->RenameFileInternal(mHandle, mNewName);
|
||||
}
|
||||
|
||||
if (mCallback) {
|
||||
@ -1021,8 +1025,7 @@ public:
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
nsRefPtr<CacheFileIOManager> ioMan = CacheFileIOManager::gInstance;
|
||||
if (!ioMan) {
|
||||
if (!mIOMan) {
|
||||
NS_WARNING("CacheFileIOManager already gone in MetadataWriteScheduleEvent::Run()");
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1030,13 +1033,13 @@ public:
|
||||
switch (mMode)
|
||||
{
|
||||
case SCHEDULE:
|
||||
ioMan->ScheduleMetadataWriteInternal(mFile);
|
||||
mIOMan->ScheduleMetadataWriteInternal(mFile);
|
||||
break;
|
||||
case UNSCHEDULE:
|
||||
ioMan->UnscheduleMetadataWriteInternal(mFile);
|
||||
mIOMan->UnscheduleMetadataWriteInternal(mFile);
|
||||
break;
|
||||
case SHUTDOWN:
|
||||
ioMan->ShutdownMetadataWriteSchedulingInternal();
|
||||
mIOMan->ShutdownMetadataWriteSchedulingInternal();
|
||||
break;
|
||||
}
|
||||
return NS_OK;
|
||||
@ -1048,20 +1051,19 @@ CacheFileIOManager * CacheFileIOManager::gInstance = nullptr;
|
||||
NS_IMPL_ISUPPORTS(CacheFileIOManager, nsITimerCallback)
|
||||
|
||||
CacheFileIOManager::CacheFileIOManager()
|
||||
: mShuttingDown(false)
|
||||
: mKind(UNKNOWN)
|
||||
, mShuttingDown(false)
|
||||
, mTreeCreated(false)
|
||||
, mHandles(this)
|
||||
, mOverLimitEvicting(false)
|
||||
, mRemovingTrashDirs(false)
|
||||
{
|
||||
LOG(("CacheFileIOManager::CacheFileIOManager [this=%p]", this));
|
||||
MOZ_COUNT_CTOR(CacheFileIOManager);
|
||||
MOZ_ASSERT(!gInstance, "multiple CacheFileIOManager instances!");
|
||||
}
|
||||
|
||||
CacheFileIOManager::~CacheFileIOManager()
|
||||
{
|
||||
LOG(("CacheFileIOManager::~CacheFileIOManager [this=%p]", this));
|
||||
MOZ_COUNT_DTOR(CacheFileIOManager);
|
||||
}
|
||||
|
||||
// static
|
||||
@ -1082,6 +1084,10 @@ CacheFileIOManager::Init()
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ioMan.swap(gInstance);
|
||||
|
||||
// Ensure pinning managers static to avoid concurrent thread initiation.
|
||||
Pinning::Self();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1090,6 +1096,7 @@ CacheFileIOManager::InitInternal()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
mKind = GENERAL;
|
||||
mIOThread = new CacheIOThread();
|
||||
|
||||
rv = mIOThread->Init();
|
||||
@ -1101,6 +1108,38 @@ CacheFileIOManager::InitInternal()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CacheFileIOManager::InitAsPinning(uint32_t aAppId, nsIFile* aProfileDir)
|
||||
{
|
||||
if (!aProfileDir || !gInstance) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
mKind = PINNING;
|
||||
|
||||
MOZ_ASSERT(!mCacheDirectory);
|
||||
MOZ_ASSERT(!mIOThread);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
rv = aProfileDir->Clone(getter_AddRefs(mCacheDirectory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mCacheDirectory->Append(NS_LITERAL_STRING("cache2"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString appIdString;
|
||||
appIdString.AppendInt(aAppId);
|
||||
rv = mCacheDirectory->Append(appIdString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mIOThread = gInstance->mIOThread;
|
||||
|
||||
mStartTime = TimeStamp::NowLoRes();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
CacheFileIOManager::Shutdown()
|
||||
@ -1133,6 +1172,7 @@ CacheFileIOManager::Shutdown()
|
||||
|
||||
MOZ_ASSERT(gInstance->mHandles.HandleCount() == 0);
|
||||
MOZ_ASSERT(gInstance->mHandlesByLastUsed.Length() == 0);
|
||||
MOZ_ASSERT(Pinning::Self()->Length() == 0);
|
||||
|
||||
if (gInstance->mIOThread) {
|
||||
gInstance->mIOThread->Shutdown();
|
||||
@ -1143,11 +1183,14 @@ CacheFileIOManager::Shutdown()
|
||||
if (CacheObserver::ClearCacheOnShutdown()) {
|
||||
Telemetry::AutoTimer<Telemetry::NETWORK_DISK_CACHE2_SHUTDOWN_CLEAR_PRIVATE> totalTimer;
|
||||
gInstance->SyncRemoveAllCacheFiles();
|
||||
// mayhemer: should this apply to pinning apps as well? followup sufficient...
|
||||
}
|
||||
|
||||
nsRefPtr<CacheFileIOManager> ioMan;
|
||||
ioMan.swap(gInstance);
|
||||
|
||||
Pinning::Self()->Destroy();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1184,7 +1227,8 @@ CacheFileIOManager::ShutdownInternal()
|
||||
}
|
||||
|
||||
if (!h->IsSpecialFile() && !h->mIsDoomed &&
|
||||
(h->mInvalid || !h->mFileExists)) {
|
||||
(h->mInvalid || !h->mFileExists) &&
|
||||
mKind != PINNING) {
|
||||
CacheIndex::RemoveEntry(h->Hash());
|
||||
}
|
||||
|
||||
@ -1215,6 +1259,8 @@ CacheFileIOManager::ShutdownInternal()
|
||||
mTrashDirEnumerator = nullptr;
|
||||
}
|
||||
|
||||
Pinning::Self()->ShutdownInternal();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1299,6 +1345,8 @@ CacheFileIOManager::OnProfile()
|
||||
CacheIndex::Init(ioMan->mCacheDirectory);
|
||||
}
|
||||
|
||||
Pinning::Self()->OnProfile();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1365,9 +1413,11 @@ CacheFileIOManager::IsShutdown()
|
||||
nsresult
|
||||
CacheFileIOManager::ScheduleMetadataWrite(CacheFile * aFile)
|
||||
{
|
||||
// This can freely go to the global IO manager, no need for distinction
|
||||
// since the timer code calls on the file that delegates to its handle
|
||||
// which is already correctly bound to the correct manager.
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
NS_ENSURE_TRUE(ioMan, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
NS_ENSURE_TRUE(!ioMan->mShuttingDown, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsRefPtr<MetadataWriteScheduleEvent> event = new MetadataWriteScheduleEvent(
|
||||
@ -1409,7 +1459,6 @@ CacheFileIOManager::UnscheduleMetadataWrite(CacheFile * aFile)
|
||||
{
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
NS_ENSURE_TRUE(ioMan, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
NS_ENSURE_TRUE(!ioMan->mShuttingDown, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsRefPtr<MetadataWriteScheduleEvent> event = new MetadataWriteScheduleEvent(
|
||||
@ -1472,9 +1521,19 @@ CacheFileIOManager::ShutdownMetadataWriteSchedulingInternal()
|
||||
NS_IMETHODIMP
|
||||
CacheFileIOManager::Notify(nsITimer * aTimer)
|
||||
{
|
||||
MOZ_ASSERT(IsOnIOThreadOrCeased());
|
||||
MOZ_ASSERT(mMetadataWritesTimer == aTimer);
|
||||
if (mTrashTimer == aTimer) {
|
||||
LOG(("CacheFileIOManager, trash timer [this=%p]", this));
|
||||
|
||||
mTrashTimer = nullptr;
|
||||
StartRemovingTrash();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mMetadataWritesTimer == aTimer) {
|
||||
LOG(("CacheFileIOManager, metadata write timer [this=%p]", this));
|
||||
|
||||
MOZ_ASSERT(IsOnIOThreadOrCeased());
|
||||
mMetadataWritesTimer = nullptr;
|
||||
|
||||
nsTArray<nsRefPtr<CacheFile> > files;
|
||||
@ -1487,23 +1546,38 @@ CacheFileIOManager::Notify(nsITimer * aTimer)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(false, "Unexpected timer in CacheFileIOManager::Notify()!");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
CacheFileIOManager::OpenFile(const nsACString &aKey,
|
||||
uint32_t aFlags, CacheFileIOListener *aCallback)
|
||||
{
|
||||
return OpenFile(aKey, nsILoadContextInfo::NO_APP_ID, aFlags, aCallback);
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
CacheFileIOManager::OpenFile(const nsACString &aKey, uint32_t aPinningAppId,
|
||||
uint32_t aFlags, CacheFileIOListener *aCallback)
|
||||
{
|
||||
LOG(("CacheFileIOManager::OpenFile() [key=%s, flags=%d, listener=%p]",
|
||||
PromiseFlatCString(aKey).get(), aFlags, aCallback));
|
||||
|
||||
nsresult rv;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
if (aPinningAppId != nsILoadContextInfo::NO_APP_ID && ioMan) {
|
||||
ioMan = Pinning::Self()->Get(aPinningAppId);
|
||||
}
|
||||
|
||||
if (!ioMan) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
bool priority = aFlags & CacheFileIOManager::PRIORITY;
|
||||
nsRefPtr<OpenFileEvent> ev = new OpenFileEvent(aKey, aFlags, aCallback);
|
||||
nsRefPtr<OpenFileEvent> ev = new OpenFileEvent(ioMan, aKey, aFlags, aCallback);
|
||||
rv = ioMan->mIOThread->Dispatch(ev, priority
|
||||
? CacheIOThread::OPEN_PRIORITY
|
||||
: CacheIOThread::OPEN);
|
||||
@ -1557,7 +1631,9 @@ CacheFileIOManager::OpenFileInternal(const SHA1Sum::Hash *aHash,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (exists) {
|
||||
if (mKind != PINNING) {
|
||||
CacheIndex::RemoveEntry(aHash);
|
||||
}
|
||||
|
||||
LOG(("CacheFileIOManager::OpenFileInternal() - Removing old file from "
|
||||
"disk"));
|
||||
@ -1569,7 +1645,10 @@ CacheFileIOManager::OpenFileInternal(const SHA1Sum::Hash *aHash,
|
||||
}
|
||||
}
|
||||
|
||||
if (mKind != PINNING) {
|
||||
CacheIndex::AddEntry(aHash);
|
||||
}
|
||||
|
||||
handle->mFile.swap(file);
|
||||
handle->mFileSize = 0;
|
||||
}
|
||||
@ -1594,10 +1673,13 @@ CacheFileIOManager::OpenFileInternal(const SHA1Sum::Hash *aHash,
|
||||
"entry was evicted by EvictByContext()"));
|
||||
exists = false;
|
||||
file->Remove(false);
|
||||
|
||||
if (mKind != PINNING) {
|
||||
CacheIndex::RemoveEntry(aHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists && (aFlags & (OPEN | CREATE | CREATE_NEW)) == OPEN) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
@ -1612,12 +1694,16 @@ CacheFileIOManager::OpenFileInternal(const SHA1Sum::Hash *aHash,
|
||||
|
||||
handle->mFileExists = true;
|
||||
|
||||
if (mKind != PINNING) {
|
||||
CacheIndex::EnsureEntryExists(aHash);
|
||||
}
|
||||
} else {
|
||||
handle->mFileSize = 0;
|
||||
|
||||
if (mKind != PINNING) {
|
||||
CacheIndex::AddEntry(aHash);
|
||||
}
|
||||
}
|
||||
|
||||
handle->mFile.swap(file);
|
||||
handle.swap(*_retval);
|
||||
@ -1664,7 +1750,7 @@ CacheFileIOManager::OpenSpecialFileInternal(const nsACString &aKey,
|
||||
handle = nullptr;
|
||||
}
|
||||
|
||||
handle = new CacheFileHandle(aKey, aFlags & PRIORITY);
|
||||
handle = new CacheFileHandle(this, aKey, aFlags & PRIORITY);
|
||||
mSpecialHandles.AppendElement(handle);
|
||||
|
||||
bool exists;
|
||||
@ -1699,7 +1785,7 @@ CacheFileIOManager::OpenSpecialFileInternal(const nsACString &aKey,
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
handle = new CacheFileHandle(aKey, aFlags & PRIORITY);
|
||||
handle = new CacheFileHandle(this, aKey, aFlags & PRIORITY);
|
||||
mSpecialHandles.AppendElement(handle);
|
||||
|
||||
if (exists) {
|
||||
@ -1740,7 +1826,8 @@ CacheFileIOManager::CloseHandleInternal(CacheFileHandle *aHandle)
|
||||
}
|
||||
|
||||
if (!aHandle->IsSpecialFile() && !aHandle->mIsDoomed &&
|
||||
(aHandle->mInvalid || !aHandle->mFileExists)) {
|
||||
(aHandle->mInvalid || !aHandle->mFileExists) &&
|
||||
mKind != PINNING) {
|
||||
CacheIndex::RemoveEntry(aHandle->Hash());
|
||||
}
|
||||
|
||||
@ -1766,7 +1853,7 @@ CacheFileIOManager::Read(CacheFileHandle *aHandle, int64_t aOffset,
|
||||
"listener=%p]", aHandle, aOffset, aCount, aCallback));
|
||||
|
||||
nsresult rv;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = aHandle->Manager();
|
||||
|
||||
if (aHandle->IsClosed() || !ioMan) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
@ -1833,7 +1920,7 @@ CacheFileIOManager::Write(CacheFileHandle *aHandle, int64_t aOffset,
|
||||
aValidate, aTruncate, aCallback));
|
||||
|
||||
nsresult rv;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = aHandle->Manager();
|
||||
|
||||
if (aHandle->IsClosed() || !ioMan) {
|
||||
if (!aCallback) {
|
||||
@ -1950,7 +2037,7 @@ CacheFileIOManager::WriteInternal(CacheFileHandle *aHandle, int64_t aOffset,
|
||||
uint32_t newSizeInK = aHandle->FileSizeInK();
|
||||
|
||||
if (oldSizeInK != newSizeInK && !aHandle->IsDoomed() &&
|
||||
!aHandle->IsSpecialFile()) {
|
||||
!aHandle->IsSpecialFile() && mKind != PINNING) {
|
||||
CacheIndex::UpdateEntry(aHandle->Hash(), nullptr, nullptr, &newSizeInK);
|
||||
|
||||
if (oldSizeInK < newSizeInK) {
|
||||
@ -1980,7 +2067,7 @@ CacheFileIOManager::DoomFile(CacheFileHandle *aHandle,
|
||||
aHandle, aCallback));
|
||||
|
||||
nsresult rv;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = aHandle->Manager();
|
||||
|
||||
if (aHandle->IsClosed() || !ioMan) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
@ -2037,7 +2124,7 @@ CacheFileIOManager::DoomFileInternal(CacheFileHandle *aHandle)
|
||||
}
|
||||
}
|
||||
|
||||
if (!aHandle->IsSpecialFile()) {
|
||||
if (!aHandle->IsSpecialFile() && mKind != PINNING) {
|
||||
CacheIndex::RemoveEntry(aHandle->Hash());
|
||||
}
|
||||
|
||||
@ -2046,12 +2133,12 @@ CacheFileIOManager::DoomFileInternal(CacheFileHandle *aHandle)
|
||||
if (!aHandle->IsSpecialFile()) {
|
||||
nsRefPtr<CacheStorageService> storageService = CacheStorageService::Self();
|
||||
if (storageService) {
|
||||
nsAutoCString idExtension, url;
|
||||
CacheFileUtils::KeyInfo keyInfo;
|
||||
nsCOMPtr<nsILoadContextInfo> info =
|
||||
CacheFileUtils::ParseKey(aHandle->Key(), &idExtension, &url);
|
||||
CacheFileUtils::ParseKey(aHandle->Key(), &keyInfo);
|
||||
MOZ_ASSERT(info);
|
||||
if (info) {
|
||||
storageService->CacheFileDoomed(info, idExtension, url);
|
||||
storageService->CacheFileDoomed(info, &keyInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2067,14 +2154,21 @@ CacheFileIOManager::DoomFileByKey(const nsACString &aKey,
|
||||
LOG(("CacheFileIOManager::DoomFileByKey() [key=%s, listener=%p]",
|
||||
PromiseFlatCString(aKey).get(), aCallback));
|
||||
|
||||
CacheFileUtils::KeyInfo keyInfo;
|
||||
nsCOMPtr<nsILoadContextInfo> info = CacheFileUtils::ParseKey(aKey, &keyInfo);
|
||||
|
||||
nsresult rv;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
|
||||
if (keyInfo.mPinningStorage && ioMan) {
|
||||
ioMan = Pinning::Self()->Get(info->AppId());
|
||||
}
|
||||
|
||||
if (!ioMan) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
nsRefPtr<DoomFileByKeyEvent> ev = new DoomFileByKeyEvent(aKey, aCallback);
|
||||
nsRefPtr<DoomFileByKeyEvent> ev = new DoomFileByKeyEvent(aKey, ioMan, aCallback);
|
||||
rv = ioMan->mIOThread->DispatchAfterPendingOpens(ev);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -2131,7 +2225,9 @@ CacheFileIOManager::DoomFileByKeyInternal(const SHA1Sum::Hash *aHash)
|
||||
"[rv=0x%08x]", rv));
|
||||
}
|
||||
|
||||
if (mKind != PINNING) {
|
||||
CacheIndex::RemoveEntry(aHash);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2143,7 +2239,7 @@ CacheFileIOManager::ReleaseNSPRHandle(CacheFileHandle *aHandle)
|
||||
LOG(("CacheFileIOManager::ReleaseNSPRHandle() [handle=%p]", aHandle));
|
||||
|
||||
nsresult rv;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = aHandle->Manager();
|
||||
|
||||
if (aHandle->IsClosed() || !ioMan) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
@ -2165,7 +2261,7 @@ CacheFileIOManager::ReleaseNSPRHandleInternal(CacheFileHandle *aHandle)
|
||||
MOZ_ASSERT(aHandle->mFD);
|
||||
|
||||
DebugOnly<bool> found;
|
||||
found = mHandlesByLastUsed.RemoveElement(aHandle);
|
||||
found = gInstance->mHandlesByLastUsed.RemoveElement(aHandle);
|
||||
MOZ_ASSERT(found);
|
||||
|
||||
PR_Close(aHandle->mFD);
|
||||
@ -2184,7 +2280,7 @@ CacheFileIOManager::TruncateSeekSetEOF(CacheFileHandle *aHandle,
|
||||
"EOFPos=%lld, listener=%p]", aHandle, aTruncatePos, aEOFPos, aCallback));
|
||||
|
||||
nsresult rv;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = aHandle->Manager();
|
||||
|
||||
if (aHandle->IsClosed() || !ioMan) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
@ -2238,19 +2334,19 @@ CacheFileIOManager::GetEntryInfo(const SHA1Sum::Hash *aHash,
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// mayhemer: This method should take aPinningAppId argument.
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
if (!ioMan) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
nsAutoCString enhanceId;
|
||||
nsAutoCString uriSpec;
|
||||
CacheFileUtils::KeyInfo keyInfo;
|
||||
|
||||
nsRefPtr<CacheFileHandle> handle;
|
||||
ioMan->mHandles.GetHandle(aHash, getter_AddRefs(handle));
|
||||
if (handle) {
|
||||
nsRefPtr<nsILoadContextInfo> info =
|
||||
CacheFileUtils::ParseKey(handle->Key(), &enhanceId, &uriSpec);
|
||||
CacheFileUtils::ParseKey(handle->Key(), &keyInfo);
|
||||
|
||||
MOZ_ASSERT(info);
|
||||
if (!info) {
|
||||
@ -2263,7 +2359,7 @@ CacheFileIOManager::GetEntryInfo(const SHA1Sum::Hash *aHash,
|
||||
}
|
||||
|
||||
// Invokes OnCacheEntryInfo when an existing entry is found
|
||||
if (service->GetCacheEntryInfo(info, enhanceId, uriSpec, aCallback)) {
|
||||
if (service->GetCacheEntryInfo(info, &keyInfo, aCallback)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2287,7 +2383,7 @@ CacheFileIOManager::GetEntryInfo(const SHA1Sum::Hash *aHash,
|
||||
metadata->GetKey(key);
|
||||
|
||||
nsRefPtr<nsILoadContextInfo> info =
|
||||
CacheFileUtils::ParseKey(key, &enhanceId, &uriSpec);
|
||||
CacheFileUtils::ParseKey(key, &keyInfo);
|
||||
MOZ_ASSERT(info);
|
||||
if (!info) {
|
||||
return NS_OK;
|
||||
@ -2309,8 +2405,8 @@ CacheFileIOManager::GetEntryInfo(const SHA1Sum::Hash *aHash,
|
||||
}
|
||||
|
||||
// Call directly on the callback.
|
||||
aCallback->OnEntryInfo(uriSpec, enhanceId, dataSize, fetchCount,
|
||||
lastModified, expirationTime);
|
||||
aCallback->OnEntryInfo(keyInfo.mURISpec, keyInfo.mIdEnhance,
|
||||
dataSize, fetchCount, lastModified, expirationTime);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2397,7 +2493,7 @@ CacheFileIOManager::RenameFile(CacheFileHandle *aHandle,
|
||||
aHandle, PromiseFlatCString(aNewName).get(), aCallback));
|
||||
|
||||
nsresult rv;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = aHandle->Manager();
|
||||
|
||||
if (aHandle->IsClosed() || !ioMan) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
@ -2508,6 +2604,10 @@ CacheFileIOManager::EvictIfOverLimitInternal()
|
||||
|
||||
MOZ_ASSERT(mIOThread->IsCurrentThread());
|
||||
|
||||
if (mKind == PINNING) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
if (mShuttingDown) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
@ -2569,6 +2669,7 @@ CacheFileIOManager::OverLimitEvictionInternal()
|
||||
nsresult rv;
|
||||
|
||||
MOZ_ASSERT(mIOThread->IsCurrentThread());
|
||||
MOZ_ASSERT(mKind != PINNING);
|
||||
|
||||
// mOverLimitEvicting is accessed only on IO thread, so we can set it to false
|
||||
// here and set it to true again once we dispatch another event that will
|
||||
@ -2701,6 +2802,31 @@ CacheFileIOManager::EvictAll()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
CacheFileIOManager::EvictPinned(uint32_t aPinningAppId)
|
||||
{
|
||||
LOG(("CacheFileIOManager::EvictPinned(appId=%d)", aPinningAppId));
|
||||
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
if (ioMan) {
|
||||
ioMan = Pinning::Self()->Get(aPinningAppId);
|
||||
}
|
||||
if (!ioMan) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> ev;
|
||||
ev = NS_NewRunnableMethod(ioMan, &CacheFileIOManager::EvictAllInternal);
|
||||
|
||||
nsresult rv = ioMan->mIOThread->DispatchAfterPendingOpens(ev);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class EvictionNotifierRunnable : public nsRunnable
|
||||
@ -2724,7 +2850,7 @@ EvictionNotifierRunnable::Run()
|
||||
nsresult
|
||||
CacheFileIOManager::EvictAllInternal()
|
||||
{
|
||||
LOG(("CacheFileIOManager::EvictAllInternal()"));
|
||||
LOG(("CacheFileIOManager::EvictAllInternal(), this=%p", this));
|
||||
|
||||
nsresult rv;
|
||||
|
||||
@ -2789,18 +2915,29 @@ CacheFileIOManager::EvictAllInternal()
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (mKind != PINNING) {
|
||||
CacheIndex::RemoveAll();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
CacheFileIOManager::EvictByContext(nsILoadContextInfo *aLoadContextInfo)
|
||||
CacheFileIOManager::EvictByContext(nsILoadContextInfo *aLoadContextInfo,
|
||||
bool aIsPinning)
|
||||
{
|
||||
LOG(("CacheFileIOManager::EvictByContext() [loadContextInfo=%p]",
|
||||
aLoadContextInfo));
|
||||
|
||||
if (aIsPinning) {
|
||||
// This is a kinda hacky workaround, we simply delete everything that
|
||||
// the app has pinned with disrespect to the load context separation.
|
||||
// This API is dependent on the index, but index is global and only
|
||||
// works for the general manager.
|
||||
return CacheFileIOManager::EvictPinned(aLoadContextInfo->AppId());
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
|
||||
@ -2937,7 +3074,7 @@ CacheFileIOManager::TrashDirectory(nsIFile *aFile)
|
||||
{
|
||||
nsAutoCString path;
|
||||
aFile->GetNativePath(path);
|
||||
LOG(("CacheFileIOManager::TrashDirectory() [file=%s]", path.get()));
|
||||
LOG(("CacheFileIOManager::TrashDirectory() [this=%p, file=%s]", this, path.get()));
|
||||
|
||||
nsresult rv;
|
||||
|
||||
@ -3001,23 +3138,6 @@ CacheFileIOManager::TrashDirectory(nsIFile *aFile)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
CacheFileIOManager::OnTrashTimer(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
LOG(("CacheFileIOManager::OnTrashTimer() [timer=%p, closure=%p]", aTimer,
|
||||
aClosure));
|
||||
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
|
||||
if (!ioMan) {
|
||||
return;
|
||||
}
|
||||
|
||||
ioMan->mTrashTimer = nullptr;
|
||||
ioMan->StartRemovingTrash();
|
||||
}
|
||||
|
||||
nsresult
|
||||
CacheFileIOManager::StartRemovingTrash()
|
||||
{
|
||||
@ -3057,8 +3177,7 @@ CacheFileIOManager::StartRemovingTrash()
|
||||
rv = timer->SetTarget(ioTarget);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = timer->InitWithFuncCallback(CacheFileIOManager::OnTrashTimer, nullptr,
|
||||
kRemoveTrashStartDelay - elapsed,
|
||||
rv = timer->InitWithCallback(this, kRemoveTrashStartDelay - elapsed,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -3260,12 +3379,16 @@ CacheFileIOManager::InitIndexEntry(CacheFileHandle *aHandle,
|
||||
", inBrowser=%d]", aHandle, aAppId, aAnonymous, aInBrowser));
|
||||
|
||||
nsresult rv;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = aHandle->Manager();
|
||||
|
||||
if (aHandle->IsClosed() || !ioMan) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
if (ioMan->Kind() == PINNING) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
if (aHandle->IsSpecialFile()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
@ -3290,12 +3413,16 @@ CacheFileIOManager::UpdateIndexEntry(CacheFileHandle *aHandle,
|
||||
aExpirationTime ? nsPrintfCString("%u", *aExpirationTime).get() : ""));
|
||||
|
||||
nsresult rv;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = gInstance;
|
||||
nsRefPtr<CacheFileIOManager> ioMan = aHandle->Manager();
|
||||
|
||||
if (aHandle->IsClosed() || !ioMan) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
if (ioMan->Kind() == PINNING) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
if (aHandle->IsSpecialFile()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
@ -3623,16 +3750,16 @@ CacheFileIOManager::OpenNSPRHandle(CacheFileHandle *aHandle, bool aCreate)
|
||||
{
|
||||
MOZ_ASSERT(CacheFileIOManager::IsOnIOThreadOrCeased());
|
||||
MOZ_ASSERT(!aHandle->mFD);
|
||||
MOZ_ASSERT(mHandlesByLastUsed.IndexOf(aHandle) == mHandlesByLastUsed.NoIndex);
|
||||
MOZ_ASSERT(mHandlesByLastUsed.Length() <= kOpenHandlesLimit);
|
||||
MOZ_ASSERT(gInstance->mHandlesByLastUsed.IndexOf(aHandle) == gInstance->mHandlesByLastUsed.NoIndex);
|
||||
MOZ_ASSERT(gInstance->mHandlesByLastUsed.Length() <= kOpenHandlesLimit);
|
||||
MOZ_ASSERT((aCreate && !aHandle->mFileExists) ||
|
||||
(!aCreate && aHandle->mFileExists));
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (mHandlesByLastUsed.Length() == kOpenHandlesLimit) {
|
||||
if (gInstance->mHandlesByLastUsed.Length() == kOpenHandlesLimit) {
|
||||
// close handle that hasn't been used for the longest time
|
||||
rv = ReleaseNSPRHandleInternal(mHandlesByLastUsed[0]);
|
||||
rv = ReleaseNSPRHandleInternal(gInstance->mHandlesByLastUsed[0]);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
@ -3689,7 +3816,7 @@ CacheFileIOManager::OpenNSPRHandle(CacheFileHandle *aHandle, bool aCreate)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
mHandlesByLastUsed.AppendElement(aHandle);
|
||||
gInstance->mHandlesByLastUsed.AppendElement(aHandle);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -3700,10 +3827,10 @@ CacheFileIOManager::NSPRHandleUsed(CacheFileHandle *aHandle)
|
||||
MOZ_ASSERT(aHandle->mFD);
|
||||
|
||||
DebugOnly<bool> found;
|
||||
found = mHandlesByLastUsed.RemoveElement(aHandle);
|
||||
found = gInstance->mHandlesByLastUsed.RemoveElement(aHandle);
|
||||
MOZ_ASSERT(found);
|
||||
|
||||
mHandlesByLastUsed.AppendElement(aHandle);
|
||||
gInstance->mHandlesByLastUsed.AppendElement(aHandle);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -3843,6 +3970,10 @@ CacheFileIOManager::UpdateSmartCacheSize(int64_t aFreeSpace)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (mKind == PINNING) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// Wait at least kSmartSizeUpdateInterval before recomputing smart size.
|
||||
static const TimeDuration kUpdateLimit =
|
||||
TimeDuration::FromMilliseconds(kSmartSizeUpdateInterval);
|
||||
@ -3984,9 +4115,19 @@ CacheFileIOManager::SizeOfExcludingThisInternal(mozilla::MallocSizeOf mallocSize
|
||||
n += mFailedTrashDirs[i].SizeOfExcludingThisIfUnshared(mallocSizeOf);
|
||||
}
|
||||
|
||||
if (mKind == GENERAL) {
|
||||
Pinning::Self()->SizeOfIncludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t
|
||||
CacheFileIOManager::SizeOfIncludingThisInternal(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
return mallocSizeOf(this) + SizeOfExcludingThisInternal(mallocSizeOf);
|
||||
}
|
||||
|
||||
// static
|
||||
size_t
|
||||
CacheFileIOManager::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
||||
@ -4004,5 +4145,128 @@ CacheFileIOManager::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
||||
return mallocSizeOf(gInstance) + SizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
// CacheFileIOManager::Pinning
|
||||
|
||||
CacheFileIOManager::Pinning*
|
||||
CacheFileIOManager::Pinning::sSelf = nullptr;
|
||||
|
||||
bool
|
||||
CacheFileIOManager::Pinning::sDestroyed = false;
|
||||
|
||||
CacheFileIOManager::Pinning::Pinning()
|
||||
: mLock("CacheFileIOManager::Pinning")
|
||||
{
|
||||
MOZ_ASSERT(!sSelf);
|
||||
sSelf = this;
|
||||
MOZ_COUNT_CTOR(CacheFileIOManager::Pinning);
|
||||
}
|
||||
|
||||
CacheFileIOManager::Pinning::~Pinning()
|
||||
{
|
||||
MOZ_ASSERT(sSelf);
|
||||
sSelf = nullptr;
|
||||
MOZ_COUNT_DTOR(CacheFileIOManager::Pinning);
|
||||
}
|
||||
|
||||
// static
|
||||
CacheFileIOManager::Pinning*
|
||||
CacheFileIOManager::Pinning::Self()
|
||||
{
|
||||
MOZ_ASSERT(!sDestroyed);
|
||||
if (!sSelf) {
|
||||
sSelf = new Pinning();
|
||||
}
|
||||
return sSelf;
|
||||
}
|
||||
|
||||
void
|
||||
CacheFileIOManager::Pinning::Destroy()
|
||||
{
|
||||
delete sSelf;
|
||||
sDestroyed = true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
CacheFileIOManager::Pinning::OnProfile()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = NS_GetSpecialDirectory(
|
||||
NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mRoamingProfileDir));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<CacheFileIOManager>
|
||||
CacheFileIOManager::Pinning::Get(uint32_t aAppId)
|
||||
{
|
||||
mozilla::MutexAutoLock lock(mLock);
|
||||
|
||||
nsRefPtr<CacheFileIOManager> pinningIOMan;
|
||||
if (!mTable.Get(aAppId, getter_AddRefs(pinningIOMan))) {
|
||||
pinningIOMan = new CacheFileIOManager();
|
||||
LOG(("CacheFileIOManager::Pinning::Get, new manager %p for appid=%u",
|
||||
pinningIOMan.get(), aAppId));
|
||||
|
||||
nsresult rv = pinningIOMan->InitAsPinning(aAppId, mRoamingProfileDir);
|
||||
if (NS_FAILED(rv)) {
|
||||
return nullptr;
|
||||
}
|
||||
mTable.Put(aAppId, pinningIOMan);
|
||||
}
|
||||
|
||||
return pinningIOMan.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
PLDHashOperator
|
||||
CacheFileIOManager::Pinning::Collect(uint32_t const& aAppId,
|
||||
nsRefPtr<CacheFileIOManager>& aIoMan,
|
||||
void* aClosure)
|
||||
{
|
||||
nsTArray<nsRefPtr<CacheFileIOManager> >* managers =
|
||||
static_cast<nsTArray<nsRefPtr<CacheFileIOManager> >*>(aClosure);
|
||||
|
||||
managers->AppendElement()->swap(aIoMan);
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
CacheFileIOManager::Pinning::ShutdownInternal()
|
||||
{
|
||||
nsTArray<nsRefPtr<CacheFileIOManager> > managers;
|
||||
{
|
||||
mozilla::MutexAutoLock lock(mLock);
|
||||
mTable.Enumerate(&Pinning::Collect, &managers);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < managers.Length(); ++i) {
|
||||
CacheFileIOManager* ioMan = managers[i];
|
||||
ioMan->ShutdownInternal();
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
size_t CollectManagerMemory(uint32_t const & aAppId,
|
||||
nsRefPtr<mozilla::net::CacheFileIOManager> const & aManager,
|
||||
mozilla::MallocSizeOf mallocSizeOf,
|
||||
void * aClosure)
|
||||
{
|
||||
return aManager->SizeOfIncludingThisInternal(mallocSizeOf);
|
||||
}
|
||||
|
||||
size_t
|
||||
CacheFileIOManager::Pinning::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
return mTable.SizeOfExcludingThis(&CollectManagerMemory, mallocSizeOf, nullptr);
|
||||
}
|
||||
|
||||
size_t
|
||||
CacheFileIOManager::Pinning::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
|
||||
{
|
||||
return mallocSizeOf(this) + SizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "nsTArray.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "prio.h"
|
||||
|
||||
//#define DEBUG_HANDLES 1
|
||||
@ -28,6 +29,7 @@ namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class CacheFile;
|
||||
class CacheFileIOManager;
|
||||
#ifdef DEBUG_HANDLES
|
||||
class CacheFileHandlesEntry;
|
||||
#endif
|
||||
@ -43,8 +45,8 @@ public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
bool DispatchRelease();
|
||||
|
||||
CacheFileHandle(const SHA1Sum::Hash *aHash, bool aPriority);
|
||||
CacheFileHandle(const nsACString &aKey, bool aPriority);
|
||||
CacheFileHandle(CacheFileIOManager* aManager, const SHA1Sum::Hash *aHash, bool aPriority);
|
||||
CacheFileHandle(CacheFileIOManager* aManager, const nsACString &aKey, bool aPriority);
|
||||
CacheFileHandle(const CacheFileHandle &aOther);
|
||||
void Log();
|
||||
bool IsDoomed() const { return mIsDoomed; }
|
||||
@ -56,6 +58,7 @@ public:
|
||||
bool IsClosed() const { return mClosed; }
|
||||
bool IsSpecialFile() const { return mSpecialFile; }
|
||||
nsCString & Key() { return mKey; }
|
||||
CacheFileIOManager* Manager() const { return mManager; }
|
||||
|
||||
// Memory reporting
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
@ -68,6 +71,8 @@ private:
|
||||
|
||||
virtual ~CacheFileHandle();
|
||||
|
||||
nsRefPtr<CacheFileIOManager> mManager;
|
||||
|
||||
const SHA1Sum::Hash *mHash;
|
||||
bool mIsDoomed;
|
||||
bool mPriority;
|
||||
@ -86,7 +91,7 @@ private:
|
||||
|
||||
class CacheFileHandles {
|
||||
public:
|
||||
CacheFileHandles();
|
||||
CacheFileHandles(CacheFileIOManager* aManager);
|
||||
~CacheFileHandles();
|
||||
|
||||
nsresult GetHandle(const SHA1Sum::Hash *aHash, CacheFileHandle **_retval);
|
||||
@ -168,6 +173,7 @@ public:
|
||||
|
||||
private:
|
||||
nsTHashtable<HandleHashKey> mTable;
|
||||
CacheFileIOManager* mManager;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -218,6 +224,12 @@ public:
|
||||
SPECIAL_FILE = 8U
|
||||
};
|
||||
|
||||
enum EKind {
|
||||
UNKNOWN,
|
||||
GENERAL,
|
||||
PINNING
|
||||
};
|
||||
|
||||
CacheFileIOManager();
|
||||
|
||||
static nsresult Init();
|
||||
@ -229,6 +241,8 @@ public:
|
||||
static bool IsOnIOThreadOrCeased();
|
||||
static bool IsShutdown();
|
||||
|
||||
EKind Kind() const { return mKind; }
|
||||
|
||||
// Make aFile's WriteMetadataIfNeeded be called automatically after
|
||||
// a short interval.
|
||||
static nsresult ScheduleMetadataWrite(CacheFile * aFile);
|
||||
@ -240,6 +254,8 @@ public:
|
||||
|
||||
static nsresult OpenFile(const nsACString &aKey,
|
||||
uint32_t aFlags, CacheFileIOListener *aCallback);
|
||||
static nsresult OpenFile(const nsACString &aKey, uint32_t aPinningAppId,
|
||||
uint32_t aFlags, CacheFileIOListener *aCallback);
|
||||
static nsresult Read(CacheFileHandle *aHandle, int64_t aOffset,
|
||||
char *aBuf, int32_t aCount,
|
||||
CacheFileIOListener *aCallback);
|
||||
@ -259,7 +275,9 @@ public:
|
||||
CacheFileIOListener *aCallback);
|
||||
static nsresult EvictIfOverLimit();
|
||||
static nsresult EvictAll();
|
||||
static nsresult EvictByContext(nsILoadContextInfo *aLoadContextInfo);
|
||||
static nsresult EvictPinned(uint32_t aPinningAppId);
|
||||
static nsresult EvictByContext(nsILoadContextInfo *aLoadContextInfo,
|
||||
bool aIsPinning);
|
||||
|
||||
static nsresult InitIndexEntry(CacheFileHandle *aHandle,
|
||||
uint32_t aAppId,
|
||||
@ -292,6 +310,9 @@ public:
|
||||
static size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||
static size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||
|
||||
size_t SizeOfIncludingThisInternal(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
size_t SizeOfExcludingThisInternal(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
|
||||
private:
|
||||
friend class CacheFileHandle;
|
||||
friend class CacheFileChunk;
|
||||
@ -313,6 +334,8 @@ private:
|
||||
virtual ~CacheFileIOManager();
|
||||
|
||||
nsresult InitInternal();
|
||||
nsresult InitAsPinning(uint32_t aAppId, nsIFile* aProfileDir);
|
||||
|
||||
nsresult ShutdownInternal();
|
||||
|
||||
nsresult OpenFileInternal(const SHA1Sum::Hash *aHash,
|
||||
@ -376,10 +399,44 @@ private:
|
||||
// before we start an eviction loop.
|
||||
nsresult UpdateSmartCacheSize(int64_t aFreeSpace);
|
||||
|
||||
// Memory reporting (private part)
|
||||
size_t SizeOfExcludingThisInternal(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
|
||||
static CacheFileIOManager *gInstance;
|
||||
// Each pinning app has its own intance of an IO manager setup to point to
|
||||
// the roaming part of the profile plus identification by the appid.
|
||||
class Pinning
|
||||
{
|
||||
nsRefPtrHashtable<nsUint32HashKey, CacheFileIOManager> mTable;
|
||||
mozilla::Mutex mLock;
|
||||
nsCOMPtr<nsIFile> mRoamingProfileDir;
|
||||
|
||||
static Pinning* sSelf;
|
||||
static bool sDestroyed;
|
||||
|
||||
static PLDHashOperator Collect(uint32_t const& aAppId,
|
||||
nsRefPtr<CacheFileIOManager>& aIoMan,
|
||||
void* aClosure);
|
||||
static PLDHashOperator Copy(uint32_t const& aAppId,
|
||||
nsRefPtr<CacheFileIOManager>& aIoMan,
|
||||
void* aClosure);
|
||||
public:
|
||||
Pinning();
|
||||
~Pinning();
|
||||
|
||||
static Pinning* Self();
|
||||
static void Destroy();
|
||||
|
||||
nsresult OnProfile();
|
||||
already_AddRefed<CacheFileIOManager> Get(uint32_t aPinningAppId);
|
||||
void ShutdownInternal();
|
||||
#ifdef DEBUG
|
||||
uint32_t Length() { return mTable.Count(); }
|
||||
#endif
|
||||
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
|
||||
};
|
||||
|
||||
EKind mKind;
|
||||
|
||||
TimeStamp mStartTime;
|
||||
bool mShuttingDown;
|
||||
nsRefPtr<CacheIOThread> mIOThread;
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "CacheLog.h"
|
||||
#include "CacheFileUtils.h"
|
||||
#include "CacheStorage.h"
|
||||
#include "LoadContextInfo.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
@ -27,6 +28,7 @@ public:
|
||||
: caret(aCaret)
|
||||
, end(aEnd)
|
||||
// Initialize attributes to their default values
|
||||
, pinningStorage(false)
|
||||
, appId(nsILoadContextInfo::NO_APP_ID)
|
||||
, isPrivate(false)
|
||||
, isInBrowser(false)
|
||||
@ -44,6 +46,7 @@ private:
|
||||
nsACString::const_iterator const end;
|
||||
|
||||
// Results
|
||||
bool pinningStorage;
|
||||
uint32_t appId;
|
||||
bool isPrivate;
|
||||
bool isInBrowser;
|
||||
@ -76,6 +79,9 @@ private:
|
||||
cacheKey = caret;
|
||||
caret = end;
|
||||
return true;
|
||||
case 'P':
|
||||
pinningStorage = true;
|
||||
break;
|
||||
case 'p':
|
||||
isPrivate = true;
|
||||
break;
|
||||
@ -194,14 +200,18 @@ public:
|
||||
{
|
||||
result.Assign(idEnhance);
|
||||
}
|
||||
|
||||
void PinningStorage(bool &result)
|
||||
{
|
||||
result = pinningStorage;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
already_AddRefed<nsILoadContextInfo>
|
||||
ParseKey(const nsCSubstring &aKey,
|
||||
nsCSubstring *aIdEnhance,
|
||||
nsCSubstring *aURISpec)
|
||||
KeyInfo* aKeyInfo)
|
||||
{
|
||||
nsACString::const_iterator caret, end;
|
||||
aKey.BeginReading(caret);
|
||||
@ -210,18 +220,25 @@ ParseKey(const nsCSubstring &aKey,
|
||||
KeyParser parser(caret, end);
|
||||
nsRefPtr<LoadContextInfo> info = parser.Parse();
|
||||
|
||||
if (info) {
|
||||
if (aIdEnhance)
|
||||
parser.IdEnhance(*aIdEnhance);
|
||||
if (aURISpec)
|
||||
parser.URISpec(*aURISpec);
|
||||
if (info && aKeyInfo) {
|
||||
parser.IdEnhance(aKeyInfo->mIdEnhance);
|
||||
parser.URISpec(aKeyInfo->mURISpec);
|
||||
parser.PinningStorage(aKeyInfo->mPinningStorage);
|
||||
}
|
||||
|
||||
return info.forget();
|
||||
}
|
||||
|
||||
void
|
||||
AppendKeyPrefix(nsILoadContextInfo* aInfo, nsACString &_retval)
|
||||
AppendKeyPrefix(CacheStorage const* aStorage, nsACString &_retval)
|
||||
{
|
||||
AppendKeyPrefix(aStorage->LoadInfo(), aStorage->IsPinning(), _retval);
|
||||
}
|
||||
|
||||
void
|
||||
AppendKeyPrefix(nsILoadContextInfo* aInfo,
|
||||
bool aPin,
|
||||
nsACString &_retval)
|
||||
{
|
||||
/**
|
||||
* This key is used to salt file hashes. When form of the key is changed
|
||||
@ -231,6 +248,10 @@ AppendKeyPrefix(nsILoadContextInfo* aInfo, nsACString &_retval)
|
||||
* Keep the attributes list sorted according their ASCII code.
|
||||
*/
|
||||
|
||||
if (aPin) {
|
||||
_retval.AppendLiteral("P,");
|
||||
}
|
||||
|
||||
if (aInfo->IsAnonymous()) {
|
||||
_retval.AppendLiteral("a,");
|
||||
}
|
||||
|
@ -11,21 +11,26 @@
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "CacheStorageService.h"
|
||||
|
||||
class nsILoadContextInfo;
|
||||
class nsACString;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class CacheStorage;
|
||||
|
||||
namespace CacheFileUtils {
|
||||
|
||||
already_AddRefed<nsILoadContextInfo>
|
||||
ParseKey(const nsCSubstring &aKey,
|
||||
nsCSubstring *aIdEnhance = nullptr,
|
||||
nsCSubstring *aURISpec = nullptr);
|
||||
KeyInfo* aKeyInfo = nullptr);
|
||||
|
||||
void
|
||||
AppendKeyPrefix(nsILoadContextInfo *aInfo, nsACString &_retval);
|
||||
AppendKeyPrefix(CacheStorage const* aStorage, nsACString &_retval);
|
||||
void
|
||||
AppendKeyPrefix(nsILoadContextInfo *aInfo, bool aPin, nsACString &_retval);
|
||||
|
||||
void
|
||||
AppendTagWithValue(nsACString & aTarget, char const aTag, nsCSubstring const & aValue);
|
||||
|
@ -429,6 +429,10 @@ CacheStorageEvictHelper::Run(mozIApplicationClearPrivateDataParams* aParams)
|
||||
rv = ClearStorage(true, aBrowserOnly, true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// And finally evict everything that this app has stored as pinned
|
||||
rv = CacheFileIOManager::EvictPinned(mAppId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,11 @@ public:
|
||||
bool aAllowDisk,
|
||||
bool aLookupAppCache);
|
||||
|
||||
virtual bool IsPinning() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~CacheStorage();
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "CacheIndex.h"
|
||||
#include "CacheIndexIterator.h"
|
||||
#include "CacheStorage.h"
|
||||
#include "PinningCacheStorage.h"
|
||||
#include "AppCacheStorage.h"
|
||||
#include "CacheEntry.h"
|
||||
#include "CacheFileUtils.h"
|
||||
@ -209,12 +210,12 @@ protected:
|
||||
class WalkMemoryCacheRunnable : public WalkCacheRunnable
|
||||
{
|
||||
public:
|
||||
WalkMemoryCacheRunnable(nsILoadContextInfo *aLoadInfo,
|
||||
WalkMemoryCacheRunnable(CacheStorage const *aStorage,
|
||||
bool aVisitEntries,
|
||||
nsICacheStorageVisitor* aVisitor)
|
||||
: WalkCacheRunnable(aVisitor, aVisitEntries)
|
||||
{
|
||||
CacheFileUtils::AppendKeyPrefix(aLoadInfo, mContextKey);
|
||||
CacheFileUtils::AppendKeyPrefix(aStorage, mContextKey);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
@ -535,8 +536,9 @@ void CacheStorageService::DropPrivateBrowsingEntries()
|
||||
nsTArray<nsCString> keys;
|
||||
sGlobalEntryTables->EnumerateRead(&CollectPrivateContexts, &keys);
|
||||
|
||||
for (uint32_t i = 0; i < keys.Length(); ++i)
|
||||
DoomStorageEntries(keys[i], nullptr, true, nullptr);
|
||||
for (uint32_t i = 0; i < keys.Length(); ++i) {
|
||||
DoomStorageEntries(keys[i], nullptr, true, false, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -716,6 +718,23 @@ NS_IMETHODIMP CacheStorageService::DiskCacheStorage(nsILoadContextInfo *aLoadCon
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP CacheStorageService::PinningCacheStorage(nsILoadContextInfo *aLoadContextInfo,
|
||||
nsICacheStorage * *_retval)
|
||||
{
|
||||
NS_ENSURE_ARG(aLoadContextInfo);
|
||||
NS_ENSURE_ARG(_retval);
|
||||
|
||||
if (!CacheObserver::UseNewCache()) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsICacheStorage> storage =
|
||||
new mozilla::net::PinningCacheStorage(aLoadContextInfo);
|
||||
|
||||
storage.forget(_retval);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP CacheStorageService::AppCacheStorage(nsILoadContextInfo *aLoadContextInfo,
|
||||
nsIApplicationCache *aApplicationCache,
|
||||
nsICacheStorage * *_retval)
|
||||
@ -751,7 +770,7 @@ NS_IMETHODIMP CacheStorageService::Clear()
|
||||
sGlobalEntryTables->EnumerateRead(&CollectContexts, &keys);
|
||||
|
||||
for (uint32_t i = 0; i < keys.Length(); ++i)
|
||||
DoomStorageEntries(keys[i], nullptr, true, nullptr);
|
||||
DoomStorageEntries(keys[i], nullptr, true, false, nullptr);
|
||||
}
|
||||
|
||||
rv = CacheFileIOManager::EvictAll();
|
||||
@ -1336,10 +1355,15 @@ CacheStorageService::AddStorageEntry(CacheStorage const* aStorage,
|
||||
NS_ENSURE_ARG(aStorage);
|
||||
|
||||
nsAutoCString contextKey;
|
||||
CacheFileUtils::AppendKeyPrefix(aStorage->LoadInfo(), contextKey);
|
||||
CacheFileUtils::AppendKeyPrefix(aStorage, contextKey);
|
||||
|
||||
uint32_t pinningAppId = aStorage->IsPinning()
|
||||
? aStorage->LoadInfo()->AppId()
|
||||
: nsILoadContextInfo::NO_APP_ID;
|
||||
|
||||
return AddStorageEntry(contextKey, aURI, aIdExtension,
|
||||
aStorage->WriteToDisk(), aCreateIfNotExist, aReplace,
|
||||
aStorage->WriteToDisk(), pinningAppId,
|
||||
aCreateIfNotExist, aReplace,
|
||||
aResult);
|
||||
}
|
||||
|
||||
@ -1348,6 +1372,7 @@ CacheStorageService::AddStorageEntry(nsCSubstring const& aContextKey,
|
||||
nsIURI* aURI,
|
||||
const nsACString & aIdExtension,
|
||||
bool aWriteToDisk,
|
||||
uint32_t aPinningAppId,
|
||||
bool aCreateIfNotExist,
|
||||
bool aReplace,
|
||||
CacheEntryHandle** aResult)
|
||||
@ -1410,7 +1435,7 @@ CacheStorageService::AddStorageEntry(nsCSubstring const& aContextKey,
|
||||
// Ensure entry for the particular URL, if not read/only
|
||||
if (!entryExists && (aCreateIfNotExist || aReplace)) {
|
||||
// Entry is not in the hashtable or has just been truncated...
|
||||
entry = new CacheEntry(aContextKey, aURI, aIdExtension, aWriteToDisk);
|
||||
entry = new CacheEntry(aContextKey, aURI, aIdExtension, aWriteToDisk, aPinningAppId);
|
||||
entries->Put(entryKey, entry);
|
||||
LOG((" new entry %p for %s", entry.get(), entryKey.get()));
|
||||
}
|
||||
@ -1435,7 +1460,7 @@ CacheStorageService::CheckStorageEntry(CacheStorage const* aStorage,
|
||||
nsresult rv;
|
||||
|
||||
nsAutoCString contextKey;
|
||||
CacheFileUtils::AppendKeyPrefix(aStorage->LoadInfo(), contextKey);
|
||||
CacheFileUtils::AppendKeyPrefix(aStorage, contextKey);
|
||||
|
||||
if (!aStorage->WriteToDisk()) {
|
||||
AppendMemoryStorageID(contextKey);
|
||||
@ -1471,6 +1496,11 @@ CacheStorageService::CheckStorageEntry(CacheStorage const* aStorage,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aStorage->IsPinning()) {
|
||||
LOG((" not implemented for pinning entries"));
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// Disk entry, not found in the hashtable, check the index.
|
||||
nsAutoCString fileKey;
|
||||
rv = CacheEntry::HashingKey(contextKey, aIdExtension, aURI, fileKey);
|
||||
@ -1557,7 +1587,7 @@ CacheStorageService::DoomStorageEntry(CacheStorage const* aStorage,
|
||||
NS_ENSURE_ARG(aURI);
|
||||
|
||||
nsAutoCString contextKey;
|
||||
CacheFileUtils::AppendKeyPrefix(aStorage->LoadInfo(), contextKey);
|
||||
CacheFileUtils::AppendKeyPrefix(aStorage, contextKey);
|
||||
|
||||
nsAutoCString entryKey;
|
||||
nsresult rv = CacheEntry::HashingKey(EmptyCString(), aIdExtension, aURI, entryKey);
|
||||
@ -1598,7 +1628,7 @@ CacheStorageService::DoomStorageEntry(CacheStorage const* aStorage,
|
||||
|
||||
if (aStorage->WriteToDisk()) {
|
||||
nsAutoCString contextKey;
|
||||
CacheFileUtils::AppendKeyPrefix(aStorage->LoadInfo(), contextKey);
|
||||
CacheFileUtils::AppendKeyPrefix(aStorage, contextKey);
|
||||
|
||||
rv = CacheEntry::HashingKey(contextKey, aIdExtension, aURI, entryKey);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -1643,18 +1673,20 @@ CacheStorageService::DoomStorageEntries(CacheStorage const* aStorage,
|
||||
NS_ENSURE_ARG(aStorage);
|
||||
|
||||
nsAutoCString contextKey;
|
||||
CacheFileUtils::AppendKeyPrefix(aStorage->LoadInfo(), contextKey);
|
||||
CacheFileUtils::AppendKeyPrefix(aStorage, contextKey);
|
||||
|
||||
mozilla::MutexAutoLock lock(mLock);
|
||||
|
||||
return DoomStorageEntries(contextKey, aStorage->LoadInfo(),
|
||||
aStorage->WriteToDisk(), aCallback);
|
||||
aStorage->WriteToDisk(),
|
||||
aStorage->IsPinning(), aCallback);
|
||||
}
|
||||
|
||||
nsresult
|
||||
CacheStorageService::DoomStorageEntries(nsCSubstring const& aContextKey,
|
||||
nsILoadContextInfo* aContext,
|
||||
bool aDiskStorage,
|
||||
bool aPinningStorage,
|
||||
nsICacheEntryDoomCallback* aCallback)
|
||||
{
|
||||
mLock.AssertCurrentThreadOwns();
|
||||
@ -1673,7 +1705,7 @@ CacheStorageService::DoomStorageEntries(nsCSubstring const& aContextKey,
|
||||
|
||||
if (aContext && !aContext->IsPrivate()) {
|
||||
LOG((" dooming disk entries"));
|
||||
CacheFileIOManager::EvictByContext(aContext);
|
||||
CacheFileIOManager::EvictByContext(aContext, aPinningStorage);
|
||||
}
|
||||
} else {
|
||||
LOG((" dooming memory-only storage of %s", aContextKey.BeginReading()));
|
||||
@ -1740,6 +1772,10 @@ CacheStorageService::WalkStorageEntries(CacheStorage const* aStorage,
|
||||
|
||||
NS_ENSURE_ARG(aStorage);
|
||||
|
||||
if (aStorage->IsPinning()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (aStorage->WriteToDisk()) {
|
||||
nsRefPtr<WalkDiskCacheRunnable> event =
|
||||
new WalkDiskCacheRunnable(aStorage->LoadInfo(), aVisitEntries, aVisitor);
|
||||
@ -1747,20 +1783,20 @@ CacheStorageService::WalkStorageEntries(CacheStorage const* aStorage,
|
||||
}
|
||||
|
||||
nsRefPtr<WalkMemoryCacheRunnable> event =
|
||||
new WalkMemoryCacheRunnable(aStorage->LoadInfo(), aVisitEntries, aVisitor);
|
||||
new WalkMemoryCacheRunnable(aStorage, aVisitEntries, aVisitor);
|
||||
return event->Walk();
|
||||
}
|
||||
|
||||
void
|
||||
CacheStorageService::CacheFileDoomed(nsILoadContextInfo* aLoadContextInfo,
|
||||
const nsACString & aIdExtension,
|
||||
const nsACString & aURISpec)
|
||||
CacheFileUtils::KeyInfo* aKeyInfo)
|
||||
{
|
||||
nsAutoCString contextKey;
|
||||
CacheFileUtils::AppendKeyPrefix(aLoadContextInfo, contextKey);
|
||||
CacheFileUtils::AppendKeyPrefix(aLoadContextInfo, aKeyInfo->mPinningStorage, contextKey);
|
||||
|
||||
nsAutoCString entryKey;
|
||||
CacheEntry::HashingKey(EmptyCString(), aIdExtension, aURISpec, entryKey);
|
||||
CacheEntry::HashingKey(EmptyCString(),
|
||||
aKeyInfo->mIdEnhance, aKeyInfo->mURISpec, entryKey);
|
||||
|
||||
mozilla::MutexAutoLock lock(mLock);
|
||||
|
||||
@ -1789,15 +1825,15 @@ CacheStorageService::CacheFileDoomed(nsILoadContextInfo* aLoadContextInfo,
|
||||
|
||||
bool
|
||||
CacheStorageService::GetCacheEntryInfo(nsILoadContextInfo* aLoadContextInfo,
|
||||
const nsACString & aIdExtension,
|
||||
const nsACString & aURISpec,
|
||||
CacheFileUtils::KeyInfo* aKeyInfo,
|
||||
EntryInfoCallback *aCallback)
|
||||
{
|
||||
nsAutoCString contextKey;
|
||||
CacheFileUtils::AppendKeyPrefix(aLoadContextInfo, contextKey);
|
||||
CacheFileUtils::AppendKeyPrefix(aLoadContextInfo, aKeyInfo->mPinningStorage, contextKey);
|
||||
|
||||
nsAutoCString entryKey;
|
||||
CacheEntry::HashingKey(EmptyCString(), aIdExtension, aURISpec, entryKey);
|
||||
CacheEntry::HashingKey(EmptyCString(),
|
||||
aKeyInfo->mIdEnhance, aKeyInfo->mURISpec, entryKey);
|
||||
|
||||
nsRefPtr<CacheEntry> entry;
|
||||
{
|
||||
|
@ -29,6 +29,17 @@ class nsIEventTarget;
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
namespace CacheFileUtils {
|
||||
|
||||
class KeyInfo {
|
||||
public:
|
||||
bool mPinningStorage;
|
||||
nsCString mIdEnhance;
|
||||
nsCString mURISpec;
|
||||
};
|
||||
|
||||
} // CacheFileUtils
|
||||
|
||||
class CacheStorageService;
|
||||
class CacheStorage;
|
||||
class CacheEntry;
|
||||
@ -229,20 +240,18 @@ private:
|
||||
* removal was originated by CacheStorageService.
|
||||
*/
|
||||
void CacheFileDoomed(nsILoadContextInfo* aLoadContextInfo,
|
||||
const nsACString & aIdExtension,
|
||||
const nsACString & aURISpec);
|
||||
CacheFileUtils::KeyInfo* aKeyInfo);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* been invoked
|
||||
* false, when an entry has not been found
|
||||
*/
|
||||
bool GetCacheEntryInfo(nsILoadContextInfo* aLoadContextInfo,
|
||||
const nsACString & aIdExtension,
|
||||
const nsACString & aURISpec,
|
||||
CacheFileUtils::KeyInfo* aKeyInfo,
|
||||
EntryInfoCallback *aCallback);
|
||||
|
||||
private:
|
||||
@ -273,11 +282,13 @@ private:
|
||||
nsresult DoomStorageEntries(nsCSubstring const& aContextKey,
|
||||
nsILoadContextInfo* aContext,
|
||||
bool aDiskStorage,
|
||||
bool aPinningStorage,
|
||||
nsICacheEntryDoomCallback* aCallback);
|
||||
nsresult AddStorageEntry(nsCSubstring const& aContextKey,
|
||||
nsIURI* aURI,
|
||||
const nsACString & aIdExtension,
|
||||
bool aWriteToDisk,
|
||||
uint32_t aPinningAppId,
|
||||
bool aCreateIfNotExist,
|
||||
bool aReplace,
|
||||
CacheEntryHandle** aResult);
|
||||
|
25
netwerk/cache2/PinningCacheStorage.cpp
Normal file
25
netwerk/cache2/PinningCacheStorage.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
/* 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/. */
|
||||
|
||||
#include "PinningCacheStorage.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
bool PinningCacheStorage::IsPinning() const
|
||||
{
|
||||
if (LoadInfo()->AppId() == nsILoadContextInfo::NO_APP_ID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LoadInfo()->IsPrivate()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We are a non-private app load, pin!
|
||||
return true;
|
||||
}
|
||||
|
||||
} // net
|
||||
} // mozilla
|
27
netwerk/cache2/PinningCacheStorage.h
Normal file
27
netwerk/cache2/PinningCacheStorage.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* 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/. */
|
||||
|
||||
#ifndef PinninCacheStorage__h__
|
||||
#define PinninCacheStorage__h__
|
||||
|
||||
#include "CacheStorage.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class PinningCacheStorage : public CacheStorage
|
||||
{
|
||||
public:
|
||||
PinningCacheStorage(nsILoadContextInfo* aInfo)
|
||||
: CacheStorage(aInfo, true, false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool IsPinning() const override;
|
||||
};
|
||||
|
||||
} // net
|
||||
} // mozilla
|
||||
|
||||
#endif
|
@ -40,6 +40,7 @@ UNIFIED_SOURCES += [
|
||||
'CacheStorage.cpp',
|
||||
'CacheStorageService.cpp',
|
||||
'OldWrappers.cpp',
|
||||
'PinningCacheStorage.cpp',
|
||||
]
|
||||
|
||||
# AppCacheStorage.cpp cannot be built in unified mode because it uses plarena.h.
|
||||
|
@ -13,7 +13,7 @@ interface nsICacheStorageConsumptionObserver;
|
||||
/**
|
||||
* Provides access to particual cache storages of the network URI cache.
|
||||
*/
|
||||
[scriptable, uuid(44de2fa4-1b0e-4cd3-9e32-211e936f721e)]
|
||||
[scriptable, uuid(6764d6a5-af42-4655-aef2-81d9efe72ae6)]
|
||||
interface nsICacheStorageService : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -42,6 +42,14 @@ interface nsICacheStorageService : nsISupports
|
||||
nsICacheStorage diskCacheStorage(in nsILoadContextInfo aLoadContextInfo,
|
||||
in bool aLookupAppCache);
|
||||
|
||||
/**
|
||||
* Entries bound to an app will be persisted in a roaming part of the profile
|
||||
* and won't unpersist until the app goes away. Common web content will use
|
||||
* disk cache storage, when under the private browsing mode, entries will be
|
||||
* held in memory and evicted on limit.
|
||||
*/
|
||||
nsICacheStorage pinningCacheStorage(in nsILoadContextInfo aLoadContextInfo);
|
||||
|
||||
/**
|
||||
* Get storage for a specified application cache obtained using some different
|
||||
* mechanism.
|
||||
|
@ -42,7 +42,7 @@ LogURI(const char *aFunctionName, void *self, nsIURI *aURI, nsILoadContextInfo *
|
||||
|
||||
nsAutoCString prefix;
|
||||
if (aInfo) {
|
||||
CacheFileUtils::AppendKeyPrefix(aInfo, prefix);
|
||||
CacheFileUtils::AppendKeyPrefix(aInfo, false, prefix);
|
||||
prefix += ":";
|
||||
}
|
||||
|
||||
@ -627,7 +627,7 @@ PackagedAppService::RequestURI(nsIURI *aURI,
|
||||
}
|
||||
|
||||
nsAutoCString key;
|
||||
CacheFileUtils::AppendKeyPrefix(aInfo, key);
|
||||
CacheFileUtils::AppendKeyPrefix(aInfo, false, key);
|
||||
|
||||
{
|
||||
nsAutoCString spec;
|
||||
|
@ -260,6 +260,7 @@ nsHttpChannel::nsHttpChannel()
|
||||
, mConcurentCacheAccess(0)
|
||||
, mIsPartialRequest(0)
|
||||
, mHasAutoRedirectVetoNotifier(0)
|
||||
, mPinCacheContent(0)
|
||||
, mIsPackagedAppResource(0)
|
||||
, mPushedStream(nullptr)
|
||||
, mLocalBlocklist(false)
|
||||
@ -2847,6 +2848,10 @@ nsHttpChannel::OpenCacheEntry(bool isHttps)
|
||||
rv = cacheStorageService->MemoryCacheStorage(info, // ? choose app cache as well...
|
||||
getter_AddRefs(cacheStorage));
|
||||
}
|
||||
else if (mPinCacheContent) {
|
||||
rv = cacheStorageService->PinningCacheStorage(info,
|
||||
getter_AddRefs(cacheStorage));
|
||||
}
|
||||
else {
|
||||
rv = cacheStorageService->DiskCacheStorage(info,
|
||||
!mPostID && (mChooseApplicationCache || (mLoadFlags & LOAD_CHECK_OFFLINE_CACHE)),
|
||||
@ -6271,6 +6276,26 @@ nsHttpChannel::SetCacheOnlyMetadata(bool aOnlyMetadata)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::GetPin(bool *aPin)
|
||||
{
|
||||
NS_ENSURE_ARG(aPin);
|
||||
*aPin = mPinCacheContent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::SetPin(bool aPin)
|
||||
{
|
||||
LOG(("nsHttpChannel::SetPin [this=%p pin=%d]\n",
|
||||
this, aPin));
|
||||
|
||||
ENSURE_CALLED_BEFORE_ASYNC_OPEN();
|
||||
|
||||
mPinCacheContent = aPin;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel::nsIResumableChannel
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -479,6 +479,9 @@ private:
|
||||
uint32_t mIsPartialRequest : 1;
|
||||
// true iff there is AutoRedirectVetoNotifier on the stack
|
||||
uint32_t mHasAutoRedirectVetoNotifier : 1;
|
||||
// consumers set this to true to use cache pinning, this has effect
|
||||
// only when the channel is in an app context (load context has an appid)
|
||||
uint32_t mPinCacheContent : 1;
|
||||
// Whether fetching the content is meant to be handled by the
|
||||
// packaged app service, which behaves like a caching layer.
|
||||
// Upon successfully fetching the package, the resource will be placed in
|
||||
|
@ -50,6 +50,7 @@ function getCacheStorage(where, lci, appcache)
|
||||
case "disk": return svc.diskCacheStorage(lci, false);
|
||||
case "memory": return svc.memoryCacheStorage(lci);
|
||||
case "appcache": return svc.appCacheStorage(lci, appcache);
|
||||
case "pin": return svc.pinningCacheStorage(lci);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
30
netwerk/test/unit/test_cache2-30-app-pinning.js
Normal file
30
netwerk/test/unit/test_cache2-30-app-pinning.js
Normal file
@ -0,0 +1,30 @@
|
||||
function run_test()
|
||||
{
|
||||
do_get_profile();
|
||||
|
||||
var applci = LoadContextInfo.custom(false, false, 1001, false);
|
||||
|
||||
// Open for write, write
|
||||
asyncOpenCacheEntry("http://a/", "pin", Ci.nsICacheStorage.OPEN_NORMALLY, applci,
|
||||
new OpenCallback(NEW|WAITFORWRITE, "a1m", "a1d", function(entry) {
|
||||
// Open for read and check
|
||||
asyncOpenCacheEntry("http://a/", "pin", Ci.nsICacheStorage.OPEN_NORMALLY, applci,
|
||||
new OpenCallback(NORMAL, "a1m", "a1d", function(entry) {
|
||||
|
||||
// Now clear the whole cache
|
||||
get_cache_service().clear();
|
||||
|
||||
// The pinned entry should be intact
|
||||
asyncOpenCacheEntry("http://a/", "pin", Ci.nsICacheStorage.OPEN_NORMALLY, applci,
|
||||
new OpenCallback(NORMAL, "a1m", "a1d", function(entry) {
|
||||
finish_cache2_test();
|
||||
})
|
||||
);
|
||||
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
do_test_pending();
|
||||
}
|
@ -101,7 +101,8 @@ function run_test() {
|
||||
|
||||
function doneFirstLoad(req, buffer, expected) {
|
||||
// Load it again, make sure it hits the cache
|
||||
var chan = makeChan(URL, 0, false);
|
||||
var nc = req.notificationCallbacks.getInterface(Ci.nsILoadContext);
|
||||
var chan = makeChan(URL, nc.appId, nc.isInBrowserElement);
|
||||
chan.asyncOpen(new ChannelListener(doneSecondLoad, expected), null);
|
||||
}
|
||||
|
||||
|
@ -68,8 +68,9 @@ skip-if = true
|
||||
[test_cache2-28a-OPEN_SECRETLY.js]
|
||||
# This test will be fixed in bug 1067931
|
||||
skip-if = true
|
||||
[test_cache2-28-concurrent_read_resumable_entry_size_zero.js]
|
||||
[test_cache2-29-concurrent_read_non-resumable_entry_size_zero.js]
|
||||
[test_cache2-29a-concurrent_read_resumable_entry_size_zero.js]
|
||||
[test_cache2-29b-concurrent_read_non-resumable_entry_size_zero.js]
|
||||
[test_cache2-30-app-pinning.js]
|
||||
[test_partial_response_entry_size_smart_shrink.js]
|
||||
[test_304_responses.js]
|
||||
[test_421.js]
|
||||
|
Loading…
Reference in New Issue
Block a user