forked from mirrors/gecko-dev
Bug 1468501 - Implement a way to delete network cache by nsIPrincipal, r=mayhemer, r=michal
This commit is contained in:
parent
d55ae44eff
commit
28962b5168
10 changed files with 297 additions and 55 deletions
|
|
@ -16,6 +16,7 @@
|
||||||
#include "nsIDirectoryEnumerator.h"
|
#include "nsIDirectoryEnumerator.h"
|
||||||
#include "mozilla/Base64.h"
|
#include "mozilla/Base64.h"
|
||||||
#include "mozilla/IntegerPrintfMacros.h"
|
#include "mozilla/IntegerPrintfMacros.h"
|
||||||
|
#include "mozilla/net/MozURL.h"
|
||||||
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
@ -93,7 +94,8 @@ CacheFileContextEvictor::ContextsCount()
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
CacheFileContextEvictor::AddContext(nsILoadContextInfo *aLoadContextInfo,
|
CacheFileContextEvictor::AddContext(nsILoadContextInfo *aLoadContextInfo,
|
||||||
bool aPinned)
|
bool aPinned,
|
||||||
|
const nsAString& aOrigin)
|
||||||
{
|
{
|
||||||
LOG(("CacheFileContextEvictor::AddContext() [this=%p, loadContextInfo=%p, pinned=%d]",
|
LOG(("CacheFileContextEvictor::AddContext() [this=%p, loadContextInfo=%p, pinned=%d]",
|
||||||
this, aLoadContextInfo, aPinned));
|
this, aLoadContextInfo, aPinned));
|
||||||
|
|
@ -107,7 +109,8 @@ CacheFileContextEvictor::AddContext(nsILoadContextInfo *aLoadContextInfo,
|
||||||
for (uint32_t i = 0; i < mEntries.Length(); ++i) {
|
for (uint32_t i = 0; i < mEntries.Length(); ++i) {
|
||||||
if (mEntries[i]->mInfo &&
|
if (mEntries[i]->mInfo &&
|
||||||
mEntries[i]->mInfo->Equals(aLoadContextInfo) &&
|
mEntries[i]->mInfo->Equals(aLoadContextInfo) &&
|
||||||
mEntries[i]->mPinned == aPinned) {
|
mEntries[i]->mPinned == aPinned &&
|
||||||
|
mEntries[i]->mOrigin.Equals(aOrigin)) {
|
||||||
entry = mEntries[i];
|
entry = mEntries[i];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -119,7 +122,8 @@ CacheFileContextEvictor::AddContext(nsILoadContextInfo *aLoadContextInfo,
|
||||||
for (uint32_t i = mEntries.Length(); i > 0;) {
|
for (uint32_t i = mEntries.Length(); i > 0;) {
|
||||||
--i;
|
--i;
|
||||||
if (mEntries[i]->mInfo && mEntries[i]->mPinned == aPinned) {
|
if (mEntries[i]->mInfo && mEntries[i]->mPinned == aPinned) {
|
||||||
RemoveEvictInfoFromDisk(mEntries[i]->mInfo, mEntries[i]->mPinned);
|
RemoveEvictInfoFromDisk(mEntries[i]->mInfo, mEntries[i]->mPinned,
|
||||||
|
mEntries[i]->mOrigin);
|
||||||
mEntries.RemoveElementAt(i);
|
mEntries.RemoveElementAt(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -129,12 +133,13 @@ CacheFileContextEvictor::AddContext(nsILoadContextInfo *aLoadContextInfo,
|
||||||
entry = new CacheFileContextEvictorEntry();
|
entry = new CacheFileContextEvictorEntry();
|
||||||
entry->mInfo = aLoadContextInfo;
|
entry->mInfo = aLoadContextInfo;
|
||||||
entry->mPinned = aPinned;
|
entry->mPinned = aPinned;
|
||||||
|
entry->mOrigin = aOrigin;
|
||||||
mEntries.AppendElement(entry);
|
mEntries.AppendElement(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
entry->mTimeStamp = PR_Now() / PR_USEC_PER_MSEC;
|
entry->mTimeStamp = PR_Now() / PR_USEC_PER_MSEC;
|
||||||
|
|
||||||
PersistEvictionInfoToDisk(aLoadContextInfo, aPinned);
|
PersistEvictionInfoToDisk(aLoadContextInfo, aPinned, aOrigin);
|
||||||
|
|
||||||
if (mIndexIsUpToDate) {
|
if (mIndexIsUpToDate) {
|
||||||
// Already existing context could be added again, in this case the iterator
|
// Already existing context could be added again, in this case the iterator
|
||||||
|
|
@ -263,7 +268,8 @@ CacheFileContextEvictor::WasEvicted(const nsACString &aKey, nsIFile *aFile,
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
CacheFileContextEvictor::PersistEvictionInfoToDisk(
|
CacheFileContextEvictor::PersistEvictionInfoToDisk(
|
||||||
nsILoadContextInfo *aLoadContextInfo, bool aPinned)
|
nsILoadContextInfo *aLoadContextInfo, bool aPinned,
|
||||||
|
const nsAString& aOrigin)
|
||||||
{
|
{
|
||||||
LOG(("CacheFileContextEvictor::PersistEvictionInfoToDisk() [this=%p, "
|
LOG(("CacheFileContextEvictor::PersistEvictionInfoToDisk() [this=%p, "
|
||||||
"loadContextInfo=%p]", this, aLoadContextInfo));
|
"loadContextInfo=%p]", this, aLoadContextInfo));
|
||||||
|
|
@ -273,7 +279,7 @@ CacheFileContextEvictor::PersistEvictionInfoToDisk(
|
||||||
MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
|
MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
|
||||||
|
|
||||||
nsCOMPtr<nsIFile> file;
|
nsCOMPtr<nsIFile> file;
|
||||||
rv = GetContextFile(aLoadContextInfo, aPinned, getter_AddRefs(file));
|
rv = GetContextFile(aLoadContextInfo, aPinned, aOrigin, getter_AddRefs(file));
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
@ -299,7 +305,7 @@ CacheFileContextEvictor::PersistEvictionInfoToDisk(
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
CacheFileContextEvictor::RemoveEvictInfoFromDisk(
|
CacheFileContextEvictor::RemoveEvictInfoFromDisk(
|
||||||
nsILoadContextInfo *aLoadContextInfo, bool aPinned)
|
nsILoadContextInfo *aLoadContextInfo, bool aPinned, const nsAString& aOrigin)
|
||||||
{
|
{
|
||||||
LOG(("CacheFileContextEvictor::RemoveEvictInfoFromDisk() [this=%p, "
|
LOG(("CacheFileContextEvictor::RemoveEvictInfoFromDisk() [this=%p, "
|
||||||
"loadContextInfo=%p]", this, aLoadContextInfo));
|
"loadContextInfo=%p]", this, aLoadContextInfo));
|
||||||
|
|
@ -309,7 +315,7 @@ CacheFileContextEvictor::RemoveEvictInfoFromDisk(
|
||||||
MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
|
MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
|
||||||
|
|
||||||
nsCOMPtr<nsIFile> file;
|
nsCOMPtr<nsIFile> file;
|
||||||
rv = GetContextFile(aLoadContextInfo, aPinned, getter_AddRefs(file));
|
rv = GetContextFile(aLoadContextInfo, aPinned, aOrigin, getter_AddRefs(file));
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
@ -393,6 +399,16 @@ CacheFileContextEvictor::LoadEvictInfoFromDisk()
|
||||||
decoded = Substring(decoded, 1);
|
decoded = Substring(decoded, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Let's see if we have an origin.
|
||||||
|
nsAutoCString origin;
|
||||||
|
if (decoded.Contains('\t')) {
|
||||||
|
auto split = decoded.Split('\t');
|
||||||
|
MOZ_ASSERT(decoded.CountChar('\t') == 2);
|
||||||
|
|
||||||
|
origin = split.Get(0);
|
||||||
|
decoded = split.Get(1);
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsILoadContextInfo> info;
|
nsCOMPtr<nsILoadContextInfo> info;
|
||||||
if (!NS_LITERAL_CSTRING("*").Equals(decoded)) {
|
if (!NS_LITERAL_CSTRING("*").Equals(decoded)) {
|
||||||
// "*" is indication of 'delete all', info left null will pass
|
// "*" is indication of 'delete all', info left null will pass
|
||||||
|
|
@ -417,6 +433,7 @@ CacheFileContextEvictor::LoadEvictInfoFromDisk()
|
||||||
CacheFileContextEvictorEntry *entry = new CacheFileContextEvictorEntry();
|
CacheFileContextEvictorEntry *entry = new CacheFileContextEvictorEntry();
|
||||||
entry->mInfo = info;
|
entry->mInfo = info;
|
||||||
entry->mPinned = pinned;
|
entry->mPinned = pinned;
|
||||||
|
CopyUTF8toUTF16(origin, entry->mOrigin);
|
||||||
entry->mTimeStamp = lastModifiedTime;
|
entry->mTimeStamp = lastModifiedTime;
|
||||||
mEntries.AppendElement(entry);
|
mEntries.AppendElement(entry);
|
||||||
}
|
}
|
||||||
|
|
@ -427,6 +444,7 @@ CacheFileContextEvictor::LoadEvictInfoFromDisk()
|
||||||
nsresult
|
nsresult
|
||||||
CacheFileContextEvictor::GetContextFile(nsILoadContextInfo *aLoadContextInfo,
|
CacheFileContextEvictor::GetContextFile(nsILoadContextInfo *aLoadContextInfo,
|
||||||
bool aPinned,
|
bool aPinned,
|
||||||
|
const nsAString& aOrigin,
|
||||||
nsIFile **_retval)
|
nsIFile **_retval)
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
@ -445,6 +463,10 @@ CacheFileContextEvictor::GetContextFile(nsILoadContextInfo *aLoadContextInfo,
|
||||||
} else {
|
} else {
|
||||||
keyPrefix.Append('*');
|
keyPrefix.Append('*');
|
||||||
}
|
}
|
||||||
|
if (!aOrigin.IsEmpty()) {
|
||||||
|
keyPrefix.Append('\t');
|
||||||
|
keyPrefix.Append(NS_ConvertUTF16toUTF8(aOrigin));
|
||||||
|
}
|
||||||
|
|
||||||
nsAutoCString data64;
|
nsAutoCString data64;
|
||||||
rv = Base64Encode(keyPrefix, data64);
|
rv = Base64Encode(keyPrefix, data64);
|
||||||
|
|
@ -516,7 +538,7 @@ CacheFileContextEvictor::StartEvicting()
|
||||||
MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
|
MOZ_ASSERT(CacheFileIOManager::IsOnIOThread());
|
||||||
|
|
||||||
if (mEvicting) {
|
if (mEvicting) {
|
||||||
LOG(("CacheFileContextEvictor::StartEvicting() - already evicintg."));
|
LOG(("CacheFileContextEvictor::StartEvicting() - already evicting."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -590,7 +612,8 @@ CacheFileContextEvictor::EvictEntries()
|
||||||
LOG(("CacheFileContextEvictor::EvictEntries() - No more entries left in "
|
LOG(("CacheFileContextEvictor::EvictEntries() - No more entries left in "
|
||||||
"iterator. [iterator=%p, info=%p]", mEntries[0]->mIterator.get(),
|
"iterator. [iterator=%p, info=%p]", mEntries[0]->mIterator.get(),
|
||||||
mEntries[0]->mInfo.get()));
|
mEntries[0]->mInfo.get()));
|
||||||
RemoveEvictInfoFromDisk(mEntries[0]->mInfo, mEntries[0]->mPinned);
|
RemoveEvictInfoFromDisk(mEntries[0]->mInfo, mEntries[0]->mPinned,
|
||||||
|
mEntries[0]->mOrigin);
|
||||||
mEntries.RemoveElementAt(0);
|
mEntries.RemoveElementAt(0);
|
||||||
continue;
|
continue;
|
||||||
} else if (NS_FAILED(rv)) {
|
} else if (NS_FAILED(rv)) {
|
||||||
|
|
@ -634,6 +657,47 @@ CacheFileContextEvictor::EvictEntries()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mEntries[0]->mOrigin.IsEmpty()) {
|
||||||
|
nsCOMPtr<nsIFile> file;
|
||||||
|
CacheFileIOManager::gInstance->GetFile(&hash, getter_AddRefs(file));
|
||||||
|
|
||||||
|
// Read metadata from the file synchronously
|
||||||
|
RefPtr<CacheFileMetadata> metadata = new CacheFileMetadata();
|
||||||
|
rv = metadata->SyncReadMetadata(file);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now get the context + enhance id + URL from the key.
|
||||||
|
nsAutoCString key;
|
||||||
|
metadata->GetKey(key);
|
||||||
|
|
||||||
|
nsAutoCString uriSpec;
|
||||||
|
|
||||||
|
RefPtr<nsILoadContextInfo> info =
|
||||||
|
CacheFileUtils::ParseKey(key, nullptr, &uriSpec);
|
||||||
|
MOZ_ASSERT(info);
|
||||||
|
if (!info) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<MozURL> url;
|
||||||
|
rv = MozURL::Init(getter_AddRefs(url), uriSpec);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
LOG(("CacheFileContextEvictor::EvictEntries() - Skipping entry since MozURL "
|
||||||
|
"fails in the parsing of the uriSpec"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoCString urlOrigin;
|
||||||
|
url->Origin(urlOrigin);
|
||||||
|
if (urlOrigin.Equals(NS_ConvertUTF16toUTF8(mEntries[0]->mOrigin))) {
|
||||||
|
LOG(("CacheFileContextEvictor::EvictEntries() - Skipping entry since origin "
|
||||||
|
"doesn't match"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsAutoCString leafName;
|
nsAutoCString leafName;
|
||||||
CacheFileIOManager::HashToStr(&hash, leafName);
|
CacheFileIOManager::HashToStr(&hash, leafName);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ struct CacheFileContextEvictorEntry
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsILoadContextInfo> mInfo;
|
nsCOMPtr<nsILoadContextInfo> mInfo;
|
||||||
bool mPinned;
|
bool mPinned;
|
||||||
|
nsString mOrigin; // it can be empty
|
||||||
PRTime mTimeStamp; // in milliseconds
|
PRTime mTimeStamp; // in milliseconds
|
||||||
RefPtr<CacheIndexIterator> mIterator;
|
RefPtr<CacheIndexIterator> mIterator;
|
||||||
};
|
};
|
||||||
|
|
@ -41,8 +42,9 @@ public:
|
||||||
|
|
||||||
// Returns number of contexts that are being evicted.
|
// Returns number of contexts that are being evicted.
|
||||||
uint32_t ContextsCount();
|
uint32_t ContextsCount();
|
||||||
// Start evicting given context.
|
// Start evicting given context and an origin, if not empty.
|
||||||
nsresult AddContext(nsILoadContextInfo *aLoadContextInfo, bool aPinned);
|
nsresult AddContext(nsILoadContextInfo *aLoadContextInfo, bool aPinned,
|
||||||
|
const nsAString& aOrigin);
|
||||||
// CacheFileIOManager calls this method when CacheIndex's state changes. We
|
// CacheFileIOManager calls this method when CacheIndex's state changes. We
|
||||||
// check whether the index is up to date and start or stop evicting according
|
// check whether the index is up to date and start or stop evicting according
|
||||||
// to index's state.
|
// to index's state.
|
||||||
|
|
@ -60,15 +62,17 @@ private:
|
||||||
// done for every context added to the evictor to be able to recover eviction
|
// done for every context added to the evictor to be able to recover eviction
|
||||||
// after a shutdown or crash. When the context file is found after startup, we
|
// after a shutdown or crash. When the context file is found after startup, we
|
||||||
// restore mTimeStamp from the last modified time of the file.
|
// restore mTimeStamp from the last modified time of the file.
|
||||||
nsresult PersistEvictionInfoToDisk(nsILoadContextInfo *aLoadContextInfo, bool aPinned);
|
nsresult PersistEvictionInfoToDisk(nsILoadContextInfo *aLoadContextInfo,
|
||||||
|
bool aPinned, const nsAString& aOrigin);
|
||||||
// Once we are done with eviction for the given context, the eviction info is
|
// Once we are done with eviction for the given context, the eviction info is
|
||||||
// removed from the disk.
|
// removed from the disk.
|
||||||
nsresult RemoveEvictInfoFromDisk(nsILoadContextInfo *aLoadContextInfo, bool aPinned);
|
nsresult RemoveEvictInfoFromDisk(nsILoadContextInfo *aLoadContextInfo,
|
||||||
|
bool aPinned, const nsAString& aOrigin);
|
||||||
// Tries to load all contexts from the disk. This method is called just once
|
// Tries to load all contexts from the disk. This method is called just once
|
||||||
// after startup.
|
// after startup.
|
||||||
nsresult LoadEvictInfoFromDisk();
|
nsresult LoadEvictInfoFromDisk();
|
||||||
nsresult GetContextFile(nsILoadContextInfo *aLoadContextInfo, bool aPinned,
|
nsresult GetContextFile(nsILoadContextInfo *aLoadContextInfo, bool aPinned,
|
||||||
nsIFile **_retval);
|
const nsAString& aOrigin, nsIFile **_retval);
|
||||||
|
|
||||||
void CreateIterators();
|
void CreateIterators();
|
||||||
void CloseIterators();
|
void CloseIterators();
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#include "nsIObserverService.h"
|
#include "nsIObserverService.h"
|
||||||
#include "nsICacheStorageVisitor.h"
|
#include "nsICacheStorageVisitor.h"
|
||||||
#include "nsISizeOf.h"
|
#include "nsISizeOf.h"
|
||||||
|
#include "mozilla/net/MozURL.h"
|
||||||
#include "mozilla/Telemetry.h"
|
#include "mozilla/Telemetry.h"
|
||||||
#include "mozilla/DebugOnly.h"
|
#include "mozilla/DebugOnly.h"
|
||||||
#include "mozilla/Services.h"
|
#include "mozilla/Services.h"
|
||||||
|
|
@ -3134,7 +3135,9 @@ CacheFileIOManager::EvictAllInternal()
|
||||||
|
|
||||||
// static
|
// static
|
||||||
nsresult
|
nsresult
|
||||||
CacheFileIOManager::EvictByContext(nsILoadContextInfo *aLoadContextInfo, bool aPinned)
|
CacheFileIOManager::EvictByContext(nsILoadContextInfo *aLoadContextInfo,
|
||||||
|
bool aPinned,
|
||||||
|
const nsAString& aOrigin)
|
||||||
{
|
{
|
||||||
LOG(("CacheFileIOManager::EvictByContext() [loadContextInfo=%p]",
|
LOG(("CacheFileIOManager::EvictByContext() [loadContextInfo=%p]",
|
||||||
aLoadContextInfo));
|
aLoadContextInfo));
|
||||||
|
|
@ -3147,12 +3150,13 @@ CacheFileIOManager::EvictByContext(nsILoadContextInfo *aLoadContextInfo, bool aP
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> ev;
|
nsCOMPtr<nsIRunnable> ev;
|
||||||
ev = NewRunnableMethod<nsCOMPtr<nsILoadContextInfo>, bool>(
|
ev = NewRunnableMethod<nsCOMPtr<nsILoadContextInfo>, bool, nsString>(
|
||||||
"net::CacheFileIOManager::EvictByContextInternal",
|
"net::CacheFileIOManager::EvictByContextInternal",
|
||||||
ioMan,
|
ioMan,
|
||||||
&CacheFileIOManager::EvictByContextInternal,
|
&CacheFileIOManager::EvictByContextInternal,
|
||||||
aLoadContextInfo,
|
aLoadContextInfo,
|
||||||
aPinned);
|
aPinned,
|
||||||
|
aOrigin);
|
||||||
|
|
||||||
rv = ioMan->mIOThread->DispatchAfterPendingOpens(ev);
|
rv = ioMan->mIOThread->DispatchAfterPendingOpens(ev);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
|
@ -3163,7 +3167,9 @@ CacheFileIOManager::EvictByContext(nsILoadContextInfo *aLoadContextInfo, bool aP
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
CacheFileIOManager::EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo, bool aPinned)
|
CacheFileIOManager::EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo,
|
||||||
|
bool aPinned,
|
||||||
|
const nsAString& aOrigin)
|
||||||
{
|
{
|
||||||
LOG(("CacheFileIOManager::EvictByContextInternal() [loadContextInfo=%p, pinned=%d]",
|
LOG(("CacheFileIOManager::EvictByContextInternal() [loadContextInfo=%p, pinned=%d]",
|
||||||
aLoadContextInfo, aPinned));
|
aLoadContextInfo, aPinned));
|
||||||
|
|
@ -3206,6 +3212,8 @@ CacheFileIOManager::EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_ConvertUTF16toUTF8 origin(aOrigin);
|
||||||
|
|
||||||
// Doom all active handles that matches the load context
|
// Doom all active handles that matches the load context
|
||||||
nsTArray<RefPtr<CacheFileHandle> > handles;
|
nsTArray<RefPtr<CacheFileHandle> > handles;
|
||||||
mHandles.GetActiveHandles(&handles);
|
mHandles.GetActiveHandles(&handles);
|
||||||
|
|
@ -3213,18 +3221,30 @@ CacheFileIOManager::EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo,
|
||||||
for (uint32_t i = 0; i < handles.Length(); ++i) {
|
for (uint32_t i = 0; i < handles.Length(); ++i) {
|
||||||
CacheFileHandle* handle = handles[i];
|
CacheFileHandle* handle = handles[i];
|
||||||
|
|
||||||
if (aLoadContextInfo) {
|
nsAutoCString uriSpec;
|
||||||
bool equals;
|
RefPtr<nsILoadContextInfo> info =
|
||||||
rv = CacheFileUtils::KeyMatchesLoadContextInfo(handle->Key(),
|
CacheFileUtils::ParseKey(handle->Key(), nullptr, &uriSpec);
|
||||||
aLoadContextInfo,
|
if (!info) {
|
||||||
&equals);
|
LOG(("CacheFileIOManager::EvictByContextInternal() - Cannot parse key in "
|
||||||
|
"handle! [handle=%p, key=%s]", handle, handle->Key().get()));
|
||||||
|
MOZ_CRASH("Unexpected error!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aLoadContextInfo && !info->Equals(aLoadContextInfo)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!origin.IsEmpty()) {
|
||||||
|
RefPtr<MozURL> url;
|
||||||
|
rv = MozURL::Init(getter_AddRefs(url), uriSpec);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
LOG(("CacheFileIOManager::EvictByContextInternal() - Cannot parse key in "
|
continue;
|
||||||
"handle! [handle=%p, key=%s]", handle, handle->Key().get()));
|
|
||||||
MOZ_CRASH("Unexpected error!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!equals) {
|
nsAutoCString urlOrigin;
|
||||||
|
url->Origin(urlOrigin);
|
||||||
|
|
||||||
|
if (!urlOrigin.Equals(origin)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3250,7 +3270,7 @@ CacheFileIOManager::EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo,
|
||||||
mContextEvictor->Init(mCacheDirectory);
|
mContextEvictor->Init(mCacheDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
mContextEvictor->AddContext(aLoadContextInfo, aPinned);
|
mContextEvictor->AddContext(aLoadContextInfo, aPinned, aOrigin);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -332,7 +332,8 @@ public:
|
||||||
static nsresult EvictIfOverLimit();
|
static nsresult EvictIfOverLimit();
|
||||||
static nsresult EvictAll();
|
static nsresult EvictAll();
|
||||||
static nsresult EvictByContext(nsILoadContextInfo *aLoadContextInfo,
|
static nsresult EvictByContext(nsILoadContextInfo *aLoadContextInfo,
|
||||||
bool aPinning);
|
bool aPinning,
|
||||||
|
const nsAString& aOrigin);
|
||||||
|
|
||||||
static nsresult InitIndexEntry(CacheFileHandle *aHandle,
|
static nsresult InitIndexEntry(CacheFileHandle *aHandle,
|
||||||
OriginAttrsHash aOriginAttrsHash,
|
OriginAttrsHash aOriginAttrsHash,
|
||||||
|
|
@ -417,7 +418,7 @@ private:
|
||||||
nsresult OverLimitEvictionInternal();
|
nsresult OverLimitEvictionInternal();
|
||||||
nsresult EvictAllInternal();
|
nsresult EvictAllInternal();
|
||||||
nsresult EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo,
|
nsresult EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo,
|
||||||
bool aPinning);
|
bool aPinning, const nsAString& aOrigin);
|
||||||
|
|
||||||
nsresult TrashDirectory(nsIFile *aFile);
|
nsresult TrashDirectory(nsIFile *aFile);
|
||||||
static void OnTrashTimer(nsITimer *aTimer, void *aClosure);
|
static void OnTrashTimer(nsITimer *aTimer, void *aClosure);
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "nsIFile.h"
|
#include "nsIFile.h"
|
||||||
#include "nsIURI.h"
|
#include "nsIURI.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
#include "nsAutoPtr.h"
|
#include "nsAutoPtr.h"
|
||||||
#include "nsNetCID.h"
|
#include "nsNetCID.h"
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
|
|
@ -795,7 +796,117 @@ NS_IMETHODIMP CacheStorageService::Clear()
|
||||||
|
|
||||||
// Passing null as a load info means to evict all contexts.
|
// Passing null as a load info means to evict all contexts.
|
||||||
// EvictByContext() respects the entry pinning. EvictAll() does not.
|
// EvictByContext() respects the entry pinning. EvictAll() does not.
|
||||||
rv = CacheFileIOManager::EvictByContext(nullptr, false);
|
rv = CacheFileIOManager::EvictByContext(nullptr, false, EmptyString());
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP CacheStorageService::ClearOrigin(nsIPrincipal* aPrincipal)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
if (NS_WARN_IF(!aPrincipal)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString origin;
|
||||||
|
rv = nsContentUtils::GetUTFOrigin(aPrincipal, origin);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
rv = ClearOriginInternal(origin, aPrincipal->OriginAttributesRef(), true);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
rv = ClearOriginInternal(origin, aPrincipal->OriginAttributesRef(), false);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
RemoveExactEntry(CacheEntryTable* aEntries,
|
||||||
|
nsACString const& aKey,
|
||||||
|
CacheEntry* aEntry,
|
||||||
|
bool aOverwrite)
|
||||||
|
{
|
||||||
|
RefPtr<CacheEntry> existingEntry;
|
||||||
|
if (!aEntries->Get(aKey, getter_AddRefs(existingEntry))) {
|
||||||
|
LOG(("RemoveExactEntry [entry=%p already gone]", aEntry));
|
||||||
|
return false; // Already removed...
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aOverwrite && existingEntry != aEntry) {
|
||||||
|
LOG(("RemoveExactEntry [entry=%p already replaced]", aEntry));
|
||||||
|
return false; // Already replaced...
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(("RemoveExactEntry [entry=%p removed]", aEntry));
|
||||||
|
aEntries->Remove(aKey);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
CacheStorageService::ClearOriginInternal(const nsAString& aOrigin,
|
||||||
|
const OriginAttributes& aOriginAttributes,
|
||||||
|
bool aAnonymous)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
RefPtr<LoadContextInfo> info =
|
||||||
|
GetLoadContextInfo(aAnonymous, aOriginAttributes);
|
||||||
|
if (NS_WARN_IF(!info)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::MutexAutoLock lock(mLock);
|
||||||
|
|
||||||
|
if (sGlobalEntryTables) {
|
||||||
|
for (auto iter = sGlobalEntryTables->Iter(); !iter.Done(); iter.Next()) {
|
||||||
|
bool matches = false;
|
||||||
|
rv = CacheFileUtils::KeyMatchesLoadContextInfo(iter.Key(), info,
|
||||||
|
&matches);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
if (!matches) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CacheEntryTable* table = iter.UserData();
|
||||||
|
MOZ_ASSERT(table);
|
||||||
|
|
||||||
|
nsTArray<RefPtr<CacheEntry>> entriesToDelete;
|
||||||
|
|
||||||
|
for (auto entryIter = table->Iter(); !entryIter.Done(); entryIter.Next()) {
|
||||||
|
CacheEntry* entry = entryIter.UserData();
|
||||||
|
|
||||||
|
nsCOMPtr<nsIURI> uri;
|
||||||
|
rv = NS_NewURI(getter_AddRefs(uri), entry->GetURI());
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
nsAutoString origin;
|
||||||
|
rv = nsContentUtils::GetUTFOrigin(uri, origin);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (origin != aOrigin) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
entriesToDelete.AppendElement(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (RefPtr<CacheEntry>& entry : entriesToDelete) {
|
||||||
|
nsAutoCString entryKey;
|
||||||
|
rv = entry->HashingKey(entryKey);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_ERROR("aEntry->HashingKey() failed?");
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveExactEntry(table, entryKey, entry, false /* don't overwrite */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = CacheFileIOManager::EvictByContext(info, false /* pinned */, aOrigin);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
@ -976,28 +1087,6 @@ AddExactEntry(CacheEntryTable* aEntries,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
RemoveExactEntry(CacheEntryTable* aEntries,
|
|
||||||
nsACString const& aKey,
|
|
||||||
CacheEntry* aEntry,
|
|
||||||
bool aOverwrite)
|
|
||||||
{
|
|
||||||
RefPtr<CacheEntry> existingEntry;
|
|
||||||
if (!aEntries->Get(aKey, getter_AddRefs(existingEntry))) {
|
|
||||||
LOG(("RemoveExactEntry [entry=%p already gone]", aEntry));
|
|
||||||
return false; // Already removed...
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!aOverwrite && existingEntry != aEntry) {
|
|
||||||
LOG(("RemoveExactEntry [entry=%p already replaced]", aEntry));
|
|
||||||
return false; // Already replaced...
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(("RemoveExactEntry [entry=%p removed]", aEntry));
|
|
||||||
aEntries->Remove(aKey);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CacheStorageService::RemoveEntry(CacheEntry* aEntry, bool aOnlyUnreferenced)
|
CacheStorageService::RemoveEntry(CacheEntry* aEntry, bool aOnlyUnreferenced)
|
||||||
{
|
{
|
||||||
|
|
@ -1844,7 +1933,7 @@ CacheStorageService::DoomStorageEntries(const nsACString& aContextKey,
|
||||||
|
|
||||||
if (aContext && !aContext->IsPrivate()) {
|
if (aContext && !aContext->IsPrivate()) {
|
||||||
LOG((" dooming disk entries"));
|
LOG((" dooming disk entries"));
|
||||||
CacheFileIOManager::EvictByContext(aContext, aPinned);
|
CacheFileIOManager::EvictByContext(aContext, aPinned, EmptyString());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG((" dooming memory-only storage of %s", aContextKey.BeginReading()));
|
LOG((" dooming memory-only storage of %s", aContextKey.BeginReading()));
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,9 @@ class nsIThread;
|
||||||
class nsIEventTarget;
|
class nsIEventTarget;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
class OriginAttributes;
|
||||||
|
|
||||||
namespace net {
|
namespace net {
|
||||||
|
|
||||||
class CacheStorageService;
|
class CacheStorageService;
|
||||||
|
|
@ -311,6 +314,10 @@ private:
|
||||||
bool aReplace,
|
bool aReplace,
|
||||||
CacheEntryHandle** aResult);
|
CacheEntryHandle** aResult);
|
||||||
|
|
||||||
|
nsresult ClearOriginInternal(const nsAString& aOrigin,
|
||||||
|
const mozilla::OriginAttributes& aOriginAttributes,
|
||||||
|
bool aAnonymous);
|
||||||
|
|
||||||
static CacheStorageService* sSelf;
|
static CacheStorageService* sSelf;
|
||||||
|
|
||||||
mozilla::Mutex mLock;
|
mozilla::Mutex mLock;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ interface nsIApplicationCache;
|
||||||
interface nsIEventTarget;
|
interface nsIEventTarget;
|
||||||
interface nsICacheStorageConsumptionObserver;
|
interface nsICacheStorageConsumptionObserver;
|
||||||
interface nsICacheStorageVisitor;
|
interface nsICacheStorageVisitor;
|
||||||
|
interface nsIPrincipal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to particual cache storages of the network URI cache.
|
* Provides access to particual cache storages of the network URI cache.
|
||||||
|
|
@ -70,6 +71,14 @@ interface nsICacheStorageService : nsISupports
|
||||||
*/
|
*/
|
||||||
nsICacheStorage synthesizedCacheStorage(in nsILoadContextInfo aLoadContextInfo);
|
nsICacheStorage synthesizedCacheStorage(in nsILoadContextInfo aLoadContextInfo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evict any cache entry having the same origin of aPrincipal.
|
||||||
|
*
|
||||||
|
* @param aPrincipal
|
||||||
|
* The principal to compare the entries with.
|
||||||
|
*/
|
||||||
|
void clearOrigin(in nsIPrincipal aPrincipal);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evict the whole cache.
|
* Evict the whole cache.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
40
netwerk/test/unit/test_cache2-32-clear-origin.js
Normal file
40
netwerk/test/unit/test_cache2-32-clear-origin.js
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
const URL = "http://example.net";
|
||||||
|
const URL2 = "http://foo.bar";
|
||||||
|
|
||||||
|
function run_test()
|
||||||
|
{
|
||||||
|
do_get_profile();
|
||||||
|
|
||||||
|
asyncOpenCacheEntry(URL + "/a", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, null,
|
||||||
|
new OpenCallback(NEW, "e1m", "e1d", function(entry) {
|
||||||
|
asyncOpenCacheEntry(URL + "/a", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, null,
|
||||||
|
new OpenCallback(NORMAL, "e1m", "e1d", function(entry) {
|
||||||
|
asyncOpenCacheEntry(URL2 + "/a", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, null,
|
||||||
|
new OpenCallback(NEW, "f1m", "f1d", function(entry) {
|
||||||
|
asyncOpenCacheEntry(URL2 + "/a", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, null,
|
||||||
|
new OpenCallback(NORMAL, "f1m", "f1d", function(entry) {
|
||||||
|
var url = Services.io.newURI(URL);
|
||||||
|
var principal = Services.scriptSecurityManager.createCodebasePrincipal(url, {});
|
||||||
|
|
||||||
|
get_cache_service().clearOrigin(principal);
|
||||||
|
|
||||||
|
asyncOpenCacheEntry(URL + "/a", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, null,
|
||||||
|
new OpenCallback(NEW, "e1m", "e1d", function(entry) {
|
||||||
|
asyncOpenCacheEntry(URL2 + "/a", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, null,
|
||||||
|
new OpenCallback(NORMAL, "f1m", "f1d", function(entry) {
|
||||||
|
finish_cache2_test();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
do_test_pending();
|
||||||
|
}
|
||||||
|
|
@ -78,6 +78,7 @@ skip-if = true
|
||||||
[test_cache2-30c-pinning-deferred-doom.js]
|
[test_cache2-30c-pinning-deferred-doom.js]
|
||||||
[test_cache2-30d-pinning-WasEvicted-API.js]
|
[test_cache2-30d-pinning-WasEvicted-API.js]
|
||||||
[test_cache2-31-visit-all.js]
|
[test_cache2-31-visit-all.js]
|
||||||
|
[test_cache2-32-clear-origin.js]
|
||||||
[test_partial_response_entry_size_smart_shrink.js]
|
[test_partial_response_entry_size_smart_shrink.js]
|
||||||
[test_304_responses.js]
|
[test_304_responses.js]
|
||||||
[test_421.js]
|
[test_421.js]
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,13 @@ const CookieCleaner = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const NetworkCacheCleaner = {
|
const NetworkCacheCleaner = {
|
||||||
|
deleteByPrincipal(aPrincipal) {
|
||||||
|
return new Promise(aResolve => {
|
||||||
|
Services.cache2.asyncClearOrigin(aPrincipal);
|
||||||
|
aResolve();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
deleteAll() {
|
deleteAll() {
|
||||||
return new Promise(aResolve => {
|
return new Promise(aResolve => {
|
||||||
Services.cache2.clear();
|
Services.cache2.clear();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue