Backed out changeset d8543551f12e (bug 913808)
authorEd Morley <emorley@mozilla.com>
Wed, 05 Mar 2014 17:25:04 +0000
changeset 189278 35590ae1652437e8e99f7be08fccc8dc37512182
parent 189277 38462b96cd96e7e99a4dbdea8241468d4493c035
child 189279 ce0ac2767d138e2280490bcc910eb0c339864555
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs913808
milestone30.0a1
backs outd8543551f12eb0f98b348a1b2ea5a21aa12b8bfe
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset d8543551f12e (bug 913808)
netwerk/cache2/CacheEntriesEnumerator.cpp
netwerk/cache2/CacheEntriesEnumerator.h
netwerk/cache2/CacheEntry.cpp
netwerk/cache2/CacheEntry.h
netwerk/cache2/CacheFile.cpp
netwerk/cache2/CacheFile.h
netwerk/cache2/CacheFileIOManager.cpp
netwerk/cache2/CacheFileIOManager.h
netwerk/cache2/CacheFileMetadata.cpp
netwerk/cache2/CacheFileMetadata.h
netwerk/cache2/CacheFileUtils.cpp
netwerk/cache2/CacheFileUtils.h
netwerk/cache2/CacheIOThread.h
netwerk/cache2/CacheIndex.cpp
netwerk/cache2/CacheIndex.h
netwerk/cache2/CacheStorageService.cpp
netwerk/cache2/CacheStorageService.h
netwerk/cache2/moz.build
--- a/netwerk/cache2/CacheEntriesEnumerator.cpp
+++ b/netwerk/cache2/CacheEntriesEnumerator.cpp
@@ -75,22 +75,112 @@ bool CacheEntriesEnumerator::HasMore()
     mEnumerator->Close();
     mEnumerator = nullptr;
     return false;
   }
 
   return !!mCurrentFile;
 }
 
+namespace { // anon
+
+class FileConsumer : public CacheFileListener
+{
+public:
+  NS_DECL_THREADSAFE_ISUPPORTS
+
+  nsresult Init(nsCSubstring const & aKey,
+                CacheEntriesEnumeratorCallback* aCallback);
+
+  virtual ~FileConsumer() {}
+
+private:
+  NS_IMETHOD OnFileReady(nsresult aResult, bool aIsNew);
+  NS_IMETHOD OnFileDoomed(nsresult aResult) { return NS_OK; }
+
+  nsRefPtr<CacheFile> mFile;
+  nsRefPtr<CacheEntriesEnumeratorCallback> mCallback;
+};
+
+nsresult FileConsumer::Init(const nsCSubstring &aKey,
+                            CacheEntriesEnumeratorCallback *aCallback)
+{
+  mCallback = aCallback;
+
+  mFile = new CacheFile();
+  nsresult rv = mFile->Init(aKey, false, false, false, true, this);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP FileConsumer::OnFileReady(nsresult aResult, bool aIsNew)
+{
+  //MOZ_ASSERT(!aIsNew);
+
+  if (NS_FAILED(aResult)) {
+    mCallback->OnFile(nullptr);
+  }
+  else {
+    mCallback->OnFile(mFile);
+  }
+
+  return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS1(FileConsumer, CacheFileListener);
+
+} // anon
+
+nsresult CacheEntriesEnumerator::GetNextCacheFile(CacheEntriesEnumeratorCallback* aCallback)
+{
+#ifdef DEBUG
+  MOZ_ASSERT(mThreadCheck == NS_GetCurrentThread());
+#endif
+
+  nsresult rv;
+
+  NS_ENSURE_TRUE(mCurrentFile, NS_ERROR_UNEXPECTED);
+
+  nsAutoCString key;
+  rv = mCurrentFile->GetNativeLeafName(key);
+
+  mCurrentFile = nullptr;
+
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsRefPtr<FileConsumer> consumer = new FileConsumer();
+  rv = consumer->Init(key, aCallback);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
 nsresult CacheEntriesEnumerator::GetNextFile(nsIFile** aFile)
 {
 #ifdef DEBUG
   MOZ_ASSERT(mThreadCheck == NS_GetCurrentThread());
 #endif
 
   NS_ENSURE_TRUE(mCurrentFile, NS_ERROR_UNEXPECTED);
 
   mCurrentFile.forget(aFile);
   return NS_OK;
 }
 
+nsresult CacheEntriesEnumerator::GetCacheFileFromFile(nsIFile* aFile,
+                                                      CacheEntriesEnumeratorCallback* aCallback)
+{
+  nsresult rv;
+
+  nsAutoCString key;
+  rv = aFile->GetNativeLeafName(key);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsRefPtr<FileConsumer> consumer = new FileConsumer();
+  rv = consumer->Init(key, aCallback);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
 } // net
 } // mozilla
--- a/netwerk/cache2/CacheEntriesEnumerator.h
+++ b/netwerk/cache2/CacheEntriesEnumerator.h
@@ -25,17 +25,19 @@ public:
 };
 
 class CacheEntriesEnumerator
 {
 public:
   ~CacheEntriesEnumerator();
 
   bool HasMore();
+  nsresult GetNextCacheFile(CacheEntriesEnumeratorCallback* aCallback);
   nsresult GetNextFile(nsIFile** aFile);
+  nsresult GetCacheFileFromFile(nsIFile* aFile, CacheEntriesEnumeratorCallback* aCallback);
 
 protected:
   friend class CacheFileIOManager;
   CacheEntriesEnumerator(nsIFile* aEntriesDirectory);
   nsresult Init();
 
 private:
   nsCOMPtr<nsIDirectoryEnumerator> mEnumerator;
--- a/netwerk/cache2/CacheEntry.cpp
+++ b/netwerk/cache2/CacheEntry.cpp
@@ -314,16 +314,17 @@ bool CacheEntry::Load(bool aTruncate, bo
     rv = HashingKeyWithStorage(fileKey);
 
     LOG(("  performing load, file=%p", mFile.get()));
     if (NS_SUCCEEDED(rv)) {
       rv = mFile->Init(fileKey,
                        aTruncate,
                        !mUseDisk,
                        aPriority,
+                       false /* key is not a hash */,
                        directLoad ? nullptr : this);
     }
 
     if (NS_FAILED(rv)) {
       mFileStatus = rv;
       AsyncDoom(nullptr);
       return false;
     }
@@ -831,27 +832,16 @@ bool CacheEntry::IsReferenced() const
 {
   CacheStorageService::Self()->Lock().AssertCurrentThreadOwns();
 
   // Increasing this counter from 0 to non-null and this check both happen only
   // under the service lock.
   return mHandlersCount > 0;
 }
 
-bool CacheEntry::IsFileDoomed()
-{
-  mozilla::MutexAutoLock lock(mLock);
-
-  if (NS_SUCCEEDED(mFileStatus)) {
-    return mFile->IsDoomed();
-  }
-
-  return false;
-}
-
 uint32_t CacheEntry::GetMetadataMemoryConsumption()
 {
   NS_ENSURE_SUCCESS(mFileStatus, 0);
 
   uint32_t size;
   if (NS_FAILED(mFile->ElementsSize(&size)))
     return 0;
 
--- a/netwerk/cache2/CacheEntry.h
+++ b/netwerk/cache2/CacheEntry.h
@@ -65,17 +65,16 @@ public:
 public:
   uint32_t GetMetadataMemoryConsumption();
   nsCString const &GetStorageID() const { return mStorageID; }
   nsCString const &GetEnhanceID() const { return mEnhanceID; }
   nsIURI* GetURI() const { return mURI; }
   bool UsingDisk() const;
   bool SetUsingDisk(bool aUsingDisk);
   bool IsReferenced() const;
-  bool IsFileDoomed();
 
   // Methods for entry management (eviction from memory),
   // called only on the management thread.
 
   // TODO make these inline
   double GetFrecency() const;
   uint32_t GetExpirationTime() const;
 
--- a/netwerk/cache2/CacheFile.cpp
+++ b/netwerk/cache2/CacheFile.cpp
@@ -190,78 +190,88 @@ CacheFile::~CacheFile()
   }
 }
 
 nsresult
 CacheFile::Init(const nsACString &aKey,
                 bool aCreateNew,
                 bool aMemoryOnly,
                 bool aPriority,
+                bool aKeyIsHash,
                 CacheFileListener *aCallback)
 {
   MOZ_ASSERT(!mListener);
   MOZ_ASSERT(!mHandle);
+  MOZ_ASSERT(!(aCreateNew && aKeyIsHash));
+  MOZ_ASSERT(!(aMemoryOnly && aKeyIsHash));
 
   nsresult rv;
 
   mKey = aKey;
   mMemoryOnly = aMemoryOnly;
+  mKeyIsHash = aKeyIsHash;
 
   LOG(("CacheFile::Init() [this=%p, key=%s, createNew=%d, memoryOnly=%d, "
        "listener=%p]", this, mKey.get(), aCreateNew, aMemoryOnly, aCallback));
 
   if (mMemoryOnly) {
     MOZ_ASSERT(!aCallback);
 
+    MOZ_ASSERT(!mKeyIsHash);
     mMetadata = new CacheFileMetadata(mKey);
     mReady = true;
     mDataSize = mMetadata->Offset();
     return NS_OK;
   }
   else {
     uint32_t flags;
     if (aCreateNew) {
       MOZ_ASSERT(!aCallback);
       flags = CacheFileIOManager::CREATE_NEW;
 
       // make sure we can use this entry immediately
+      MOZ_ASSERT(!mKeyIsHash);
       mMetadata = new CacheFileMetadata(mKey);
       mReady = true;
       mDataSize = mMetadata->Offset();
     }
     else {
       flags = CacheFileIOManager::CREATE;
 
-      // Have a look into index and change to CREATE_NEW when we are sure
-      // that the entry does not exist.
-      CacheIndex::EntryStatus status;
-      rv = CacheIndex::HasEntry(mKey, &status);
-      if (status == CacheIndex::DOES_NOT_EXIST) {
-        LOG(("CacheFile::Init() - Forcing CREATE_NEW flag since we don't have"
-             " this entry according to index"));
-        flags = CacheFileIOManager::CREATE_NEW;
+      if (!mKeyIsHash) {
+        // Have a look into index and change to CREATE_NEW when we are sure
+        // that the entry does not exist.
+        CacheIndex::EntryStatus status;
+        rv = CacheIndex::HasEntry(mKey, &status);
+        if (status == CacheIndex::DOES_NOT_EXIST) {
+          LOG(("CacheFile::Init() - Forcing CREATE_NEW flag since we don't have"
+               " this entry according to index"));
+          flags = CacheFileIOManager::CREATE_NEW;
 
-        // make sure we can use this entry immediately
-        mMetadata = new CacheFileMetadata(mKey);
-        mReady = true;
-        mDataSize = mMetadata->Offset();
+          // make sure we can use this entry immediately
+          mMetadata = new CacheFileMetadata(mKey);
+          mReady = true;
+          mDataSize = mMetadata->Offset();
 
-        // Notify callback now and don't store it in mListener, no further
-        // operation can change the result.
-        nsRefPtr<NotifyCacheFileListenerEvent> ev;
-        ev = new NotifyCacheFileListenerEvent(aCallback, NS_OK, true);
-        rv = NS_DispatchToCurrentThread(ev);
-        NS_ENSURE_SUCCESS(rv, rv);
+          // Notify callback now and don't store it in mListener, no further
+          // operation can change the result.
+          nsRefPtr<NotifyCacheFileListenerEvent> ev;
+          ev = new NotifyCacheFileListenerEvent(aCallback, NS_OK, true);
+          rv = NS_DispatchToCurrentThread(ev);
+          NS_ENSURE_SUCCESS(rv, rv);
 
-        aCallback = nullptr;
+          aCallback = nullptr;
+        }
       }
     }
 
     if (aPriority)
       flags |= CacheFileIOManager::PRIORITY;
+    if (aKeyIsHash)
+      flags |= CacheFileIOManager::NOHASH;
 
     mOpeningFile = true;
     mListener = aCallback;
     rv = CacheFileIOManager::OpenFile(mKey, flags, this);
     if (NS_FAILED(rv)) {
       mListener = nullptr;
       mOpeningFile = false;
 
@@ -275,16 +285,17 @@ CacheFile::Init(const nsACString &aKey,
       }
       else if (rv == NS_ERROR_NOT_INITIALIZED) {
         NS_WARNING("Forcing memory-only entry since CacheIOManager isn't "
                    "initialized.");
         LOG(("CacheFile::Init() - CacheFileIOManager isn't initialized, "
              "initializing entry as memory-only. [this=%p]", this));
 
         mMemoryOnly = true;
+        MOZ_ASSERT(!mKeyIsHash);
         mMetadata = new CacheFileMetadata(mKey);
         mReady = true;
         mDataSize = mMetadata->Offset();
 
         nsRefPtr<NotifyCacheFileListenerEvent> ev;
         ev = new NotifyCacheFileListenerEvent(aCallback, NS_OK, true);
         rv = NS_DispatchToCurrentThread(ev);
         NS_ENSURE_SUCCESS(rv, rv);
@@ -472,16 +483,17 @@ CacheFile::OnFileOpened(CacheFileHandle 
         // memory-only mode.
         NS_WARNING("Forcing memory-only entry since CacheFileIOManager doesn't "
                    "have mCacheDirectory.");
         LOG(("CacheFile::OnFileOpened() - CacheFileIOManager doesn't have "
              "mCacheDirectory, initializing entry as memory-only. [this=%p]",
              this));
 
         mMemoryOnly = true;
+        MOZ_ASSERT(!mKeyIsHash);
         mMetadata = new CacheFileMetadata(mKey);
         mReady = true;
         mDataSize = mMetadata->Offset();
 
         isNew = true;
         retval = NS_OK;
       }
       else {
@@ -513,17 +525,17 @@ CacheFile::OnFileOpened(CacheFileHandle 
     listener->OnFileReady(retval, isNew);
     return NS_OK;
   }
 
   MOZ_ASSERT(NS_SUCCEEDED(aResult));
   MOZ_ASSERT(!mMetadata);
   MOZ_ASSERT(mListener);
 
-  mMetadata = new CacheFileMetadata(mHandle, mKey);
+  mMetadata = new CacheFileMetadata(mHandle, mKey, mKeyIsHash);
 
   rv = mMetadata->ReadMetadata(this);
   if (NS_FAILED(rv)) {
     mListener.swap(listener);
     listener->OnFileReady(rv, false);
   }
 
   return NS_OK;
@@ -548,16 +560,23 @@ nsresult
 CacheFile::OnMetadataRead(nsresult aResult)
 {
   MOZ_ASSERT(mListener);
 
   LOG(("CacheFile::OnMetadataRead() [this=%p, rv=0x%08x]", this, aResult));
 
   bool isNew = false;
   if (NS_SUCCEEDED(aResult)) {
+    MOZ_ASSERT(!mMetadata->KeyIsHash());
+
+    if (mKeyIsHash) {
+      mMetadata->GetKey(mKey);
+      mKeyIsHash = false;
+    }
+
     mReady = true;
     mDataSize = mMetadata->Offset();
     if (mDataSize == 0 && mMetadata->ElementsSize() == 0) {
       isNew = true;
       mMetadata->MarkDirty();
     }
 
     InitIndexEntry();
@@ -731,20 +750,16 @@ CacheFile::Doom(CacheFileListener *aCall
   LOG(("CacheFile::Doom() [this=%p, listener=%p]", this, aCallback));
 
   nsresult rv = NS_OK;
 
   if (mMemoryOnly) {
     return NS_ERROR_FILE_NOT_FOUND;
   }
 
-  if (mHandle && mHandle->IsDoomed()) {
-    return NS_ERROR_FILE_NOT_FOUND;
-  }
-
   nsCOMPtr<CacheFileIOListener> listener;
   if (aCallback || !mHandle) {
     listener = new DoomFileHelper(aCallback);
   }
   if (mHandle) {
     rv = CacheFileIOManager::DoomFile(mHandle, listener);
   } else if (mOpeningFile) {
     mDoomAfterOpenListener = listener;
@@ -1346,27 +1361,16 @@ CacheFile::DataSize(int64_t* aSize)
   if (mOutput)
     return false;
 
   *aSize = mDataSize;
   return true;
 }
 
 bool
-CacheFile::IsDoomed()
-{
-  CacheFileAutoLock lock(this);
-
-  if (!mHandle)
-    return false;
-
-  return mHandle->IsDoomed();
-}
-
-bool
 CacheFile::IsDirty()
 {
   return mDataIsDirty || mMetadata->IsDirty();
 }
 
 void
 CacheFile::WriteMetadataIfNeeded()
 {
--- a/netwerk/cache2/CacheFile.h
+++ b/netwerk/cache2/CacheFile.h
@@ -51,16 +51,17 @@ public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   CacheFile();
 
   nsresult Init(const nsACString &aKey,
                 bool aCreateNew,
                 bool aMemoryOnly,
                 bool aPriority,
+                bool aKeyIsHash,
                 CacheFileListener *aCallback);
 
   NS_IMETHOD OnChunkRead(nsresult aResult, CacheFileChunk *aChunk);
   NS_IMETHOD OnChunkWritten(nsresult aResult, CacheFileChunk *aChunk);
   NS_IMETHOD OnChunkAvailable(nsresult aResult, uint32_t aChunkIdx,
                               CacheFileChunk *aChunk);
   NS_IMETHOD OnChunkUpdated(CacheFileChunk *aChunk);
 
@@ -92,17 +93,16 @@ public:
   nsresult GetLastModified(uint32_t *_retval);
   nsresult SetFrecency(uint32_t aFrecency);
   nsresult GetFrecency(uint32_t *_retval);
   nsresult GetLastFetched(uint32_t *_retval);
   nsresult GetFetchCount(uint32_t *_retval);
 
   bool DataSize(int64_t* aSize);
   void Key(nsACString& aKey) { aKey = mKey; }
-  bool IsDoomed();
 
 private:
   friend class CacheFileIOManager;
   friend class CacheFileChunk;
   friend class CacheFileInputStream;
   friend class CacheFileOutputStream;
   friend class CacheFileAutoLock;
   friend class MetadataWriteTimer;
@@ -160,16 +160,17 @@ private:
 
   mozilla::Mutex mLock;
   bool           mOpeningFile;
   bool           mReady;
   bool           mMemoryOnly;
   bool           mDataAccessed;
   bool           mDataIsDirty;
   bool           mWritingMetadata;
+  bool           mKeyIsHash;
   nsresult       mStatus;
   int64_t        mDataSize;
   nsCString      mKey;
 
   nsRefPtr<CacheFileHandle>    mHandle;
   nsRefPtr<CacheFileMetadata>  mMetadata;
   nsCOMPtr<CacheFileListener>  mListener;
   nsCOMPtr<CacheFileIOListener>   mDoomAfterOpenListener;
--- a/netwerk/cache2/CacheFileIOManager.cpp
+++ b/netwerk/cache2/CacheFileIOManager.cpp
@@ -4,20 +4,18 @@
 
 #include "CacheLog.h"
 #include "CacheFileIOManager.h"
 
 #include "../cache/nsCacheUtils.h"
 #include "CacheHashUtils.h"
 #include "CacheStorageService.h"
 #include "CacheIndex.h"
-#include "CacheFileUtils.h"
 #include "nsThreadUtils.h"
 #include "CacheFile.h"
-#include "CacheObserver.h"
 #include "nsIFile.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/DebugOnly.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "private/pprio.h"
 #include "mozilla/VisualEventTracer.h"
 
@@ -33,17 +31,16 @@
 #endif
 
 
 namespace mozilla {
 namespace net {
 
 #define kOpenHandlesLimit   64
 #define kMetadataWriteDelay 5000
-#define kEvictionLoopLimit  40       // in milliseconds
 
 bool
 CacheFileHandle::DispatchRelease()
 {
   if (CacheFileIOManager::IsOnIOThreadOrCeased())
     return false;
 
   nsCOMPtr<nsIEventTarget> ioTarget = CacheFileIOManager::IOTarget();
@@ -478,17 +475,42 @@ public:
     MOZ_COUNT_DTOR(OpenFileEvent);
   }
 
   NS_IMETHOD Run()
   {
     if (mTarget) {
       mRV = NS_OK;
 
-      if (!(mFlags & CacheFileIOManager::SPECIAL_FILE)) {
+      if (mFlags & CacheFileIOManager::SPECIAL_FILE) {
+      }
+      else if (mFlags & CacheFileIOManager::NOHASH) {
+        nsACString::const_char_iterator begin, end;
+        begin = mKey.BeginReading();
+        end = mKey.EndReading();
+        uint32_t i = 0;
+        while (begin != end && i < (SHA1Sum::HashSize << 1)) {
+          if (!(i & 1))
+            mHash[i >> 1] = 0;
+          uint8_t shift = (i & 1) ? 0 : 4;
+          if (*begin >= '0' && *begin <= '9')
+            mHash[i >> 1] |= (*begin - '0') << shift;
+          else if (*begin >= 'A' && *begin <= 'F')
+            mHash[i >> 1] |= (*begin - 'A' + 10) << shift;
+          else
+            break;
+
+          ++i;
+          ++begin;
+        }
+
+        if (i != (SHA1Sum::HashSize << 1) || begin != end)
+          mRV = NS_ERROR_INVALID_ARG;
+      }
+      else {
         SHA1Sum sum;
         sum.update(mKey.BeginReading(), mKey.Length());
         sum.finish(mHash);
       }
 
       MOZ_EVENT_TRACER_EXEC(static_cast<nsIRunnable*>(this),
                             "net::cache::open-background");
       if (NS_SUCCEEDED(mRV)) {
@@ -1016,17 +1038,16 @@ public:
 
 CacheFileIOManager * CacheFileIOManager::gInstance = nullptr;
 
 NS_IMPL_ISUPPORTS1(CacheFileIOManager, nsITimerCallback)
 
 CacheFileIOManager::CacheFileIOManager()
   : mShuttingDown(false)
   , mTreeCreated(false)
-  , mOverLimitEvicting(false)
 {
   LOG(("CacheFileIOManager::CacheFileIOManager [this=%p]", this));
   MOZ_COUNT_CTOR(CacheFileIOManager);
   MOZ_ASSERT(!gInstance, "multiple CacheFileIOManager instances!");
 }
 
 CacheFileIOManager::~CacheFileIOManager()
 {
@@ -1755,17 +1776,16 @@ CacheFileIOManager::WriteInternal(CacheF
   int32_t bytesWritten = PR_Write(aHandle->mFD, aBuf, aCount);
 
   if (bytesWritten != -1 && aHandle->mFileSize < aOffset+bytesWritten) {
     aHandle->mFileSize = aOffset+bytesWritten;
 
     if (!aHandle->IsDoomed() && !aHandle->IsSpecialFile()) {
       uint32_t size = aHandle->FileSizeInK();
       CacheIndex::UpdateEntry(aHandle->Hash(), nullptr, nullptr, &size);
-      EvictIfOverLimitInternal();
     }
   }
 
   if (bytesWritten != aCount)
     return NS_ERROR_FAILURE;
 
   // Write was successful and this write validates the entry (i.e. metadata)
   if (aValidate)
@@ -1836,30 +1856,16 @@ CacheFileIOManager::DoomFileInternal(Cac
       aHandle->mFile.swap(file);
     }
   }
 
   if (!aHandle->IsSpecialFile())
     CacheIndex::RemoveEntry(aHandle->Hash());
 
   aHandle->mIsDoomed = true;
-
-  if (!aHandle->IsSpecialFile()) {
-    nsRefPtr<CacheStorageService> storageService = CacheStorageService::Self();
-    if (storageService) {
-      nsAutoCString url;
-      nsCOMPtr<nsILoadContextInfo> info;
-      rv = CacheFileUtils::ParseKey(aHandle->Key(), getter_AddRefs(info), &url);
-      MOZ_ASSERT(NS_SUCCEEDED(rv));
-      if (NS_SUCCEEDED(rv)) {
-        storageService->CacheFileDoomed(info, url);
-      }
-    }
-  }
-
   return NS_OK;
 }
 
 nsresult
 CacheFileIOManager::DoomFileByKey(const nsACString &aKey,
                                   CacheFileIOListener *aCallback)
 {
   LOG(("CacheFileIOManager::DoomFileByKey() [key=%s, listener=%p]",
@@ -2148,191 +2154,16 @@ CacheFileIOManager::RenameFileInternal(C
   rv = aHandle->mFile->MoveToNative(nullptr, aNewName);
   NS_ENSURE_SUCCESS(rv, rv);
 
   aHandle->mKey = aNewName;
   return NS_OK;
 }
 
 nsresult
-CacheFileIOManager::EvictIfOverLimit()
-{
-  LOG(("CacheFileIOManager::EvictIfOverLimit()"));
-
-  nsresult rv;
-  nsRefPtr<CacheFileIOManager> ioMan = gInstance;
-
-  if (!ioMan)
-    return NS_ERROR_NOT_INITIALIZED;
-
-  nsCOMPtr<nsIRunnable> ev;
-  ev = NS_NewRunnableMethod(ioMan,
-                            &CacheFileIOManager::EvictIfOverLimitInternal);
-
-  rv = ioMan->mIOThread->Dispatch(ev, CacheIOThread::EVICT);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
-}
-
-nsresult
-CacheFileIOManager::EvictIfOverLimitInternal()
-{
-  LOG(("CacheFileIOManager::EvictIfOverLimitInternal()"));
-
-  nsresult rv;
-
-  MOZ_ASSERT(mIOThread->IsCurrentThread());
-
-  if (mShuttingDown)
-    return NS_ERROR_NOT_INITIALIZED;
-
-  if (mOverLimitEvicting) {
-    LOG(("CacheFileIOManager::EvictIfOverLimitInternal() - Eviction already "
-         "running."));
-    return NS_OK;
-  }
-
-  uint32_t cacheUsage;
-  rv = CacheIndex::GetCacheSize(&cacheUsage);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  uint32_t cacheLimit = CacheObserver::DiskCacheCapacity() >> 10;
-  if (cacheUsage <= cacheLimit) {
-    LOG(("CacheFileIOManager::EvictIfOverLimitInternal() - Cache size under "
-         "limit. [cacheSize=%u, limit=%u]", cacheUsage, cacheLimit));
-    return NS_OK;
-  }
-
-  LOG(("CacheFileIOManager::EvictIfOverLimitInternal() - Cache size exceeded "
-       "limit. Starting overlimit eviction. [cacheSize=%u, limit=%u]",
-       cacheUsage, cacheLimit));
-
-  nsCOMPtr<nsIRunnable> ev;
-  ev = NS_NewRunnableMethod(this,
-                            &CacheFileIOManager::OverLimitEvictionInternal);
-
-  rv = mIOThread->Dispatch(ev, CacheIOThread::EVICT);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  mOverLimitEvicting = true;
-  return NS_OK;
-}
-
-nsresult
-CacheFileIOManager::OverLimitEvictionInternal()
-{
-  LOG(("CacheFileIOManager::OverLimitEvictionInternal()"));
-
-  nsresult rv;
-
-  // mOverLimitEvicting is accessed only on IO thread, so we can set it to false
-  // here and set ti to true again once we dispatch another event that will
-  // continue with the eviction. The reason why we do so is that we can fail
-  // early anywhere in this method and the variable will contain a correct
-  // value. Otherwise we would need to set it to false on every failing place.
-  mOverLimitEvicting = false;
-
-  if (mShuttingDown)
-    return NS_ERROR_NOT_INITIALIZED;
-
-  TimeStamp start;
-
-  while (true) {
-    uint32_t cacheUsage;
-    rv = CacheIndex::GetCacheSize(&cacheUsage);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    uint32_t cacheLimit = CacheObserver::DiskCacheCapacity() >> 10;
-    if (cacheUsage <= cacheLimit) {
-      LOG(("CacheFileIOManager::OverLimitEvictionInternal() - Cache size under "
-           "limit. [cacheSize=%u, limit=%u]", cacheUsage, cacheLimit));
-      return NS_OK;
-    }
-
-    LOG(("CacheFileIOManager::OverLimitEvictionInternal() - Cache size over "
-         "limit. [cacheSize=%u, limit=%u]", cacheUsage, cacheLimit));
-
-    if (start.IsNull()) {
-      start = TimeStamp::NowLoRes();
-    } else {
-      TimeDuration elapsed = TimeStamp::NowLoRes() - start;
-      if (elapsed.ToMilliseconds() >= kEvictionLoopLimit) {
-        LOG(("CacheFileIOManager::OverLimitEvictionInternal() - Breaking loop "
-             "after %u ms.", static_cast<uint32_t>(elapsed.ToMilliseconds())));
-        break;
-      }
-    }
-
-    SHA1Sum::Hash hash;
-    uint32_t cnt;
-    static uint32_t consecutiveFailures = 0;
-    rv = CacheIndex::GetEntryForEviction(&hash, &cnt);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    rv = DoomFileByKeyInternal(&hash);
-    if (NS_SUCCEEDED(rv)) {
-      consecutiveFailures = 0;
-    }
-    else if (rv == NS_ERROR_NOT_AVAILABLE) {
-      LOG(("CacheFileIOManager::OverLimitEvictionInternal() - "
-           "DoomFileByKeyInternal() failed. [rv=0x%08x]", rv));
-      // TODO index is outdated, start update
-
-      // Make sure index won't return the same entry again
-      CacheIndex::RemoveEntry(&hash);
-      consecutiveFailures = 0;
-    }
-    else {
-      // This shouldn't normally happen, but the eviction must not fail
-      // completely if we ever encounter this problem.
-      NS_WARNING("CacheFileIOManager::OverLimitEvictionInternal() - Unexpected "
-                 "failure of DoomFileByKeyInternal()");
-
-      LOG(("CacheFileIOManager::OverLimitEvictionInternal() - "
-           "DoomFileByKeyInternal() failed. [rv=0x%08x]", rv));
-
-      // Normally, CacheIndex::UpdateEntry() is called only to update newly
-      // created/opened entries which are always fresh and UpdateEntry() expects
-      // and checks this flag. The way we use UpdateEntry() here is a kind of
-      // hack and we must make sure the flag is set by calling
-      // EnsureEntryExists().
-      rv = CacheIndex::EnsureEntryExists(&hash);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      // Move the entry at the end of both lists to make sure we won't end up
-      // failing on one entry forever.
-      uint32_t frecency = 0;
-      uint32_t expTime = nsICacheEntry::NO_EXPIRATION_TIME;
-      rv = CacheIndex::UpdateEntry(&hash, &frecency, &expTime, nullptr);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      consecutiveFailures++;
-      if (consecutiveFailures >= cnt) {
-        // This doesn't necessarily mean that we've tried to doom every entry
-        // but we've reached a sane number of tries. It is likely that another
-        // eviction will start soon. And as said earlier, this normally doesn't
-        // happen at all.
-        return NS_OK;
-      }
-    }
-  }
-
-  nsCOMPtr<nsIRunnable> ev;
-  ev = NS_NewRunnableMethod(this,
-                            &CacheFileIOManager::OverLimitEvictionInternal);
-
-  rv = mIOThread->Dispatch(ev, CacheIOThread::EVICT);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  mOverLimitEvicting = true;
-  return NS_OK;
-}
-
-nsresult
 CacheFileIOManager::InitIndexEntry(CacheFileHandle *aHandle,
                                    uint32_t         aAppId,
                                    bool             aAnonymous,
                                    bool             aInBrowser)
 {
   LOG(("CacheFileIOManager::InitIndexEntry() [handle=%p, appId=%u, anonymous=%d"
        ", inBrowser=%d]", aHandle, aAppId, aAnonymous, aInBrowser));
 
--- a/netwerk/cache2/CacheFileIOManager.h
+++ b/netwerk/cache2/CacheFileIOManager.h
@@ -190,17 +190,18 @@ public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSITIMERCALLBACK
 
   enum {
     OPEN         = 0U,
     CREATE       = 1U,
     CREATE_NEW   = 2U,
     PRIORITY     = 4U,
-    SPECIAL_FILE = 8U
+    NOHASH       = 8U,
+    SPECIAL_FILE = 16U
   };
 
   CacheFileIOManager();
 
   static nsresult Init();
   static nsresult Shutdown();
   static nsresult OnProfile();
   static already_AddRefed<nsIEventTarget> IOTarget();
@@ -233,18 +234,16 @@ public:
                                 CacheFileIOListener *aCallback);
   static nsresult ReleaseNSPRHandle(CacheFileHandle *aHandle);
   static nsresult TruncateSeekSetEOF(CacheFileHandle *aHandle,
                                      int64_t aTruncatePos, int64_t aEOFPos,
                                      CacheFileIOListener *aCallback);
   static nsresult RenameFile(CacheFileHandle *aHandle,
                              const nsACString &aNewName,
                              CacheFileIOListener *aCallback);
-  static nsresult EvictIfOverLimit();
-
   static nsresult InitIndexEntry(CacheFileHandle *aHandle,
                                  uint32_t         aAppId,
                                  bool             aAnonymous,
                                  bool             aInBrowser);
   static nsresult UpdateIndexEntry(CacheFileHandle *aHandle,
                                    const uint32_t  *aFrecency,
                                    const uint32_t  *aExpirationTime);
 
@@ -295,18 +294,16 @@ private:
                          const char *aBuf, int32_t aCount, bool aValidate);
   nsresult DoomFileInternal(CacheFileHandle *aHandle);
   nsresult DoomFileByKeyInternal(const SHA1Sum::Hash *aHash);
   nsresult ReleaseNSPRHandleInternal(CacheFileHandle *aHandle);
   nsresult TruncateSeekSetEOFInternal(CacheFileHandle *aHandle,
                                       int64_t aTruncatePos, int64_t aEOFPos);
   nsresult RenameFileInternal(CacheFileHandle *aHandle,
                               const nsACString &aNewName);
-  nsresult EvictIfOverLimitInternal();
-  nsresult OverLimitEvictionInternal();
 
   nsresult CreateFile(CacheFileHandle *aHandle);
   static void HashToStr(const SHA1Sum::Hash *aHash, nsACString &_retval);
   static nsresult StrToHash(const nsACString &aHash, SHA1Sum::Hash *_retval);
   nsresult GetFile(const SHA1Sum::Hash *aHash, nsIFile **_retval);
   nsresult GetSpecialFile(const nsACString &aKey, nsIFile **_retval);
   nsresult GetDoomedFile(nsIFile **_retval);
   nsresult CheckAndCreateDir(nsIFile *aFile, const char *aDir);
@@ -323,15 +320,14 @@ private:
   nsRefPtr<CacheIOThread>              mIOThread;
   nsCOMPtr<nsIFile>                    mCacheDirectory;
   bool                                 mTreeCreated;
   CacheFileHandles                     mHandles;
   nsTArray<CacheFileHandle *>          mHandlesByLastUsed;
   nsTArray<nsRefPtr<CacheFileHandle> > mSpecialHandles;
   nsTArray<nsRefPtr<CacheFile> >       mScheduledMetadataWrites;
   nsCOMPtr<nsITimer>                   mMetadataWritesTimer;
-  bool                                 mOverLimitEvicting;
 };
 
 } // net
 } // mozilla
 
 #endif
--- a/netwerk/cache2/CacheFileMetadata.cpp
+++ b/netwerk/cache2/CacheFileMetadata.cpp
@@ -4,35 +4,35 @@
 
 #include "CacheLog.h"
 #include "CacheFileMetadata.h"
 
 #include "CacheFileIOManager.h"
 #include "nsICacheEntry.h"
 #include "CacheHashUtils.h"
 #include "CacheFileChunk.h"
-#include "CacheFileUtils.h"
 #include "nsILoadContextInfo.h"
 #include "../cache/nsCacheUtils.h"
 #include "nsIFile.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/DebugOnly.h"
 #include "prnetdb.h"
 
 
 namespace mozilla {
 namespace net {
 
 #define kMinMetadataRead 1024  // TODO find optimal value from telemetry
 #define kAlignSize       4096
 
 NS_IMPL_ISUPPORTS1(CacheFileMetadata, CacheFileIOListener)
 
-CacheFileMetadata::CacheFileMetadata(CacheFileHandle *aHandle, const nsACString &aKey)
+CacheFileMetadata::CacheFileMetadata(CacheFileHandle *aHandle, const nsACString &aKey, bool aKeyIsHash)
   : mHandle(aHandle)
+  , mKeyIsHash(aKeyIsHash)
   , mHashArray(nullptr)
   , mHashArraySize(0)
   , mHashCount(0)
   , mOffset(-1)
   , mBuf(nullptr)
   , mBufSize(0)
   , mWriteBuf(nullptr)
   , mElementsSize(0)
@@ -43,20 +43,21 @@ CacheFileMetadata::CacheFileMetadata(Cac
 {
   LOG(("CacheFileMetadata::CacheFileMetadata() [this=%p, handle=%p, key=%s]",
        this, aHandle, PromiseFlatCString(aKey).get()));
 
   MOZ_COUNT_CTOR(CacheFileMetadata);
   memset(&mMetaHdr, 0, sizeof(CacheFileMetadataHeader));
   mMetaHdr.mExpirationTime = nsICacheEntry::NO_EXPIRATION_TIME;
   mKey = aKey;
-
-  DebugOnly<nsresult> rv;
-  rv = ParseKey(aKey);
-  MOZ_ASSERT(NS_SUCCEEDED(rv));
+  if (!aKeyIsHash) {
+    DebugOnly<nsresult> rv;
+    rv = ParseKey(aKey);
+    MOZ_ASSERT(NS_SUCCEEDED(rv));
+  }
 }
 
 CacheFileMetadata::~CacheFileMetadata()
 {
   LOG(("CacheFileMetadata::~CacheFileMetadata() [this=%p]", this));
 
   MOZ_COUNT_DTOR(CacheFileMetadata);
   MOZ_ASSERT(!mListener);
@@ -73,16 +74,17 @@ CacheFileMetadata::~CacheFileMetadata()
     mBufSize = 0;
   }
 
   DoMemoryReport(MemoryUsage());
 }
 
 CacheFileMetadata::CacheFileMetadata(const nsACString &aKey)
   : mHandle(nullptr)
+  , mKeyIsHash(false)
   , mHashArray(nullptr)
   , mHashArraySize(0)
   , mHashCount(0)
   , mOffset(0)
   , mBuf(nullptr)
   , mBufSize(0)
   , mWriteBuf(nullptr)
   , mElementsSize(0)
@@ -103,16 +105,17 @@ CacheFileMetadata::CacheFileMetadata(con
 
   DebugOnly<nsresult> rv;
   rv = ParseKey(aKey);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
 }
 
 CacheFileMetadata::CacheFileMetadata()
   : mHandle(nullptr)
+  , mKeyIsHash(false)
   , mHashArray(nullptr)
   , mHashArraySize(0)
   , mHashCount(0)
   , mOffset(0)
   , mBuf(nullptr)
   , mBufSize(0)
   , mWriteBuf(nullptr)
   , mElementsSize(0)
@@ -139,42 +142,65 @@ CacheFileMetadata::SetHandle(CacheFileHa
 
 nsresult
 CacheFileMetadata::GetKey(nsACString &_retval)
 {
   _retval = mKey;
   return NS_OK;
 }
 
+bool
+CacheFileMetadata::KeyIsHash()
+{
+  return mKeyIsHash;
+}
+
 nsresult
 CacheFileMetadata::ReadMetadata(CacheFileMetadataListener *aListener)
 {
   LOG(("CacheFileMetadata::ReadMetadata() [this=%p, listener=%p]", this, aListener));
 
   MOZ_ASSERT(!mListener);
   MOZ_ASSERT(!mHashArray);
   MOZ_ASSERT(!mBuf);
   MOZ_ASSERT(!mWriteBuf);
 
   nsresult rv;
 
   int64_t size = mHandle->FileSize();
   MOZ_ASSERT(size != -1);
 
   if (size == 0) {
+    if (mKeyIsHash) {
+      LOG(("CacheFileMetadata::ReadMetadata() - Filesize == 0, cannot create "
+           "empty metadata since key is a hash. [this=%p]", this));
+
+      CacheFileIOManager::DoomFile(mHandle, nullptr);
+      return NS_ERROR_NOT_AVAILABLE;
+    }
+
     // this is a new entry
     LOG(("CacheFileMetadata::ReadMetadata() - Filesize == 0, creating empty "
          "metadata. [this=%p]", this));
 
     InitEmptyMetadata();
     aListener->OnMetadataRead(NS_OK);
     return NS_OK;
   }
 
   if (size < int64_t(sizeof(CacheFileMetadataHeader) + 2*sizeof(uint32_t))) {
+    if (mKeyIsHash) {
+      LOG(("CacheFileMetadata::ReadMetadata() - File is corrupted, cannot "
+           "create empty metadata since key is a hash. [this=%p, "
+           "filesize=%lld]", this, size));
+
+      CacheFileIOManager::DoomFile(mHandle, nullptr);
+      return NS_ERROR_FILE_CORRUPTED;
+    }
+
     // there must be at least checksum, header and offset
     LOG(("CacheFileMetadata::ReadMetadata() - File is corrupted, creating "
          "empty metadata. [this=%p, filesize=%lld]", this, size));
 
     InitEmptyMetadata();
     aListener->OnMetadataRead(NS_OK);
     return NS_OK;
   }
@@ -191,16 +217,25 @@ CacheFileMetadata::ReadMetadata(CacheFil
   DoMemoryReport(MemoryUsage());
 
   LOG(("CacheFileMetadata::ReadMetadata() - Reading metadata from disk, trying "
        "offset=%lld, filesize=%lld [this=%p]", offset, size, this));
 
   mListener = aListener;
   rv = CacheFileIOManager::Read(mHandle, offset, mBuf, mBufSize, this);
   if (NS_FAILED(rv)) {
+    if (mKeyIsHash) {
+      LOG(("CacheFileMetadata::ReadMetadata() - CacheFileIOManager::Read() "
+           "failed synchronously, cannot create empty metadata since key is "
+           "a hash. [this=%p, rv=0x%08x]", this, rv));
+
+      CacheFileIOManager::DoomFile(mHandle, nullptr);
+      return rv;
+    }
+
     LOG(("CacheFileMetadata::ReadMetadata() - CacheFileIOManager::Read() failed"
          " synchronously, creating empty metadata. [this=%p, rv=0x%08x]",
          this, rv));
 
     mListener = nullptr;
     InitEmptyMetadata();
     aListener->OnMetadataRead(NS_OK);
     return NS_OK;
@@ -213,16 +248,17 @@ nsresult
 CacheFileMetadata::WriteMetadata(uint32_t aOffset,
                                  CacheFileMetadataListener *aListener)
 {
   LOG(("CacheFileMetadata::WriteMetadata() [this=%p, offset=%d, listener=%p]",
        this, aOffset, aListener));
 
   MOZ_ASSERT(!mListener);
   MOZ_ASSERT(!mWriteBuf);
+  MOZ_ASSERT(!mKeyIsHash);
 
   nsresult rv;
 
   mIsDirty = false;
 
   mWriteBuf = static_cast<char *>(moz_xmalloc(sizeof(uint32_t) +
                 mHashCount * sizeof(CacheHash::Hash16_t) +
                 sizeof(CacheFileMetadataHeader) + mKey.Length() + 1 +
@@ -336,17 +372,19 @@ CacheFileMetadata::SyncReadMetadata(nsIF
   }
 
   bytesRead = PR_Read(fd, mBuf, mBufSize);
   PR_Close(fd);
   if (bytesRead != static_cast<int32_t>(mBufSize)) {
     return NS_ERROR_FAILURE;
   }
 
-  rv = ParseMetadata(metaOffset, 0, false);
+  mKeyIsHash = true;
+
+  rv = ParseMetadata(metaOffset, 0);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 const char *
 CacheFileMetadata::GetElement(const char *aKey)
 {
@@ -574,41 +612,61 @@ CacheFileMetadata::OnDataRead(CacheFileH
        this, aHandle, aResult));
 
   MOZ_ASSERT(mListener);
 
   nsresult rv, retval;
   nsCOMPtr<CacheFileMetadataListener> listener;
 
   if (NS_FAILED(aResult)) {
-    LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() failed"
-         ", creating empty metadata. [this=%p, rv=0x%08x]", this, aResult));
+    if (mKeyIsHash) {
+      LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() "
+           "failed, cannot create empty metadata since key is a hash. [this=%p,"
+           " rv=0x%08x]", this, aResult));
 
-    InitEmptyMetadata();
-    retval = NS_OK;
+      CacheFileIOManager::DoomFile(mHandle, nullptr);
+      retval = aResult;
+    }
+    else {
+      LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() failed"
+           ", creating empty metadata. [this=%p, rv=0x%08x]", this, aResult));
+
+      InitEmptyMetadata();
+      retval = NS_OK;
+    }
 
     mListener.swap(listener);
     listener->OnMetadataRead(retval);
     return NS_OK;
   }
 
   // check whether we have read all necessary data
   uint32_t realOffset = PR_ntohl(*(reinterpret_cast<uint32_t *>(
                                  mBuf + mBufSize - sizeof(uint32_t))));
 
   int64_t size = mHandle->FileSize();
   MOZ_ASSERT(size != -1);
 
   if (realOffset >= size) {
-    LOG(("CacheFileMetadata::OnDataRead() - Invalid realOffset, creating "
-         "empty metadata. [this=%p, realOffset=%d, size=%lld]", this,
-         realOffset, size));
+    if (mKeyIsHash) {
+      LOG(("CacheFileMetadata::OnDataRead() - Invalid realOffset, cannot create"
+           "empty metadata since key is a hash. [this=%p, realOffset=%d, "
+           "size=%lld]", this, realOffset, size));
 
-    InitEmptyMetadata();
-    retval = NS_OK;
+      CacheFileIOManager::DoomFile(mHandle, nullptr);
+      retval = NS_ERROR_FILE_CORRUPTED;
+    }
+    else {
+      LOG(("CacheFileMetadata::OnDataRead() - Invalid realOffset, creating "
+           "empty metadata. [this=%p, realOffset=%d, size=%lld]", this,
+           realOffset, size));
+
+      InitEmptyMetadata();
+      retval = NS_OK;
+    }
 
     mListener.swap(listener);
     listener->OnMetadataRead(retval);
     return NS_OK;
   }
 
   uint32_t usedOffset = size - mBufSize;
 
@@ -621,39 +679,58 @@ CacheFileMetadata::OnDataRead(CacheFileH
 
     DoMemoryReport(MemoryUsage());
 
     LOG(("CacheFileMetadata::OnDataRead() - We need to read %d more bytes to "
          "have full metadata. [this=%p]", missing, this));
 
     rv = CacheFileIOManager::Read(mHandle, realOffset, mBuf, missing, this);
     if (NS_FAILED(rv)) {
-      LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() "
-           "failed synchronously, creating empty metadata. [this=%p, "
-           "rv=0x%08x]", this, rv));
+      if (mKeyIsHash) {
+        LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() "
+             "failed synchronously, cannot create empty metadata since key is "
+             "a hash. [this=%p, rv=0x%08x]", this, rv));
 
-      InitEmptyMetadata();
-      retval = NS_OK;
+        CacheFileIOManager::DoomFile(mHandle, nullptr);
+        retval = rv;
+      }
+      else {
+        LOG(("CacheFileMetadata::OnDataRead() - CacheFileIOManager::Read() "
+             "failed synchronously, creating empty metadata. [this=%p, "
+             "rv=0x%08x]", this, rv));
+
+        InitEmptyMetadata();
+        retval = NS_OK;
+      }
 
       mListener.swap(listener);
       listener->OnMetadataRead(retval);
       return NS_OK;
     }
 
     return NS_OK;
   }
 
   // We have all data according to offset information at the end of the entry.
   // Try to parse it.
-  rv = ParseMetadata(realOffset, realOffset - usedOffset, true);
+  rv = ParseMetadata(realOffset, realOffset - usedOffset);
   if (NS_FAILED(rv)) {
-    LOG(("CacheFileMetadata::OnDataRead() - Error parsing metadata, creating "
-         "empty metadata. [this=%p]", this));
-    InitEmptyMetadata();
-    retval = NS_OK;
+    if (mKeyIsHash) {
+      LOG(("CacheFileMetadata::OnDataRead() - Error parsing metadata, cannot "
+           "create empty metadata since key is a hash. [this=%p]", this));
+
+      CacheFileIOManager::DoomFile(mHandle, nullptr);
+      retval = rv;
+    }
+    else {
+      LOG(("CacheFileMetadata::OnDataRead() - Error parsing metadata, creating "
+           "empty metadata. [this=%p]", this));
+      InitEmptyMetadata();
+      retval = NS_OK;
+    }
   }
   else {
     retval = NS_OK;
   }
 
   mListener.swap(listener);
   listener->OnMetadataRead(retval);
 
@@ -693,21 +770,20 @@ CacheFileMetadata::InitEmptyMetadata()
   mMetaHdr.mFetchCount = 1;
   mMetaHdr.mExpirationTime = nsICacheEntry::NO_EXPIRATION_TIME;
   mMetaHdr.mKeySize = mKey.Length();
 
   DoMemoryReport(MemoryUsage());
 }
 
 nsresult
-CacheFileMetadata::ParseMetadata(uint32_t aMetaOffset, uint32_t aBufOffset,
-                                 bool aHaveKey)
+CacheFileMetadata::ParseMetadata(uint32_t aMetaOffset, uint32_t aBufOffset)
 {
   LOG(("CacheFileMetadata::ParseMetadata() [this=%p, metaOffset=%d, "
-       "bufOffset=%d, haveKey=%u]", this, aMetaOffset, aBufOffset, aHaveKey));
+       "bufOffset=%d]", this, aMetaOffset, aBufOffset));
 
   nsresult rv;
 
   uint32_t metaposOffset = mBufSize - sizeof(uint32_t);
   uint32_t hashesOffset = aBufOffset + sizeof(uint32_t);
   uint32_t hashCount = aMetaOffset / kChunkSize;
   if (aMetaOffset % kChunkSize)
     hashCount++;
@@ -737,24 +813,26 @@ CacheFileMetadata::ParseMetadata(uint32_
 
   // check that key ends with \0
   if (mBuf[elementsOffset - 1] != 0) {
     LOG(("CacheFileMetadata::ParseMetadata() - Elements not null terminated. "
          "[this=%p]", this));
     return NS_ERROR_FILE_CORRUPTED;
   }
 
+  nsAutoCString origKey;
+
   uint32_t keySize = reinterpret_cast<CacheFileMetadataHeader *>(
                        mBuf + hdrOffset)->mKeySize;
 
-  if (!aHaveKey) {
-    // get the key form metadata
-    mKey.Assign(mBuf + keyOffset, keySize);
+  if (mKeyIsHash) {
+    // get the original key
+    origKey.Assign(mBuf + keyOffset, keySize);
 
-    rv = ParseKey(mKey);
+    rv = ParseKey(origKey);
     if (NS_FAILED(rv))
       return rv;
   }
   else {
     if (keySize != mKey.Length()) {
       LOG(("CacheFileMetadata::ParseMetadata() - Key collision (1), key=%s "
            "[this=%p]", nsCString(mBuf + keyOffset, keySize).get(), this));
       return NS_ERROR_FILE_CORRUPTED;
@@ -794,16 +872,21 @@ CacheFileMetadata::ParseMetadata(uint32_
   memcpy(&mMetaHdr, mBuf + hdrOffset, sizeof(CacheFileMetadataHeader));
   mMetaHdr.mFetchCount++;
   MarkDirty();
 
   mElementsSize = metaposOffset - elementsOffset;
   memmove(mBuf, mBuf + elementsOffset, mElementsSize);
   mOffset = aMetaOffset;
 
+  if (mKeyIsHash) {
+    mKey = origKey;
+    mKeyIsHash = false;
+  }
+
   // TODO: shrink memory if buffer is too big
 
   DoMemoryReport(MemoryUsage());
 
   return NS_OK;
 }
 
 nsresult
@@ -843,23 +926,59 @@ CacheFileMetadata::EnsureBuffer(uint32_t
   }
 
   DoMemoryReport(MemoryUsage());
 }
 
 nsresult
 CacheFileMetadata::ParseKey(const nsACString &aKey)
 {
-  nsresult rv;
+  if (aKey.Length() < 4) {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (aKey[1] == '-') {
+    mAnonymous = false;
+  }
+  else if (aKey[1] == 'A') {
+    mAnonymous = true;
+  }
+  else {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (aKey[2] != ':') {
+    return NS_ERROR_FAILURE;
+  }
+
+  int32_t appIdEndIdx = aKey.FindChar(':', 3);
+  if (appIdEndIdx == kNotFound) {
+    return NS_ERROR_FAILURE;
+  }
 
-  nsCOMPtr<nsILoadContextInfo> info;
-  rv = CacheFileUtils::ParseKey(aKey, getter_AddRefs(info), nullptr);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (aKey[appIdEndIdx - 1] == 'B') {
+    mInBrowser = true;
+    appIdEndIdx--;
+  } else {
+    mInBrowser = false;
+  }
+
+  if (appIdEndIdx < 3) {
+    return NS_ERROR_FAILURE;
+  }
 
-  mAnonymous =  info->IsAnonymous();
-  mAppId = info->AppId();
-  mInBrowser = info->IsInBrowserElement();
+  if (appIdEndIdx == 3) {
+    mAppId = nsILoadContextInfo::NO_APP_ID;
+  }
+  else {
+    nsAutoCString appIdStr(Substring(aKey, 3, appIdEndIdx - 3));
+    nsresult rv;
+    int64_t appId64 = appIdStr.ToInteger64(&rv);
+    if (NS_FAILED(rv) || appId64 > PR_UINT32_MAX)
+      return NS_ERROR_FAILURE;
+    mAppId = appId64;
+  }
 
   return NS_OK;
 }
 
 } // net
 } // mozilla
--- a/netwerk/cache2/CacheFileMetadata.h
+++ b/netwerk/cache2/CacheFileMetadata.h
@@ -57,23 +57,25 @@ NS_DEFINE_STATIC_IID_ACCESSOR(CacheFileM
 
 class CacheFileMetadata : public CacheFileIOListener
                         , public CacheMemoryConsumer
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   CacheFileMetadata(CacheFileHandle *aHandle,
-                    const nsACString &aKey);
+                    const nsACString &aKey,
+                    bool aKeyIsHash);
   CacheFileMetadata(const nsACString &aKey);
   CacheFileMetadata();
 
   void SetHandle(CacheFileHandle *aHandle);
 
   nsresult GetKey(nsACString &_retval);
+  bool     KeyIsHash();
 
   nsresult ReadMetadata(CacheFileMetadataListener *aListener);
   nsresult WriteMetadata(uint32_t aOffset,
                          CacheFileMetadataListener *aListener);
   nsresult SyncReadMetadata(nsIFile *aFile);
 
   bool     IsAnonymous() { return mAnonymous; }
   bool     IsInBrowser() { return mInBrowser; }
@@ -107,23 +109,24 @@ public:
   NS_IMETHOD OnFileDoomed(CacheFileHandle *aHandle, nsresult aResult);
   NS_IMETHOD OnEOFSet(CacheFileHandle *aHandle, nsresult aResult);
   NS_IMETHOD OnFileRenamed(CacheFileHandle *aHandle, nsresult aResult);
 
 private:
   virtual ~CacheFileMetadata();
 
   void     InitEmptyMetadata();
-  nsresult ParseMetadata(uint32_t aMetaOffset, uint32_t aBufOffset, bool aHaveKey);
+  nsresult ParseMetadata(uint32_t aMetaOffset, uint32_t aBufOffset);
   nsresult CheckElements(const char *aBuf, uint32_t aSize);
   void     EnsureBuffer(uint32_t aSize);
   nsresult ParseKey(const nsACString &aKey);
 
   nsRefPtr<CacheFileHandle>           mHandle;
   nsCString                           mKey;
+  bool                                mKeyIsHash;
   CacheHash::Hash16_t                *mHashArray;
   uint32_t                            mHashArraySize;
   uint32_t                            mHashCount;
   int64_t                             mOffset;
   char                               *mBuf; // used for parsing, then points
                                             // to elements
   uint32_t                            mBufSize;
   char                               *mWriteBuf;
deleted file mode 100644
--- a/netwerk/cache2/CacheFileUtils.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/* 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 "CacheLog.h"
-#include "CacheFileUtils.h"
-#include "LoadContextInfo.h"
-#include "nsCOMPtr.h"
-#include "nsString.h"
-
-
-namespace mozilla {
-namespace net {
-namespace CacheFileUtils {
-
-nsresult ParseKey(const nsACString &aKey,
-                  nsILoadContextInfo **aInfo,
-                  nsACString *aURL)
-{
-  bool isPrivate;
-  bool isAnonymous;
-  bool isInBrowser;
-  uint32_t appId;
-
-  if (aKey.Length() < 4) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (aKey[0] == '-') {
-    isPrivate = false;
-  }
-  else if (aKey[0] == 'P') {
-    isPrivate = true;
-  }
-  else {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (aKey[1] == '-') {
-    isAnonymous = false;
-  }
-  else if (aKey[1] == 'A') {
-    isAnonymous = true;
-  }
-  else {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (aKey[2] != ':') {
-    return NS_ERROR_FAILURE;
-  }
-
-  int32_t appIdEndIdx = aKey.FindChar(':', 3);
-  if (appIdEndIdx == kNotFound) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (aKey[appIdEndIdx - 1] == 'B') {
-    isInBrowser = true;
-    appIdEndIdx--;
-  } else {
-    isInBrowser = false;
-  }
-
-  if (appIdEndIdx < 3) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (appIdEndIdx == 3) {
-    appId = nsILoadContextInfo::NO_APP_ID;
-  }
-  else {
-    nsAutoCString appIdStr(Substring(aKey, 3, appIdEndIdx - 3));
-    nsresult rv;
-    int64_t appId64 = appIdStr.ToInteger64(&rv);
-    if (NS_FAILED(rv) || appId64 > PR_UINT32_MAX)
-      return NS_ERROR_FAILURE;
-    appId = appId64;
-  }
-
-  if (aInfo) {
-    nsCOMPtr<nsILoadContextInfo> info;
-    info = GetLoadContextInfo(isPrivate, appId, isInBrowser, isAnonymous);
-    info.forget(aInfo);
-  }
-
-  if (aURL) {
-    *aURL = Substring(aKey, appIdEndIdx + 1);
-  }
-
-  return NS_OK;
-}
-
-void CreateKeyPrefix(nsILoadContextInfo* aInfo, nsACString &_retval)
-{
-  /**
-   * This key is used to salt file hashes.  When form of the key is changed
-   * cache entries will fail to find on disk.
-   */
-  _retval.Assign(aInfo->IsPrivate() ? 'P' : '-');
-  _retval.Append(aInfo->IsAnonymous() ? 'A' : '-');
-  _retval.Append(':');
-  if (aInfo->AppId() != nsILoadContextInfo::NO_APP_ID) {
-    _retval.AppendInt(aInfo->AppId());
-  }
-  if (aInfo->IsInBrowserElement()) {
-    _retval.Append('B');
-  }
-}
-
-
-} // CacheFileUtils
-} // net
-} // mozilla
-
deleted file mode 100644
--- a/netwerk/cache2/CacheFileUtils.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* 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 CacheFileUtils__h__
-#define CacheFileUtils__h__
-
-#include "nsError.h"
-
-class nsILoadContextInfo;
-class nsACString;
-
-namespace mozilla {
-namespace net {
-namespace CacheFileUtils {
-
-nsresult ParseKey(const nsACString &aKey,
-                  nsILoadContextInfo **aInfo,
-                  nsACString *aURL);
-
-void CreateKeyPrefix(nsILoadContextInfo* aInfo, nsACString &_retval);
-
-} // CacheFileUtils
-} // net
-} // mozilla
-
-#endif
--- a/netwerk/cache2/CacheIOThread.h
+++ b/netwerk/cache2/CacheIOThread.h
@@ -29,18 +29,18 @@ public:
   enum ELevel {
     OPEN_PRIORITY,
     READ_PRIORITY,
     OPEN,
     READ,
     WRITE,
     MANAGEMENT,
     CLOSE,
+    EVICT,
     BUILD_OR_UPDATE_INDEX,
-    EVICT,
     LAST_LEVEL
   };
 
   nsresult Init();
   nsresult Dispatch(nsIRunnable* aRunnable, uint32_t aLevel);
   bool IsCurrentThread();
   nsresult Shutdown();
   already_AddRefed<nsIEventTarget> Target();
--- a/netwerk/cache2/CacheIndex.cpp
+++ b/netwerk/cache2/CacheIndex.cpp
@@ -44,32 +44,28 @@ public:
   CacheIndexEntryAutoManage(const SHA1Sum::Hash *aHash, CacheIndex *aIndex)
     : mIndex(aIndex)
     , mOldRecord(nullptr)
     , mOldFrecency(0)
     , mOldExpirationTime(nsICacheEntry::NO_EXPIRATION_TIME)
     , mDoNotSearchInIndex(false)
     , mDoNotSearchInUpdates(false)
   {
-    mIndex->AssertOwnsLock();
-
     mHash = aHash;
     CacheIndexEntry *entry = FindEntry();
     mIndex->mIndexStats.BeforeChange(entry);
     if (entry && entry->IsInitialized() && !entry->IsRemoved()) {
       mOldRecord = entry->mRec;
       mOldFrecency = entry->mRec->mFrecency;
       mOldExpirationTime = entry->mRec->mExpirationTime;
     }
   }
 
   ~CacheIndexEntryAutoManage()
   {
-    mIndex->AssertOwnsLock();
-
     CacheIndexEntry *entry = FindEntry();
     mIndex->mIndexStats.AfterChange(entry);
     if (!entry || !entry->IsInitialized() || entry->IsRemoved()) {
       entry = nullptr;
     }
 
     if (entry && !mOldRecord) {
       mIndex->InsertRecordToFrecencyArray(entry->mRec);
@@ -80,29 +76,21 @@ public:
     } else if (entry && mOldRecord) {
       bool replaceFrecency = false;
       bool replaceExpiration = false;
 
       if (entry->mRec != mOldRecord) {
         // record has a different address, we have to replace it
         replaceFrecency = replaceExpiration = true;
       } else {
-        if (entry->mRec->mFrecency == 0 &&
-            entry->mRec->mExpirationTime == nsICacheEntry::NO_EXPIRATION_TIME) {
-          // This is a special case when we want to make sure that the entry is
-          // placed at the end of the lists even when the values didn't change.
-          replaceFrecency = replaceExpiration = true;
+        if (entry->mRec->mFrecency != mOldFrecency) {
+          replaceFrecency = true;
         }
-        else {
-          if (entry->mRec->mFrecency != mOldFrecency) {
-            replaceFrecency = true;
-          }
-          if (entry->mRec->mExpirationTime != mOldExpirationTime) {
-            replaceExpiration = true;
-          }
+        if (entry->mRec->mExpirationTime != mOldExpirationTime) {
+          replaceExpiration = true;
         }
       }
 
       if (replaceFrecency) {
         mIndex->RemoveRecordFromFrecencyArray(mOldRecord);
         mIndex->InsertRecordToFrecencyArray(entry->mRec);
       }
       if (replaceExpiration) {
@@ -1038,84 +1026,16 @@ CacheIndex::HasEntry(const nsACString &a
       *_retval = EXISTS;
     }
   }
 
   LOG(("CacheIndex::HasEntry() - result is %u", *_retval));
   return NS_OK;
 }
 
-// static
-nsresult
-CacheIndex::GetEntryForEviction(SHA1Sum::Hash *aHash, uint32_t *aCnt)
-{
-  LOG(("CacheIndex::GetEntryForEviction()"));
-
-  nsRefPtr<CacheIndex> index = gInstance;
-
-  if (!index)
-    return NS_ERROR_NOT_INITIALIZED;
-
-  CacheIndexAutoLock lock(index);
-
-  if (!index->IsIndexUsable()) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  MOZ_ASSERT(index->mFrecencyArray.Length() ==
-             index->mExpirationArray.Length());
-
-  if (index->mExpirationArray.Length() == 0)
-    return NS_ERROR_NOT_AVAILABLE;
-
-  uint32_t now = PR_Now() / PR_USEC_PER_SEC;
-  if (index->mExpirationArray[0]->mExpirationTime < now) {
-    memcpy(aHash, &index->mExpirationArray[0]->mHash, sizeof(SHA1Sum::Hash));
-    *aCnt = index->mExpirationArray.Length();
-    LOG(("CacheIndex::GetEntryForEviction() - returning entry from expiration "
-         "array [hash=%08x%08x%08x%08x%08x, cnt=%u, expTime=%u, now=%u, "
-         "frecency=%u]", LOGSHA1(aHash), *aCnt,
-         index->mExpirationArray[0]->mExpirationTime, now,
-         index->mExpirationArray[0]->mFrecency));
-  }
-  else {
-    memcpy(aHash, &index->mFrecencyArray[0]->mHash, sizeof(SHA1Sum::Hash));
-    *aCnt = index->mFrecencyArray.Length();
-    LOG(("CacheIndex::GetEntryForEviction() - returning entry from frecency "
-         "array [hash=%08x%08x%08x%08x%08x, cnt=%u, expTime=%u, now=%u, "
-         "frecency=%u]", LOGSHA1(aHash), *aCnt,
-         index->mExpirationArray[0]->mExpirationTime, now,
-         index->mExpirationArray[0]->mFrecency));
-  }
-
-  return NS_OK;
-}
-
-// static
-nsresult
-CacheIndex::GetCacheSize(uint32_t *_retval)
-{
-  LOG(("CacheIndex::GetCacheSize()"));
-
-  nsRefPtr<CacheIndex> index = gInstance;
-
-  if (!index)
-    return NS_ERROR_NOT_INITIALIZED;
-
-  CacheIndexAutoLock lock(index);
-
-  if (!index->IsIndexUsable()) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  *_retval = index->mIndexStats.Size();
-  LOG(("CacheIndex::GetCacheSize() - returning %u", *_retval));
-  return NS_OK;
-}
-
 bool
 CacheIndex::IsIndexUsable()
 {
   MOZ_ASSERT(mState != INITIAL);
 
   switch (mState) {
     case INITIAL:
     case SHUTDOWN:
@@ -2877,23 +2797,16 @@ CacheIndex::ChangeState(EState aNewState
   // possible transition is to SHUTDOWN state.
   MOZ_ASSERT(!mShuttingDown || mState != READY || aNewState == SHUTDOWN);
 
   // Start updating process when switching to READY state if needed
   if (aNewState == READY && StartUpdatingIndexIfNeeded(true)) {
     return;
   }
 
-  // Try to evict entries over limit everytime we're leaving state READING,
-  // BUILDING or UPDATING, but not during shutdown.
-  if (!mShuttingDown && aNewState != SHUTDOWN &&
-      (mState == READING || mState == BUILDING || mState == UPDATING))  {
-    CacheFileIOManager::EvictIfOverLimit();
-  }
-
   mState = aNewState;
 }
 
 void
 CacheIndex::AllocBuffer()
 {
   switch (mState) {
     case WRITING:
@@ -2930,23 +2843,16 @@ namespace { // anon
 
 class FrecencyComparator
 {
 public:
   bool Equals(CacheIndexRecord* a, CacheIndexRecord* b) const {
     return a->mFrecency == b->mFrecency;
   }
   bool LessThan(CacheIndexRecord* a, CacheIndexRecord* b) const {
-    // Place entries with frecency 0 at the end of the array.
-    if (a->mFrecency == 0) {
-      return false;
-    }
-    if (b->mFrecency == 0) {
-      return true;
-    }
     return a->mFrecency < b->mFrecency;
   }
 };
 
 class ExpirationComparator
 {
 public:
   bool Equals(CacheIndexRecord* a, CacheIndexRecord* b) const {
--- a/netwerk/cache2/CacheIndex.h
+++ b/netwerk/cache2/CacheIndex.h
@@ -343,17 +343,17 @@ public:
   }
 
   uint32_t ActiveEntriesCount() {
     MOZ_ASSERT(!mStateLogged, "CacheIndexStats::ActiveEntriesCount() - state "
                "logged!");
     return mCount - mRemoved - mNotInitialized - mEmpty;
   }
 
-  uint32_t Size() {
+  int64_t Size() {
     MOZ_ASSERT(!mStateLogged, "CacheIndexStats::Size() - state logged!");
     return mSize;
   }
 
   void BeforeChange(CacheIndexEntry *aEntry) {
 #ifdef DEBUG_STATS
     if (!mDisableLogging) {
       LOG(("CacheIndexStats::BeforeChange()"));
@@ -384,17 +384,17 @@ public:
         if (!aEntry->IsInitialized()) {
           MOZ_ASSERT(mNotInitialized);
           mNotInitialized--;
         } else {
           if (aEntry->IsFileEmpty()) {
             MOZ_ASSERT(mEmpty);
             mEmpty--;
           } else {
-            MOZ_ASSERT(mSize >= aEntry->GetFileSize());
+            MOZ_ASSERT(mSize);
             mSize -= aEntry->GetFileSize();
           }
         }
       }
     }
   }
 
   void AfterChange(CacheIndexEntry *aEntry) {
@@ -436,17 +436,17 @@ public:
 
 private:
   uint32_t mCount;
   uint32_t mNotInitialized;
   uint32_t mRemoved;
   uint32_t mDirty;
   uint32_t mFresh;
   uint32_t mEmpty;
-  uint32_t mSize;
+  int64_t  mSize;
 #ifdef DEBUG
   // We completely remove the data about an entry from the stats in
   // BeforeChange() and set this flag to true. The entry is then modified,
   // deleted or created and the data is again put into the stats and this flag
   // set to false. Statistics must not be read during this time since the
   // information is not correct.
   bool     mStateLogged;
 
@@ -507,25 +507,16 @@ public:
     DOES_NOT_EXIST = 1,
     DO_NOT_KNOW    = 2
   };
 
   // Returns status of the entry in index for the given key. It can be called
   // on any thread.
   static nsresult HasEntry(const nsACString &aKey, EntryStatus *_retval);
 
-  // Returns a hash of the least important entry that should be evicted if the
-  // cache size is over limit and also returns a total number of all entries in
-  // the index.
-  static nsresult GetEntryForEviction(SHA1Sum::Hash *aHash, uint32_t *aCnt);
-
-  // Returns cache size in kB.
-  static nsresult GetCacheSize(uint32_t *_retval);
-
-
 private:
   friend class CacheIndexEntryAutoManage;
   friend class CacheIndexAutoLock;
   friend class CacheIndexAutoUnlock;
 
   virtual ~CacheIndex();
 
   NS_IMETHOD OnFileOpened(CacheFileHandle *aHandle, nsresult aResult);
--- a/netwerk/cache2/CacheStorageService.cpp
+++ b/netwerk/cache2/CacheStorageService.cpp
@@ -7,17 +7,16 @@
 #include "CacheFileIOManager.h"
 #include "CacheObserver.h"
 
 #include "nsICacheStorageVisitor.h"
 #include "nsIObserverService.h"
 #include "CacheStorage.h"
 #include "AppCacheStorage.h"
 #include "CacheEntry.h"
-#include "CacheFileUtils.h"
 
 #include "OldWrappers.h"
 #include "nsCacheService.h"
 #include "nsDeleteDir.h"
 
 #include "nsIFile.h"
 #include "nsIURI.h"
 #include "nsCOMPtr.h"
@@ -29,16 +28,33 @@
 #include "mozilla/VisualEventTracer.h"
 #include "mozilla/Services.h"
 
 namespace mozilla {
 namespace net {
 
 namespace {
 
+void LoadContextInfoMappingKey(nsAutoCString &key, nsILoadContextInfo* aInfo)
+{
+  /**
+   * This key is used to salt file hashes.  When form of the key is changed
+   * cache entries will fail to find on disk.
+   */
+  key.Append(aInfo->IsPrivate() ? 'P' : '-');
+  key.Append(aInfo->IsAnonymous() ? 'A' : '-');
+  key.Append(':');
+  if (aInfo->AppId() != nsILoadContextInfo::NO_APP_ID) {
+    key.AppendInt(aInfo->AppId());
+  }
+  if (aInfo->IsInBrowserElement()) {
+    key.Append('B');
+  }
+}
+
 void AppendMemoryStorageID(nsAutoCString &key)
 {
   key.Append('M');
 }
 
 }
 
 // Not defining as static or class member of CacheStorageService since
@@ -492,32 +508,34 @@ class CacheFilesDeletor : public nsRunna
                         , public CacheEntriesEnumeratorCallback
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   CacheFilesDeletor(nsICacheEntryDoomCallback* aCallback);
   ~CacheFilesDeletor();
 
   nsresult DeleteAll();
+  nsresult DeleteOverLimit();
   nsresult DeleteDoomed();
 
 private:
   nsresult Init(CacheFileIOManager::EEnumerateMode aMode);
   NS_IMETHOD Run();
   NS_IMETHOD Execute();
   void Callback();
   virtual void OnFile(CacheFile* aFile);
 
   nsCOMPtr<nsICacheEntryDoomCallback> mCallback;
   nsAutoPtr<CacheEntriesEnumerator> mEnumerator;
   nsRefPtr<CacheIOThread> mIOThread;
 
   uint32_t mRunning;
   enum {
     ALL,
+    OVERLIMIT,
     DOOMED
   } mMode;
   nsresult mRv;
 };
 
 NS_IMPL_ISUPPORTS_INHERITED0(CacheFilesDeletor, nsRunnable);
 
 CacheFilesDeletor::CacheFilesDeletor(nsICacheEntryDoomCallback* aCallback)
@@ -545,16 +563,22 @@ CacheFilesDeletor::~CacheFilesDeletor()
 }
 
 nsresult CacheFilesDeletor::DeleteAll()
 {
   mMode = ALL;
   return Init(CacheFileIOManager::ENTRIES);
 }
 
+nsresult CacheFilesDeletor::DeleteOverLimit()
+{
+  mMode = OVERLIMIT;
+  return Init(CacheFileIOManager::ENTRIES);
+}
+
 nsresult CacheFilesDeletor::DeleteDoomed()
 {
   mMode = DOOMED;
   return Init(CacheFileIOManager::DOOMED);
 }
 
 nsresult CacheFilesDeletor::Init(CacheFileIOManager::EEnumerateMode aMode)
 {
@@ -633,16 +657,31 @@ nsresult CacheFilesDeletor::Execute()
     // No enumerator means the job is done.
     return NS_OK;
   }
 
   nsresult rv;
   TimeStamp start;
 
   switch (mMode) {
+  case OVERLIMIT:
+    // Examine file by file and delete what is considered expired/unused.
+    while (mEnumerator->HasMore()) {
+      rv = mEnumerator->GetNextCacheFile(this);
+      if (NS_FAILED(rv))
+        return rv;
+
+      // Limit up to 5 concurrent file opens
+      if (mRunning >= 5)
+        break;
+
+      ++mRunning;
+    }
+    break;
+
   case ALL:
   case DOOMED:
     // Simply delete all files, don't doom then though the backend
     start = TimeStamp::NowLoRes();
 
     while (mEnumerator->HasMore()) {
       nsCOMPtr<nsIFile> file;
       rv = mEnumerator->GetNextFile(getter_AddRefs(file));
@@ -653,16 +692,23 @@ nsresult CacheFilesDeletor::Execute()
       nsAutoCString key;
       file->GetNativeLeafName(key);
       LOG(("  deleting file with key=%s", key.get()));
 #endif
 
       rv = file->Remove(false);
       if (NS_FAILED(rv)) {
         LOG(("  could not remove the file, probably doomed, rv=0x%08x", rv));
+#if 0
+        // No need to open and doom the file manually since we doom all entries
+        // we currently have loaded in memory.
+        rv = mEnumerator->GetCacheFileFromFile(file, this);
+        if (NS_FAILED(rv))
+          return rv;
+#endif
       }
 
       ++mRunning;
 
       if (!(mRunning % (1 << 5)) && mEnumerator->HasMore()) {
         TimeStamp now(TimeStamp::NowLoRes());
 #define DELETOR_LOOP_LIMIT_MS 200
         static TimeDuration const kLimitms = TimeDuration::FromMilliseconds(DELETOR_LOOP_LIMIT_MS);
@@ -693,16 +739,25 @@ void CacheFilesDeletor::OnFile(CacheFile
   MOZ_EVENT_TRACER_EXEC(static_cast<nsRunnable*>(this), "net::cache::deletor::file");
 
 #ifdef PR_LOG
   nsAutoCString key;
   aFile->Key(key);
 #endif
 
   switch (mMode) {
+  case OVERLIMIT:
+    if (mEnumerator->HasMore())
+      mEnumerator->GetNextCacheFile(this);
+
+    // NO BREAK ..so far..
+    // mayhemer TODO - here we should decide based on frecency and exp time
+    // whether to delete the file or not.  Then we have to check the consumption
+    // as well.
+
   case ALL:
   case DOOMED:
     LOG(("  dooming file with key=%s", key.get()));
     // Uncompromisely delete the file!
     aFile->Doom(nullptr);
     break;
   }
 
@@ -1148,17 +1203,17 @@ CacheStorageService::AddStorageEntry(Cac
                                      bool aReplace,
                                      CacheEntryHandle** aResult)
 {
   NS_ENSURE_FALSE(mShutdown, NS_ERROR_NOT_INITIALIZED);
 
   NS_ENSURE_ARG(aStorage);
 
   nsAutoCString contextKey;
-  CacheFileUtils::CreateKeyPrefix(aStorage->LoadInfo(), contextKey);
+  LoadContextInfoMappingKey(contextKey, aStorage->LoadInfo());
 
   return AddStorageEntry(contextKey, aURI, aIdExtension,
                          aStorage->WriteToDisk(), aCreateIfNotExist, aReplace,
                          aResult);
 }
 
 nsresult
 CacheStorageService::AddStorageEntry(nsCSubstring const& aContextKey,
@@ -1193,21 +1248,16 @@ CacheStorageService::AddStorageEntry(nsC
     if (!sGlobalEntryTables->Get(aContextKey, &entries)) {
       entries = new CacheEntryTable();
       sGlobalEntryTables->Put(aContextKey, entries);
       LOG(("  new storage entries table for context %s", aContextKey.BeginReading()));
     }
 
     bool entryExists = entries->Get(entryKey, getter_AddRefs(entry));
 
-    // check whether the file is already doomed
-    if (entryExists && entry->IsFileDoomed() && !aReplace) {
-      aReplace = true;
-    }
-
     // Check entry that is memory-only is also in related memory-only hashtable.
     // If not, it has been evicted and we will truncate it ; doom is pending for it,
     // this consumer just made it sooner then the entry has actually been removed
     // from the master hash table.
     // (This can be bypassed when entry is about to be replaced anyway.)
     if (entryExists && !entry->UsingDisk() && !aReplace) {
       nsAutoCString memoryStorageID(aContextKey);
       AppendMemoryStorageID(memoryStorageID);
@@ -1306,17 +1356,17 @@ CacheStorageService::DoomStorageEntry(Ca
                                       nsICacheEntryDoomCallback* aCallback)
 {
   LOG(("CacheStorageService::DoomStorageEntry"));
 
   NS_ENSURE_ARG(aStorage);
   NS_ENSURE_ARG(aURI);
 
   nsAutoCString contextKey;
-  CacheFileUtils::CreateKeyPrefix(aStorage->LoadInfo(), contextKey);
+  LoadContextInfoMappingKey(contextKey, aStorage->LoadInfo());
 
   nsAutoCString entryKey;
   nsresult rv = CacheEntry::HashingKey(EmptyCString(), aIdExtension, aURI, entryKey);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsRefPtr<CacheEntry> entry;
   {
     mozilla::MutexAutoLock lock(mLock);
@@ -1347,17 +1397,17 @@ CacheStorageService::DoomStorageEntry(Ca
     LOG(("  dooming entry %p for %s", entry.get(), entryKey.get()));
     return entry->AsyncDoom(aCallback);
   }
 
   LOG(("  no entry loaded for %s", entryKey.get()));
 
   if (aStorage->WriteToDisk()) {
     nsAutoCString contextKey;
-    CacheFileUtils::CreateKeyPrefix(aStorage->LoadInfo(), contextKey);
+    LoadContextInfoMappingKey(contextKey, aStorage->LoadInfo());
 
     rv = CacheEntry::HashingKey(contextKey, aIdExtension, aURI, entryKey);
     NS_ENSURE_SUCCESS(rv, rv);
 
     LOG(("  dooming file only for %s", entryKey.get()));
 
     nsRefPtr<CacheEntryDoomByKeyCallback> callback(
       new CacheEntryDoomByKeyCallback(aCallback));
@@ -1378,17 +1428,17 @@ CacheStorageService::DoomStorageEntries(
                                         nsICacheEntryDoomCallback* aCallback)
 {
   LOG(("CacheStorageService::DoomStorageEntries"));
 
   NS_ENSURE_FALSE(mShutdown, NS_ERROR_NOT_INITIALIZED);
   NS_ENSURE_ARG(aStorage);
 
   nsAutoCString contextKey;
-  CacheFileUtils::CreateKeyPrefix(aStorage->LoadInfo(), contextKey);
+  LoadContextInfoMappingKey(contextKey, aStorage->LoadInfo());
 
   mozilla::MutexAutoLock lock(mLock);
 
   return DoomStorageEntries(contextKey, aStorage->WriteToDisk(), aCallback);
 }
 
 nsresult
 CacheStorageService::DoomStorageEntries(nsCSubstring const& aContextKey,
@@ -1431,44 +1481,17 @@ CacheStorageService::WalkStorageEntries(
                                         nsICacheStorageVisitor* aVisitor)
 {
   LOG(("CacheStorageService::WalkStorageEntries [cb=%p, visitentries=%d]", aVisitor, aVisitEntries));
   NS_ENSURE_FALSE(mShutdown, NS_ERROR_NOT_INITIALIZED);
 
   NS_ENSURE_ARG(aStorage);
 
   nsAutoCString contextKey;
-  CacheFileUtils::CreateKeyPrefix(aStorage->LoadInfo(), contextKey);
+  LoadContextInfoMappingKey(contextKey, aStorage->LoadInfo());
 
   nsRefPtr<WalkRunnable> event = new WalkRunnable(
     contextKey, aVisitEntries, aStorage->WriteToDisk(), aVisitor);
   return Dispatch(event);
 }
 
-nsresult
-CacheStorageService::CacheFileDoomed(nsILoadContextInfo* aLoadContextInfo,
-                                     const nsACString & aURL)
-{
-  nsRefPtr<CacheEntry> entry;
-  nsAutoCString contextKey;
-  CacheFileUtils::CreateKeyPrefix(aLoadContextInfo, contextKey);
-
-  {
-    mozilla::MutexAutoLock lock(mLock);
-
-    NS_ENSURE_FALSE(mShutdown, NS_ERROR_NOT_INITIALIZED);
-
-    CacheEntryTable* entries;
-    if (sGlobalEntryTables->Get(contextKey, &entries)) {
-      entries->Get(aURL, getter_AddRefs(entry));
-    }
-  }
-
-  if (entry && entry->IsFileDoomed()) {
-    entry->PurgeAndDoom();
-  }
-
-  return NS_OK;
-}
-
-
 } // net
 } // mozilla
--- a/netwerk/cache2/CacheStorageService.h
+++ b/netwerk/cache2/CacheStorageService.h
@@ -98,17 +98,16 @@ private:
    */
   void RecordMemoryOnlyEntry(CacheEntry* aEntry,
                              bool aOnlyInMemory,
                              bool aOverwrite);
 
 private:
   // Following methods are thread safe to call.
   friend class CacheStorage;
-  friend class CacheFileIOManager;
 
   /**
    * Get, or create when not existing and demanded, an entry for the storage
    * and uri+id extension.
    */
   nsresult AddStorageEntry(CacheStorage const* aStorage,
                            nsIURI* aURI,
                            const nsACString & aIdExtension,
@@ -133,24 +132,16 @@ private:
 
   /**
    * Walk all entiries beloging to the storage.
    */
   nsresult WalkStorageEntries(CacheStorage const* aStorage,
                               bool aVisitEntries,
                               nsICacheStorageVisitor* aVisitor);
 
-  /**
-   * CacheFileIOManager uses this method to notify CacheStorageService that
-   * an active entry was removed. This method is called even if the entry
-   * removal was originated by CacheStorageService.
-   */
-  nsresult CacheFileDoomed(nsILoadContextInfo* aLoadContextInfo,
-                           const nsACString & aURL);
-
 private:
   friend class CacheMemoryConsumer;
 
   /**
    * When memory consumption of this entry radically changes, this method
    * is called to reflect the size of allocated memory.  This call may purge
    * unspecified number of entries from memory (but not from disk).
    */
--- a/netwerk/cache2/moz.build
+++ b/netwerk/cache2/moz.build
@@ -34,17 +34,16 @@ SOURCES += [
     'AppCacheStorage.cpp',
     'CacheEntry.cpp',
     'CacheFile.cpp',
     'CacheFileChunk.cpp',
     'CacheFileInputStream.cpp',
     'CacheFileIOManager.cpp',
     'CacheFileMetadata.cpp',
     'CacheFileOutputStream.cpp',
-    'CacheFileUtils.cpp',
     'CacheIndex.cpp',
     'CacheLog.cpp',
     'CacheStorage.cpp',
     'CacheStorageService.cpp',
     'OldWrappers.cpp',
 ]
 
 LOCAL_INCLUDES += [