From 28962b5168ff77d9f8dba7546f64c11656b6fb8b Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Fri, 20 Jul 2018 13:57:18 +0200 Subject: [PATCH] Bug 1468501 - Implement a way to delete network cache by nsIPrincipal, r=mayhemer, r=michal --- netwerk/cache2/CacheFileContextEvictor.cpp | 84 +++++++++-- netwerk/cache2/CacheFileContextEvictor.h | 14 +- netwerk/cache2/CacheFileIOManager.cpp | 48 ++++-- netwerk/cache2/CacheFileIOManager.h | 5 +- netwerk/cache2/CacheStorageService.cpp | 137 +++++++++++++++--- netwerk/cache2/CacheStorageService.h | 7 + netwerk/cache2/nsICacheStorageService.idl | 9 ++ .../test/unit/test_cache2-32-clear-origin.js | 40 +++++ netwerk/test/unit/xpcshell.ini | 1 + .../components/cleardata/ClearDataService.js | 7 + 10 files changed, 297 insertions(+), 55 deletions(-) create mode 100644 netwerk/test/unit/test_cache2-32-clear-origin.js diff --git a/netwerk/cache2/CacheFileContextEvictor.cpp b/netwerk/cache2/CacheFileContextEvictor.cpp index e0261eecf622..1e297f319c72 100644 --- a/netwerk/cache2/CacheFileContextEvictor.cpp +++ b/netwerk/cache2/CacheFileContextEvictor.cpp @@ -16,6 +16,7 @@ #include "nsIDirectoryEnumerator.h" #include "mozilla/Base64.h" #include "mozilla/IntegerPrintfMacros.h" +#include "mozilla/net/MozURL.h" namespace mozilla { @@ -93,7 +94,8 @@ CacheFileContextEvictor::ContextsCount() nsresult CacheFileContextEvictor::AddContext(nsILoadContextInfo *aLoadContextInfo, - bool aPinned) + bool aPinned, + const nsAString& aOrigin) { LOG(("CacheFileContextEvictor::AddContext() [this=%p, loadContextInfo=%p, pinned=%d]", this, aLoadContextInfo, aPinned)); @@ -107,7 +109,8 @@ CacheFileContextEvictor::AddContext(nsILoadContextInfo *aLoadContextInfo, for (uint32_t i = 0; i < mEntries.Length(); ++i) { if (mEntries[i]->mInfo && mEntries[i]->mInfo->Equals(aLoadContextInfo) && - mEntries[i]->mPinned == aPinned) { + mEntries[i]->mPinned == aPinned && + mEntries[i]->mOrigin.Equals(aOrigin)) { entry = mEntries[i]; break; } @@ -119,7 +122,8 @@ CacheFileContextEvictor::AddContext(nsILoadContextInfo *aLoadContextInfo, for (uint32_t i = mEntries.Length(); i > 0;) { --i; 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); } } @@ -129,12 +133,13 @@ CacheFileContextEvictor::AddContext(nsILoadContextInfo *aLoadContextInfo, entry = new CacheFileContextEvictorEntry(); entry->mInfo = aLoadContextInfo; entry->mPinned = aPinned; + entry->mOrigin = aOrigin; mEntries.AppendElement(entry); } entry->mTimeStamp = PR_Now() / PR_USEC_PER_MSEC; - PersistEvictionInfoToDisk(aLoadContextInfo, aPinned); + PersistEvictionInfoToDisk(aLoadContextInfo, aPinned, aOrigin); if (mIndexIsUpToDate) { // Already existing context could be added again, in this case the iterator @@ -263,7 +268,8 @@ CacheFileContextEvictor::WasEvicted(const nsACString &aKey, nsIFile *aFile, nsresult CacheFileContextEvictor::PersistEvictionInfoToDisk( - nsILoadContextInfo *aLoadContextInfo, bool aPinned) + nsILoadContextInfo *aLoadContextInfo, bool aPinned, + const nsAString& aOrigin) { LOG(("CacheFileContextEvictor::PersistEvictionInfoToDisk() [this=%p, " "loadContextInfo=%p]", this, aLoadContextInfo)); @@ -273,7 +279,7 @@ CacheFileContextEvictor::PersistEvictionInfoToDisk( MOZ_ASSERT(CacheFileIOManager::IsOnIOThread()); nsCOMPtr file; - rv = GetContextFile(aLoadContextInfo, aPinned, getter_AddRefs(file)); + rv = GetContextFile(aLoadContextInfo, aPinned, aOrigin, getter_AddRefs(file)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } @@ -299,7 +305,7 @@ CacheFileContextEvictor::PersistEvictionInfoToDisk( nsresult CacheFileContextEvictor::RemoveEvictInfoFromDisk( - nsILoadContextInfo *aLoadContextInfo, bool aPinned) + nsILoadContextInfo *aLoadContextInfo, bool aPinned, const nsAString& aOrigin) { LOG(("CacheFileContextEvictor::RemoveEvictInfoFromDisk() [this=%p, " "loadContextInfo=%p]", this, aLoadContextInfo)); @@ -309,7 +315,7 @@ CacheFileContextEvictor::RemoveEvictInfoFromDisk( MOZ_ASSERT(CacheFileIOManager::IsOnIOThread()); nsCOMPtr file; - rv = GetContextFile(aLoadContextInfo, aPinned, getter_AddRefs(file)); + rv = GetContextFile(aLoadContextInfo, aPinned, aOrigin, getter_AddRefs(file)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } @@ -393,6 +399,16 @@ CacheFileContextEvictor::LoadEvictInfoFromDisk() 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 info; if (!NS_LITERAL_CSTRING("*").Equals(decoded)) { // "*" is indication of 'delete all', info left null will pass @@ -417,6 +433,7 @@ CacheFileContextEvictor::LoadEvictInfoFromDisk() CacheFileContextEvictorEntry *entry = new CacheFileContextEvictorEntry(); entry->mInfo = info; entry->mPinned = pinned; + CopyUTF8toUTF16(origin, entry->mOrigin); entry->mTimeStamp = lastModifiedTime; mEntries.AppendElement(entry); } @@ -427,6 +444,7 @@ CacheFileContextEvictor::LoadEvictInfoFromDisk() nsresult CacheFileContextEvictor::GetContextFile(nsILoadContextInfo *aLoadContextInfo, bool aPinned, + const nsAString& aOrigin, nsIFile **_retval) { nsresult rv; @@ -445,6 +463,10 @@ CacheFileContextEvictor::GetContextFile(nsILoadContextInfo *aLoadContextInfo, } else { keyPrefix.Append('*'); } + if (!aOrigin.IsEmpty()) { + keyPrefix.Append('\t'); + keyPrefix.Append(NS_ConvertUTF16toUTF8(aOrigin)); + } nsAutoCString data64; rv = Base64Encode(keyPrefix, data64); @@ -516,7 +538,7 @@ CacheFileContextEvictor::StartEvicting() MOZ_ASSERT(CacheFileIOManager::IsOnIOThread()); if (mEvicting) { - LOG(("CacheFileContextEvictor::StartEvicting() - already evicintg.")); + LOG(("CacheFileContextEvictor::StartEvicting() - already evicting.")); return; } @@ -590,7 +612,8 @@ CacheFileContextEvictor::EvictEntries() LOG(("CacheFileContextEvictor::EvictEntries() - No more entries left in " "iterator. [iterator=%p, info=%p]", mEntries[0]->mIterator.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); continue; } else if (NS_FAILED(rv)) { @@ -634,6 +657,47 @@ CacheFileContextEvictor::EvictEntries() continue; } + if (!mEntries[0]->mOrigin.IsEmpty()) { + nsCOMPtr file; + CacheFileIOManager::gInstance->GetFile(&hash, getter_AddRefs(file)); + + // Read metadata from the file synchronously + RefPtr 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 info = + CacheFileUtils::ParseKey(key, nullptr, &uriSpec); + MOZ_ASSERT(info); + if (!info) { + continue; + } + + RefPtr 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; CacheFileIOManager::HashToStr(&hash, leafName); diff --git a/netwerk/cache2/CacheFileContextEvictor.h b/netwerk/cache2/CacheFileContextEvictor.h index 3a0ee1da59b8..1ba88a0e3aeb 100644 --- a/netwerk/cache2/CacheFileContextEvictor.h +++ b/netwerk/cache2/CacheFileContextEvictor.h @@ -21,6 +21,7 @@ struct CacheFileContextEvictorEntry { nsCOMPtr mInfo; bool mPinned; + nsString mOrigin; // it can be empty PRTime mTimeStamp; // in milliseconds RefPtr mIterator; }; @@ -41,8 +42,9 @@ public: // Returns number of contexts that are being evicted. uint32_t ContextsCount(); - // Start evicting given context. - nsresult AddContext(nsILoadContextInfo *aLoadContextInfo, bool aPinned); + // Start evicting given context and an origin, if not empty. + nsresult AddContext(nsILoadContextInfo *aLoadContextInfo, bool aPinned, + const nsAString& aOrigin); // CacheFileIOManager calls this method when CacheIndex's state changes. We // check whether the index is up to date and start or stop evicting according // to index's state. @@ -60,15 +62,17 @@ private: // 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 // 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 // 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 // after startup. nsresult LoadEvictInfoFromDisk(); nsresult GetContextFile(nsILoadContextInfo *aLoadContextInfo, bool aPinned, - nsIFile **_retval); + const nsAString& aOrigin, nsIFile **_retval); void CreateIterators(); void CloseIterators(); diff --git a/netwerk/cache2/CacheFileIOManager.cpp b/netwerk/cache2/CacheFileIOManager.cpp index e6c6a8c2ea85..a24abf9b2782 100644 --- a/netwerk/cache2/CacheFileIOManager.cpp +++ b/netwerk/cache2/CacheFileIOManager.cpp @@ -21,6 +21,7 @@ #include "nsIObserverService.h" #include "nsICacheStorageVisitor.h" #include "nsISizeOf.h" +#include "mozilla/net/MozURL.h" #include "mozilla/Telemetry.h" #include "mozilla/DebugOnly.h" #include "mozilla/Services.h" @@ -3134,7 +3135,9 @@ CacheFileIOManager::EvictAllInternal() // static nsresult -CacheFileIOManager::EvictByContext(nsILoadContextInfo *aLoadContextInfo, bool aPinned) +CacheFileIOManager::EvictByContext(nsILoadContextInfo *aLoadContextInfo, + bool aPinned, + const nsAString& aOrigin) { LOG(("CacheFileIOManager::EvictByContext() [loadContextInfo=%p]", aLoadContextInfo)); @@ -3147,12 +3150,13 @@ CacheFileIOManager::EvictByContext(nsILoadContextInfo *aLoadContextInfo, bool aP } nsCOMPtr ev; - ev = NewRunnableMethod, bool>( + ev = NewRunnableMethod, bool, nsString>( "net::CacheFileIOManager::EvictByContextInternal", ioMan, &CacheFileIOManager::EvictByContextInternal, aLoadContextInfo, - aPinned); + aPinned, + aOrigin); rv = ioMan->mIOThread->DispatchAfterPendingOpens(ev); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -3163,7 +3167,9 @@ CacheFileIOManager::EvictByContext(nsILoadContextInfo *aLoadContextInfo, bool aP } nsresult -CacheFileIOManager::EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo, bool aPinned) +CacheFileIOManager::EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo, + bool aPinned, + const nsAString& aOrigin) { LOG(("CacheFileIOManager::EvictByContextInternal() [loadContextInfo=%p, pinned=%d]", aLoadContextInfo, aPinned)); @@ -3206,6 +3212,8 @@ CacheFileIOManager::EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo, } } + NS_ConvertUTF16toUTF8 origin(aOrigin); + // Doom all active handles that matches the load context nsTArray > handles; mHandles.GetActiveHandles(&handles); @@ -3213,18 +3221,30 @@ CacheFileIOManager::EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo, for (uint32_t i = 0; i < handles.Length(); ++i) { CacheFileHandle* handle = handles[i]; - if (aLoadContextInfo) { - bool equals; - rv = CacheFileUtils::KeyMatchesLoadContextInfo(handle->Key(), - aLoadContextInfo, - &equals); + nsAutoCString uriSpec; + RefPtr info = + CacheFileUtils::ParseKey(handle->Key(), nullptr, &uriSpec); + if (!info) { + 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 url; + rv = MozURL::Init(getter_AddRefs(url), uriSpec); if (NS_FAILED(rv)) { - LOG(("CacheFileIOManager::EvictByContextInternal() - Cannot parse key in " - "handle! [handle=%p, key=%s]", handle, handle->Key().get())); - MOZ_CRASH("Unexpected error!"); + continue; } - if (!equals) { + nsAutoCString urlOrigin; + url->Origin(urlOrigin); + + if (!urlOrigin.Equals(origin)) { continue; } } @@ -3250,7 +3270,7 @@ CacheFileIOManager::EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo, mContextEvictor->Init(mCacheDirectory); } - mContextEvictor->AddContext(aLoadContextInfo, aPinned); + mContextEvictor->AddContext(aLoadContextInfo, aPinned, aOrigin); return NS_OK; } diff --git a/netwerk/cache2/CacheFileIOManager.h b/netwerk/cache2/CacheFileIOManager.h index c77e7ec501c6..dc38ac26ea22 100644 --- a/netwerk/cache2/CacheFileIOManager.h +++ b/netwerk/cache2/CacheFileIOManager.h @@ -332,7 +332,8 @@ public: static nsresult EvictIfOverLimit(); static nsresult EvictAll(); static nsresult EvictByContext(nsILoadContextInfo *aLoadContextInfo, - bool aPinning); + bool aPinning, + const nsAString& aOrigin); static nsresult InitIndexEntry(CacheFileHandle *aHandle, OriginAttrsHash aOriginAttrsHash, @@ -417,7 +418,7 @@ private: nsresult OverLimitEvictionInternal(); nsresult EvictAllInternal(); nsresult EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo, - bool aPinning); + bool aPinning, const nsAString& aOrigin); nsresult TrashDirectory(nsIFile *aFile); static void OnTrashTimer(nsITimer *aTimer, void *aClosure); diff --git a/netwerk/cache2/CacheStorageService.cpp b/netwerk/cache2/CacheStorageService.cpp index a9f94bcfa79c..77997e2a063e 100644 --- a/netwerk/cache2/CacheStorageService.cpp +++ b/netwerk/cache2/CacheStorageService.cpp @@ -24,6 +24,7 @@ #include "nsIFile.h" #include "nsIURI.h" #include "nsCOMPtr.h" +#include "nsContentUtils.h" #include "nsAutoPtr.h" #include "nsNetCID.h" #include "nsNetUtil.h" @@ -795,7 +796,117 @@ NS_IMETHODIMP CacheStorageService::Clear() // Passing null as a load info means to evict all contexts. // 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 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 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> entriesToDelete; + + for (auto entryIter = table->Iter(); !entryIter.Done(); entryIter.Next()) { + CacheEntry* entry = entryIter.UserData(); + + nsCOMPtr 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& 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); return NS_OK; @@ -976,28 +1087,6 @@ AddExactEntry(CacheEntryTable* aEntries, return true; } -static bool -RemoveExactEntry(CacheEntryTable* aEntries, - nsACString const& aKey, - CacheEntry* aEntry, - bool aOverwrite) -{ - RefPtr 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 CacheStorageService::RemoveEntry(CacheEntry* aEntry, bool aOnlyUnreferenced) { @@ -1844,7 +1933,7 @@ CacheStorageService::DoomStorageEntries(const nsACString& aContextKey, if (aContext && !aContext->IsPrivate()) { LOG((" dooming disk entries")); - CacheFileIOManager::EvictByContext(aContext, aPinned); + CacheFileIOManager::EvictByContext(aContext, aPinned, EmptyString()); } } else { LOG((" dooming memory-only storage of %s", aContextKey.BeginReading())); diff --git a/netwerk/cache2/CacheStorageService.h b/netwerk/cache2/CacheStorageService.h index 56c604e2bdc8..17b7da6fac8a 100644 --- a/netwerk/cache2/CacheStorageService.h +++ b/netwerk/cache2/CacheStorageService.h @@ -30,6 +30,9 @@ class nsIThread; class nsIEventTarget; namespace mozilla { + +class OriginAttributes; + namespace net { class CacheStorageService; @@ -311,6 +314,10 @@ private: bool aReplace, CacheEntryHandle** aResult); + nsresult ClearOriginInternal(const nsAString& aOrigin, + const mozilla::OriginAttributes& aOriginAttributes, + bool aAnonymous); + static CacheStorageService* sSelf; mozilla::Mutex mLock; diff --git a/netwerk/cache2/nsICacheStorageService.idl b/netwerk/cache2/nsICacheStorageService.idl index dc9714796ee9..5c29759cd93a 100644 --- a/netwerk/cache2/nsICacheStorageService.idl +++ b/netwerk/cache2/nsICacheStorageService.idl @@ -10,6 +10,7 @@ interface nsIApplicationCache; interface nsIEventTarget; interface nsICacheStorageConsumptionObserver; interface nsICacheStorageVisitor; +interface nsIPrincipal; /** * Provides access to particual cache storages of the network URI cache. @@ -70,6 +71,14 @@ interface nsICacheStorageService : nsISupports */ 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. */ diff --git a/netwerk/test/unit/test_cache2-32-clear-origin.js b/netwerk/test/unit/test_cache2-32-clear-origin.js new file mode 100644 index 000000000000..1f2ab7fdf6f9 --- /dev/null +++ b/netwerk/test/unit/test_cache2-32-clear-origin.js @@ -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(); +} diff --git a/netwerk/test/unit/xpcshell.ini b/netwerk/test/unit/xpcshell.ini index 33eb1be20ba0..c880e61ab946 100644 --- a/netwerk/test/unit/xpcshell.ini +++ b/netwerk/test/unit/xpcshell.ini @@ -78,6 +78,7 @@ skip-if = true [test_cache2-30c-pinning-deferred-doom.js] [test_cache2-30d-pinning-WasEvicted-API.js] [test_cache2-31-visit-all.js] +[test_cache2-32-clear-origin.js] [test_partial_response_entry_size_smart_shrink.js] [test_304_responses.js] [test_421.js] diff --git a/toolkit/components/cleardata/ClearDataService.js b/toolkit/components/cleardata/ClearDataService.js index a93f67e64ece..967dae182e18 100644 --- a/toolkit/components/cleardata/ClearDataService.js +++ b/toolkit/components/cleardata/ClearDataService.js @@ -86,6 +86,13 @@ const CookieCleaner = { }; const NetworkCacheCleaner = { + deleteByPrincipal(aPrincipal) { + return new Promise(aResolve => { + Services.cache2.asyncClearOrigin(aPrincipal); + aResolve(); + }); + }, + deleteAll() { return new Promise(aResolve => { Services.cache2.clear();