Backed out 3 changesets (bug 1110485) for wpt-3 bustage
authorWes Kocher <wkocher@mozilla.com>
Mon, 13 Apr 2015 15:18:19 -0700
changeset 238940 fb25d83dcaa05008678ad2f14c24c1a1fdd47266
parent 238939 09f1edec24b6b4f54f8ddaadf5c77859c36eeae3
child 238941 f65fd10ee5a7bf7082f1edbf5e5ce64d4c06780c
push id28577
push userryanvm@gmail.com
push dateTue, 14 Apr 2015 14:06:33 +0000
treeherdermozilla-central@388f5861dc7d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1110485
milestone40.0a1
backs oute8bd3bf404ff5d0fc62e2957fcdaaad7c085a8d7
fa29dbb49a668c61b13e7808176bf73afc35ae70
12deb121d126d59bec12953eecdf5bfe0d1af7bf
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 3 changesets (bug 1110485) for wpt-3 bustage Backed out changeset e8bd3bf404ff (bug 1110485) Backed out changeset fa29dbb49a66 (bug 1110485) Backed out changeset 12deb121d126 (bug 1110485)
dom/cache/AutoUtils.cpp
dom/cache/AutoUtils.h
dom/cache/Cache.cpp
dom/cache/Cache.h
dom/cache/CacheChild.cpp
dom/cache/CacheChild.h
dom/cache/CacheInitData.ipdlh
dom/cache/CacheOpChild.cpp
dom/cache/CacheOpChild.h
dom/cache/CacheOpParent.cpp
dom/cache/CacheOpParent.h
dom/cache/CacheParent.cpp
dom/cache/CacheParent.h
dom/cache/CacheStorage.cpp
dom/cache/CacheStorage.h
dom/cache/CacheStorageChild.cpp
dom/cache/CacheStorageChild.h
dom/cache/CacheStorageParent.cpp
dom/cache/CacheStorageParent.h
dom/cache/CacheStreamControlChild.cpp
dom/cache/CacheStreamControlChild.h
dom/cache/CacheStreamControlParent.cpp
dom/cache/CacheStreamControlParent.h
dom/cache/CacheTypes.ipdlh
dom/cache/DBAction.cpp
dom/cache/DBAction.h
dom/cache/DBSchema.cpp
dom/cache/DBSchema.h
dom/cache/FetchPut.cpp
dom/cache/FetchPut.h
dom/cache/IPCUtils.h
dom/cache/Manager.cpp
dom/cache/Manager.h
dom/cache/PCache.ipdl
dom/cache/PCacheOp.ipdl
dom/cache/PCacheStorage.ipdl
dom/cache/PCacheTypes.ipdlh
dom/cache/PrincipalVerifier.cpp
dom/cache/PrincipalVerifier.h
dom/cache/ReadStream.cpp
dom/cache/ReadStream.h
dom/cache/SavedTypes.h
dom/cache/StreamControl.h
dom/cache/StreamUtils.cpp
dom/cache/StreamUtils.h
dom/cache/TypeUtils.cpp
dom/cache/TypeUtils.h
dom/cache/Types.h
dom/cache/moz.build
dom/fetch/FetchIPCUtils.h
dom/fetch/InternalHeaders.cpp
dom/fetch/InternalHeaders.h
dom/fetch/PHeaders.ipdlh
dom/fetch/moz.build
--- a/dom/cache/AutoUtils.cpp
+++ b/dom/cache/AutoUtils.cpp
@@ -2,46 +2,45 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "mozilla/dom/cache/AutoUtils.h"
 
 #include "mozilla/unused.h"
-#include "mozilla/dom/cache/CacheParent.h"
 #include "mozilla/dom/cache/CachePushStreamChild.h"
 #include "mozilla/dom/cache/CacheStreamControlParent.h"
 #include "mozilla/dom/cache/ReadStream.h"
 #include "mozilla/dom/cache/SavedTypes.h"
 #include "mozilla/dom/cache/StreamList.h"
 #include "mozilla/dom/cache/TypeUtils.h"
 #include "mozilla/ipc/FileDescriptorSetChild.h"
 #include "mozilla/ipc/FileDescriptorSetParent.h"
 #include "mozilla/ipc/PBackgroundParent.h"
 
 namespace {
 
 using mozilla::unused;
 using mozilla::dom::cache::CachePushStreamChild;
-using mozilla::dom::cache::CacheReadStream;
-using mozilla::dom::cache::CacheReadStreamOrVoid;
+using mozilla::dom::cache::PCacheReadStream;
+using mozilla::dom::cache::PCacheReadStreamOrVoid;
 using mozilla::ipc::FileDescriptor;
 using mozilla::ipc::FileDescriptorSetChild;
 using mozilla::ipc::FileDescriptorSetParent;
 using mozilla::ipc::OptionalFileDescriptorSet;
 
 enum CleanupAction
 {
   Forget,
   Delete
 };
 
 void
-CleanupChildFds(CacheReadStream& aReadStream, CleanupAction aAction)
+CleanupChildFds(PCacheReadStream& aReadStream, CleanupAction aAction)
 {
   if (aReadStream.fds().type() !=
       OptionalFileDescriptorSet::TPFileDescriptorSetChild) {
     return;
   }
 
   nsAutoTArray<FileDescriptor, 4> fds;
 
@@ -55,17 +54,17 @@ CleanupChildFds(CacheReadStream& aReadSt
 
   // FileDescriptorSet doesn't clear its fds in its ActorDestroy, so we
   // unconditionally forget them here.  The fds themselves are auto-closed in
   // ~FileDescriptor since they originated in this process.
   fdSetActor->ForgetFileDescriptors(fds);
 }
 
 void
-CleanupChildPushStream(CacheReadStream& aReadStream, CleanupAction aAction)
+CleanupChildPushStream(PCacheReadStream& aReadStream, CleanupAction aAction)
 {
   if (!aReadStream.pushStreamChild()) {
     return;
   }
 
   auto pushStream =
     static_cast<CachePushStreamChild*>(aReadStream.pushStreamChild());
 
@@ -74,34 +73,34 @@ CleanupChildPushStream(CacheReadStream& 
     return;
   }
 
   // If we send the stream, then we need to start it before forgetting about it.
   pushStream->Start();
 }
 
 void
-CleanupChild(CacheReadStream& aReadStream, CleanupAction aAction)
+CleanupChild(PCacheReadStream& aReadStream, CleanupAction aAction)
 {
   CleanupChildFds(aReadStream, aAction);
   CleanupChildPushStream(aReadStream, aAction);
 }
 
 void
-CleanupChild(CacheReadStreamOrVoid& aReadStreamOrVoid, CleanupAction aAction)
+CleanupChild(PCacheReadStreamOrVoid& aReadStreamOrVoid, CleanupAction aAction)
 {
-  if (aReadStreamOrVoid.type() == CacheReadStreamOrVoid::Tvoid_t) {
+  if (aReadStreamOrVoid.type() == PCacheReadStreamOrVoid::Tvoid_t) {
     return;
   }
 
-  CleanupChild(aReadStreamOrVoid.get_CacheReadStream(), aAction);
+  CleanupChild(aReadStreamOrVoid.get_PCacheReadStream(), aAction);
 }
 
 void
-CleanupParentFds(CacheReadStream& aReadStream, CleanupAction aAction)
+CleanupParentFds(PCacheReadStream& aReadStream, CleanupAction aAction)
 {
   if (aReadStream.fds().type() !=
       OptionalFileDescriptorSet::TPFileDescriptorSetParent) {
     return;
   }
 
   nsAutoTArray<FileDescriptor, 4> fds;
 
@@ -115,408 +114,198 @@ CleanupParentFds(CacheReadStream& aReadS
 
   // FileDescriptorSet doesn't clear its fds in its ActorDestroy, so we
   // unconditionally forget them here.  The fds themselves are auto-closed in
   // ~FileDescriptor since they originated in this process.
   fdSetActor->ForgetFileDescriptors(fds);
 }
 
 void
-CleanupParentFds(CacheReadStreamOrVoid& aReadStreamOrVoid, CleanupAction aAction)
+CleanupParentFds(PCacheReadStreamOrVoid& aReadStreamOrVoid, CleanupAction aAction)
 {
-  if (aReadStreamOrVoid.type() == CacheReadStreamOrVoid::Tvoid_t) {
+  if (aReadStreamOrVoid.type() == PCacheReadStreamOrVoid::Tvoid_t) {
     return;
   }
 
-  CleanupParentFds(aReadStreamOrVoid.get_CacheReadStream(), aAction);
+  CleanupParentFds(aReadStreamOrVoid.get_PCacheReadStream(), aAction);
 }
 
 } // anonymous namespace
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 using mozilla::ipc::PBackgroundParent;
 
-// --------------------------------------------
-
-AutoChildOpArgs::AutoChildOpArgs(TypeUtils* aTypeUtils,
-                                 const CacheOpArgs& aOpArgs)
+AutoChildBase::AutoChildBase(TypeUtils* aTypeUtils)
   : mTypeUtils(aTypeUtils)
-  , mOpArgs(aOpArgs)
   , mSent(false)
 {
   MOZ_ASSERT(mTypeUtils);
 }
 
-AutoChildOpArgs::~AutoChildOpArgs()
+AutoChildBase::~AutoChildBase()
+{
+}
+
+// --------------------------------------------
+
+AutoChildRequest::AutoChildRequest(TypeUtils* aTypeUtils)
+  : AutoChildBase(aTypeUtils)
+{
+  mRequestOrVoid = void_t();
+}
+
+AutoChildRequest::~AutoChildRequest()
+{
+  if (mRequestOrVoid.type() != PCacheRequestOrVoid::TPCacheRequest) {
+    return;
+  }
+
+  CleanupAction action = mSent ? Forget : Delete;
+  CleanupChild(mRequestOrVoid.get_PCacheRequest().body(), action);
+}
+
+void
+AutoChildRequest::Add(InternalRequest* aRequest, BodyAction aBodyAction,
+                      ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
+                      ErrorResult& aRv)
+{
+  MOZ_ASSERT(!mSent);
+  MOZ_ASSERT(mRequestOrVoid.type() == PCacheRequestOrVoid::Tvoid_t);
+  mRequestOrVoid = PCacheRequest();
+  mTypeUtils->ToPCacheRequest(mRequestOrVoid.get_PCacheRequest(), aRequest,
+                              aBodyAction, aReferrerAction, aSchemeAction, aRv);
+}
+
+const PCacheRequest&
+AutoChildRequest::SendAsRequest()
+{
+  MOZ_ASSERT(mRequestOrVoid.type() == PCacheRequestOrVoid::TPCacheRequest);
+  return mRequestOrVoid.get_PCacheRequest();
+}
+
+const PCacheRequestOrVoid&
+AutoChildRequest::SendAsRequestOrVoid()
+{
+  return mRequestOrVoid;
+}
+
+// --------------------------------------------
+
+AutoChildRequestList::AutoChildRequestList(TypeUtils* aTypeUtils,
+                                           uint32_t aCapacity)
+  : AutoChildBase(aTypeUtils)
+{
+  mRequestList.SetCapacity(aCapacity);
+}
+
+AutoChildRequestList::~AutoChildRequestList()
 {
   CleanupAction action = mSent ? Forget : Delete;
-
-  switch(mOpArgs.type()) {
-    case CacheOpArgs::TCacheMatchArgs:
-    {
-      CacheMatchArgs& args = mOpArgs.get_CacheMatchArgs();
-      CleanupChild(args.request().body(), action);
-      break;
-    }
-    case CacheOpArgs::TCacheMatchAllArgs:
-    {
-      CacheMatchAllArgs& args = mOpArgs.get_CacheMatchAllArgs();
-      if (args.requestOrVoid().type() == CacheRequestOrVoid::Tvoid_t) {
-        break;
-      }
-      CleanupChild(args.requestOrVoid().get_CacheRequest().body(), action);
-      break;
-    }
-    case CacheOpArgs::TCacheAddAllArgs:
-    {
-      CacheAddAllArgs& args = mOpArgs.get_CacheAddAllArgs();
-      auto& list = args.requestList();
-      for (uint32_t i = 0; i < list.Length(); ++i) {
-        CleanupChild(list[i].body(), action);
-      }
-      break;
-    }
-    case CacheOpArgs::TCachePutAllArgs:
-    {
-      CachePutAllArgs& args = mOpArgs.get_CachePutAllArgs();
-      auto& list = args.requestResponseList();
-      for (uint32_t i = 0; i < list.Length(); ++i) {
-        CleanupChild(list[i].request().body(), action);
-        CleanupChild(list[i].response().body(), action);
-      }
-      break;
-    }
-    case CacheOpArgs::TCacheDeleteArgs:
-    {
-      CacheDeleteArgs& args = mOpArgs.get_CacheDeleteArgs();
-      CleanupChild(args.request().body(), action);
-      break;
-    }
-    case CacheOpArgs::TCacheKeysArgs:
-    {
-      CacheKeysArgs& args = mOpArgs.get_CacheKeysArgs();
-      if (args.requestOrVoid().type() == CacheRequestOrVoid::Tvoid_t) {
-        break;
-      }
-      CleanupChild(args.requestOrVoid().get_CacheRequest().body(), action);
-      break;
-    }
-    case CacheOpArgs::TStorageMatchArgs:
-    {
-      StorageMatchArgs& args = mOpArgs.get_StorageMatchArgs();
-      CleanupChild(args.request().body(), action);
-      break;
-    }
-    default:
-      // Other types do not need cleanup
-      break;
+  for (uint32_t i = 0; i < mRequestList.Length(); ++i) {
+    CleanupChild(mRequestList[i].body(), action);
   }
 }
 
 void
-AutoChildOpArgs::Add(InternalRequest* aRequest, BodyAction aBodyAction,
-                     ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
-                     ErrorResult& aRv)
+AutoChildRequestList::Add(InternalRequest* aRequest, BodyAction aBodyAction,
+                          ReferrerAction aReferrerAction,
+                          SchemeAction aSchemeAction, ErrorResult& aRv)
 {
   MOZ_ASSERT(!mSent);
 
-  switch(mOpArgs.type()) {
-    case CacheOpArgs::TCacheMatchArgs:
-    {
-      CacheMatchArgs& args = mOpArgs.get_CacheMatchArgs();
-      mTypeUtils->ToCacheRequest(args.request(), aRequest, aBodyAction,
-                                  aReferrerAction, aSchemeAction, aRv);
-      break;
-    }
-    case CacheOpArgs::TCacheMatchAllArgs:
-    {
-      CacheMatchAllArgs& args = mOpArgs.get_CacheMatchAllArgs();
-      MOZ_ASSERT(args.requestOrVoid().type() == CacheRequestOrVoid::Tvoid_t);
-      args.requestOrVoid() = CacheRequest();
-      mTypeUtils->ToCacheRequest(args.requestOrVoid().get_CacheRequest(),
-                                  aRequest, aBodyAction, aReferrerAction,
-                                  aSchemeAction, aRv);
-      break;
-    }
-    case CacheOpArgs::TCacheAddAllArgs:
-    {
-      CacheAddAllArgs& args = mOpArgs.get_CacheAddAllArgs();
-
-      // The FileDescriptorSetChild asserts in its destructor that all fds have
-      // been removed.  The copy constructor, however, simply duplicates the
-      // fds without removing any.  This means each temporary and copy must be
-      // explicitly cleaned up.
-      //
-      // Avoid a lot of this hassle by making sure we only create one here.  On
-      // error we remove it.
-      CacheRequest& request = *args.requestList().AppendElement();
+  // The FileDescriptorSetChild asserts in its destructor that all fds have
+  // been removed.  The copy constructor, however, simply duplicates the
+  // fds without removing any.  This means each temporary and copy must be
+  // explicitly cleaned up.
+  //
+  // Avoid a lot of this hassle by making sure we only create one here.  On
+  // error we remove it.
 
-      mTypeUtils->ToCacheRequest(request, aRequest, aBodyAction,
-                                  aReferrerAction, aSchemeAction, aRv);
-      if (aRv.Failed()) {
-        args.requestList().RemoveElementAt(args.requestList().Length() - 1);
-      }
-      break;
-    }
-    case CacheOpArgs::TCacheDeleteArgs:
-    {
-      CacheDeleteArgs& args = mOpArgs.get_CacheDeleteArgs();
-      mTypeUtils->ToCacheRequest(args.request(), aRequest, aBodyAction,
-                                  aReferrerAction, aSchemeAction, aRv);
-      break;
-    }
-    case CacheOpArgs::TCacheKeysArgs:
-    {
-      CacheKeysArgs& args = mOpArgs.get_CacheKeysArgs();
-      MOZ_ASSERT(args.requestOrVoid().type() == CacheRequestOrVoid::Tvoid_t);
-      args.requestOrVoid() = CacheRequest();
-      mTypeUtils->ToCacheRequest(args.requestOrVoid().get_CacheRequest(),
-                                  aRequest, aBodyAction, aReferrerAction,
-                                  aSchemeAction, aRv);
-      break;
-    }
-    case CacheOpArgs::TStorageMatchArgs:
-    {
-      StorageMatchArgs& args = mOpArgs.get_StorageMatchArgs();
-      mTypeUtils->ToCacheRequest(args.request(), aRequest, aBodyAction,
-                                  aReferrerAction, aSchemeAction, aRv);
-      break;
-    }
-    default:
-      MOZ_CRASH("Cache args type cannot send a Request!");
+  PCacheRequest* request = mRequestList.AppendElement();
+  mTypeUtils->ToPCacheRequest(*request, aRequest, aBodyAction, aReferrerAction,
+                              aSchemeAction, aRv);
+  if (aRv.Failed()) {
+    mRequestList.RemoveElementAt(mRequestList.Length() - 1);
   }
 }
 
-void
-AutoChildOpArgs::Add(InternalRequest* aRequest, BodyAction aBodyAction,
-                     ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
-                     Response& aResponse, ErrorResult& aRv)
-{
-  MOZ_ASSERT(!mSent);
-
-  switch(mOpArgs.type()) {
-    case CacheOpArgs::TCachePutAllArgs:
-    {
-      CachePutAllArgs& args = mOpArgs.get_CachePutAllArgs();
-
-      // The FileDescriptorSetChild asserts in its destructor that all fds have
-      // been removed.  The copy constructor, however, simply duplicates the
-      // fds without removing any.  This means each temporary and copy must be
-      // explicitly cleaned up.
-      //
-      // Avoid a lot of this hassle by making sure we only create one here.  On
-      // error we remove it.
-      CacheRequestResponse& pair = *args.requestResponseList().AppendElement();
-      pair.request().body() = void_t();
-      pair.response().body() = void_t();
-
-      mTypeUtils->ToCacheRequest(pair.request(), aRequest, aBodyAction,
-                                  aReferrerAction, aSchemeAction, aRv);
-      if (!aRv.Failed()) {
-        mTypeUtils->ToCacheResponse(pair.response(), aResponse, aRv);
-      }
-
-      if (aRv.Failed()) {
-        CleanupChild(pair.request().body(), Delete);
-        args.requestResponseList().RemoveElementAt(
-          args.requestResponseList().Length() - 1);
-      }
-
-      break;
-    }
-    default:
-      MOZ_CRASH("Cache args type cannot send a Request/Response pair!");
-  }
-}
-
-const CacheOpArgs&
-AutoChildOpArgs::SendAsOpArgs()
+const nsTArray<PCacheRequest>&
+AutoChildRequestList::SendAsRequestList()
 {
   MOZ_ASSERT(!mSent);
   mSent = true;
-  return mOpArgs;
+  return mRequestList;
 }
 
 // --------------------------------------------
 
-AutoParentOpResult::AutoParentOpResult(mozilla::ipc::PBackgroundParent* aManager,
-                                       const CacheOpResult& aOpResult)
+AutoChildRequestResponse::AutoChildRequestResponse(TypeUtils* aTypeUtils)
+  : AutoChildBase(aTypeUtils)
+{
+  // Default IPC-generated constructor does not initialize these correctly
+  // and we check them later when cleaning up.
+  mRequestResponse.request().body() = void_t();
+  mRequestResponse.response().body() = void_t();
+}
+
+AutoChildRequestResponse::~AutoChildRequestResponse()
+{
+  CleanupAction action = mSent ? Forget : Delete;
+  CleanupChild(mRequestResponse.request().body(), action);
+  CleanupChild(mRequestResponse.response().body(), action);
+}
+
+void
+AutoChildRequestResponse::Add(InternalRequest* aRequest, BodyAction aBodyAction,
+                              ReferrerAction aReferrerAction,
+                              SchemeAction aSchemeAction, ErrorResult& aRv)
+{
+  MOZ_ASSERT(!mSent);
+  mTypeUtils->ToPCacheRequest(mRequestResponse.request(), aRequest, aBodyAction,
+                              aReferrerAction, aSchemeAction, aRv);
+}
+
+void
+AutoChildRequestResponse::Add(Response& aResponse, ErrorResult& aRv)
+{
+  MOZ_ASSERT(!mSent);
+  mTypeUtils->ToPCacheResponse(mRequestResponse.response(), aResponse, aRv);
+}
+
+const CacheRequestResponse&
+AutoChildRequestResponse::SendAsRequestResponse()
+{
+  MOZ_ASSERT(!mSent);
+  mSent = true;
+  return mRequestResponse;
+}
+
+// --------------------------------------------
+
+AutoParentBase::AutoParentBase(PBackgroundParent* aManager)
   : mManager(aManager)
-  , mOpResult(aOpResult)
   , mStreamControl(nullptr)
   , mSent(false)
 {
   MOZ_ASSERT(mManager);
 }
 
-AutoParentOpResult::~AutoParentOpResult()
+AutoParentBase::~AutoParentBase()
 {
-  CleanupAction action = mSent ? Forget : Delete;
-
-  switch (mOpResult.type()) {
-    case CacheOpResult::TCacheMatchResult:
-    {
-      CacheMatchResult& result = mOpResult.get_CacheMatchResult();
-      if (result.responseOrVoid().type() == CacheResponseOrVoid::Tvoid_t) {
-        break;
-      }
-      CleanupParentFds(result.responseOrVoid().get_CacheResponse().body(),
-                       action);
-      break;
-    }
-    case CacheOpResult::TCacheMatchAllResult:
-    {
-      CacheMatchAllResult& result = mOpResult.get_CacheMatchAllResult();
-      for (uint32_t i = 0; i < result.responseList().Length(); ++i) {
-        CleanupParentFds(result.responseList()[i].body(), action);
-      }
-      break;
-    }
-    case CacheOpResult::TCacheKeysResult:
-    {
-      CacheKeysResult& result = mOpResult.get_CacheKeysResult();
-      for (uint32_t i = 0; i < result.requestList().Length(); ++i) {
-        CleanupParentFds(result.requestList()[i].body(), action);
-      }
-      break;
-    }
-    case CacheOpResult::TStorageMatchResult:
-    {
-      StorageMatchResult& result = mOpResult.get_StorageMatchResult();
-      if (result.responseOrVoid().type() == CacheResponseOrVoid::Tvoid_t) {
-        break;
-      }
-      CleanupParentFds(result.responseOrVoid().get_CacheResponse().body(),
-                       action);
-      break;
-    }
-    case CacheOpResult::TStorageOpenResult:
-    {
-      StorageOpenResult& result = mOpResult.get_StorageOpenResult();
-      if (action == Forget || result.actorParent() == nullptr) {
-        break;
-      }
-      unused << PCacheParent::Send__delete__(result.actorParent());
-    }
-    default:
-      // other types do not need clean up
-      break;
-  }
-
-  if (action == Delete && mStreamControl) {
+  if (!mSent && mStreamControl) {
     unused << PCacheStreamControlParent::Send__delete__(mStreamControl);
   }
 }
 
 void
-AutoParentOpResult::Add(CacheId aOpenedCacheId, Manager* aManager)
-{
-  MOZ_ASSERT(mOpResult.type() == CacheOpResult::TStorageOpenResult);
-  MOZ_ASSERT(mOpResult.get_StorageOpenResult().actorParent() == nullptr);
-  mOpResult.get_StorageOpenResult().actorParent() =
-    mManager->SendPCacheConstructor(new CacheParent(aManager, aOpenedCacheId));
-}
-
-void
-AutoParentOpResult::Add(const SavedResponse& aSavedResponse,
-                        StreamList* aStreamList)
-{
-  MOZ_ASSERT(!mSent);
-
-  switch (mOpResult.type()) {
-    case CacheOpResult::TCacheMatchResult:
-    {
-      CacheMatchResult& result = mOpResult.get_CacheMatchResult();
-      MOZ_ASSERT(result.responseOrVoid().type() == CacheResponseOrVoid::Tvoid_t);
-      result.responseOrVoid() = aSavedResponse.mValue;
-      SerializeResponseBody(aSavedResponse, aStreamList,
-                            &result.responseOrVoid().get_CacheResponse());
-      break;
-    }
-    case CacheOpResult::TCacheMatchAllResult:
-    {
-      CacheMatchAllResult& result = mOpResult.get_CacheMatchAllResult();
-      result.responseList().AppendElement(aSavedResponse.mValue);
-      SerializeResponseBody(aSavedResponse, aStreamList,
-                            &result.responseList().LastElement());
-      break;
-    }
-    case CacheOpResult::TStorageMatchResult:
-    {
-      StorageMatchResult& result = mOpResult.get_StorageMatchResult();
-      MOZ_ASSERT(result.responseOrVoid().type() == CacheResponseOrVoid::Tvoid_t);
-      result.responseOrVoid() = aSavedResponse.mValue;
-      SerializeResponseBody(aSavedResponse, aStreamList,
-                            &result.responseOrVoid().get_CacheResponse());
-      break;
-    }
-    default:
-      MOZ_CRASH("Cache result type cannot handle returning a Response!");
-  }
-}
-
-void
-AutoParentOpResult::Add(const SavedRequest& aSavedRequest,
-                        StreamList* aStreamList)
-{
-  MOZ_ASSERT(!mSent);
-
-  switch (mOpResult.type()) {
-    case CacheOpResult::TCacheKeysResult:
-    {
-      CacheKeysResult& result = mOpResult.get_CacheKeysResult();
-      result.requestList().AppendElement(aSavedRequest.mValue);
-      CacheRequest& request = result.requestList().LastElement();
-
-      if (!aSavedRequest.mHasBodyId) {
-        request.body() = void_t();
-        break;
-      }
-
-      request.body() = CacheReadStream();
-      SerializeReadStream(aSavedRequest.mBodyId, aStreamList,
-                          &request.body().get_CacheReadStream());
-      break;
-    }
-    default:
-      MOZ_CRASH("Cache result type cannot handle returning a Request!");
-  }
-}
-
-const CacheOpResult&
-AutoParentOpResult::SendAsOpResult()
-{
-  MOZ_ASSERT(!mSent);
-  mSent = true;
-  return mOpResult;
-}
-
-void
-AutoParentOpResult::SerializeResponseBody(const SavedResponse& aSavedResponse,
-                                          StreamList* aStreamList,
-                                          CacheResponse* aResponseOut)
-{
-  MOZ_ASSERT(aResponseOut);
-
-  if (!aSavedResponse.mHasBodyId) {
-    aResponseOut->body() = void_t();
-    return;
-  }
-
-  aResponseOut->body() = CacheReadStream();
-  SerializeReadStream(aSavedResponse.mBodyId, aStreamList,
-                      &aResponseOut->body().get_CacheReadStream());
-}
-
-void
-AutoParentOpResult::SerializeReadStream(const nsID& aId, StreamList* aStreamList,
-                                        CacheReadStream* aReadStreamOut)
+AutoParentBase::SerializeReadStream(const nsID& aId, StreamList* aStreamList,
+                                    PCacheReadStream* aReadStreamOut)
 {
   MOZ_ASSERT(aStreamList);
   MOZ_ASSERT(aReadStreamOut);
   MOZ_ASSERT(!mSent);
 
   nsCOMPtr<nsIInputStream> stream = aStreamList->Extract(aId);
   MOZ_ASSERT(stream);
 
@@ -534,11 +323,144 @@ AutoParentOpResult::SerializeReadStream(
 
   aStreamList->SetStreamControl(mStreamControl);
 
   nsRefPtr<ReadStream> readStream = ReadStream::Create(mStreamControl,
                                                        aId, stream);
   readStream->Serialize(aReadStreamOut);
 }
 
+// --------------------------------------------
+
+AutoParentRequestList::AutoParentRequestList(PBackgroundParent* aManager,
+                                             uint32_t aCapacity)
+  : AutoParentBase(aManager)
+{
+  mRequestList.SetCapacity(aCapacity);
+}
+
+AutoParentRequestList::~AutoParentRequestList()
+{
+  CleanupAction action = mSent ? Forget : Delete;
+  for (uint32_t i = 0; i < mRequestList.Length(); ++i) {
+    CleanupParentFds(mRequestList[i].body(), action);
+  }
+}
+
+void
+AutoParentRequestList::Add(const SavedRequest& aSavedRequest,
+                           StreamList* aStreamList)
+{
+  MOZ_ASSERT(!mSent);
+
+  mRequestList.AppendElement(aSavedRequest.mValue);
+  PCacheRequest& request = mRequestList.LastElement();
+
+  if (!aSavedRequest.mHasBodyId) {
+    request.body() = void_t();
+    return;
+  }
+
+  request.body() = PCacheReadStream();
+  SerializeReadStream(aSavedRequest.mBodyId, aStreamList,
+                      &request.body().get_PCacheReadStream());
+}
+
+const nsTArray<PCacheRequest>&
+AutoParentRequestList::SendAsRequestList()
+{
+  MOZ_ASSERT(!mSent);
+  mSent = true;
+  return mRequestList;
+}
+
+// --------------------------------------------
+
+AutoParentResponseList::AutoParentResponseList(PBackgroundParent* aManager,
+                                               uint32_t aCapacity)
+  : AutoParentBase(aManager)
+{
+  mResponseList.SetCapacity(aCapacity);
+}
+
+AutoParentResponseList::~AutoParentResponseList()
+{
+  CleanupAction action = mSent ? Forget : Delete;
+  for (uint32_t i = 0; i < mResponseList.Length(); ++i) {
+    CleanupParentFds(mResponseList[i].body(), action);
+  }
+}
+
+void
+AutoParentResponseList::Add(const SavedResponse& aSavedResponse,
+                            StreamList* aStreamList)
+{
+  MOZ_ASSERT(!mSent);
+
+  mResponseList.AppendElement(aSavedResponse.mValue);
+  PCacheResponse& response = mResponseList.LastElement();
+
+  if (!aSavedResponse.mHasBodyId) {
+    response.body() = void_t();
+    return;
+  }
+
+  response.body() = PCacheReadStream();
+  SerializeReadStream(aSavedResponse.mBodyId, aStreamList,
+                      &response.body().get_PCacheReadStream());
+}
+
+const nsTArray<PCacheResponse>&
+AutoParentResponseList::SendAsResponseList()
+{
+  MOZ_ASSERT(!mSent);
+  mSent = true;
+  return mResponseList;
+}
+
+// --------------------------------------------
+
+AutoParentResponseOrVoid::AutoParentResponseOrVoid(ipc::PBackgroundParent* aManager)
+  : AutoParentBase(aManager)
+{
+  mResponseOrVoid = void_t();
+}
+
+AutoParentResponseOrVoid::~AutoParentResponseOrVoid()
+{
+  if (mResponseOrVoid.type() != PCacheResponseOrVoid::TPCacheResponse) {
+    return;
+  }
+
+  CleanupAction action = mSent ? Forget : Delete;
+  CleanupParentFds(mResponseOrVoid.get_PCacheResponse().body(), action);
+}
+
+void
+AutoParentResponseOrVoid::Add(const SavedResponse& aSavedResponse,
+                              StreamList* aStreamList)
+{
+  MOZ_ASSERT(!mSent);
+
+  mResponseOrVoid = aSavedResponse.mValue;
+  PCacheResponse& response = mResponseOrVoid.get_PCacheResponse();
+
+  if (!aSavedResponse.mHasBodyId) {
+    response.body() = void_t();
+    return;
+  }
+
+  response.body() = PCacheReadStream();
+  SerializeReadStream(aSavedResponse.mBodyId, aStreamList,
+                      &response.body().get_PCacheReadStream());
+}
+
+const PCacheResponseOrVoid&
+AutoParentResponseOrVoid::SendAsResponseOrVoid()
+{
+  MOZ_ASSERT(!mSent);
+  mSent = true;
+  return mResponseOrVoid;
+}
+
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
--- a/dom/cache/AutoUtils.h
+++ b/dom/cache/AutoUtils.h
@@ -3,18 +3,17 @@
 /* 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 mozilla_dom_cache_AutoUtils_h
 #define mozilla_dom_cache_AutoUtils_h
 
 #include "mozilla/Attributes.h"
-#include "mozilla/dom/cache/CacheTypes.h"
-#include "mozilla/dom/cache/Types.h"
+#include "mozilla/dom/cache/PCacheTypes.h"
 #include "mozilla/dom/cache/TypeUtils.h"
 #include "nsTArray.h"
 
 struct nsID;
 
 namespace mozilla {
 
 class ErrorResult;
@@ -25,78 +24,150 @@ class PBackgroundParent;
 
 namespace dom {
 
 class InternalRequest;
 
 namespace cache {
 
 class CacheStreamControlParent;
-class Manager;
 struct SavedRequest;
 struct SavedResponse;
 class StreamList;
 
 // A collection of RAII-style helper classes to ensure that IPC
 // FileDescriptorSet actors are properly cleaned up.  The user of these actors
 // must manually either Forget() the Fds or Send__delete__() the actor
 // depending on if the descriptors were actually sent.
 //
 // Note, these should only be used when *sending* streams across IPC.  The
 // deserialization case is handled by creating a ReadStream object.
 
-class MOZ_STACK_CLASS AutoChildOpArgs final
+class MOZ_STACK_CLASS AutoChildBase
 {
-public:
+protected:
   typedef TypeUtils::BodyAction BodyAction;
   typedef TypeUtils::ReferrerAction ReferrerAction;
   typedef TypeUtils::SchemeAction SchemeAction;
 
-  AutoChildOpArgs(TypeUtils* aTypeUtils, const CacheOpArgs& aOpArgs);
-  ~AutoChildOpArgs();
+  AutoChildBase(TypeUtils* aTypeUtils);
+  virtual ~AutoChildBase() = 0;
+
+  TypeUtils* mTypeUtils;
+  bool mSent;
+};
+
+class MOZ_STACK_CLASS AutoChildRequest final : public AutoChildBase
+{
+public:
+  explicit AutoChildRequest(TypeUtils* aTypeUtils);
+  ~AutoChildRequest();
+
+  void Add(InternalRequest* aRequest, BodyAction aBodyAction,
+           ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
+           ErrorResult& aRv);
+
+  const PCacheRequest& SendAsRequest();
+  const PCacheRequestOrVoid& SendAsRequestOrVoid();
+
+private:
+  PCacheRequestOrVoid mRequestOrVoid;
+};
+
+class MOZ_STACK_CLASS AutoChildRequestList final : public AutoChildBase
+{
+public:
+  AutoChildRequestList(TypeUtils* aTypeUtils, uint32_t aCapacity);
+  ~AutoChildRequestList();
+
+  void Add(InternalRequest* aRequest, BodyAction aBodyAction,
+           ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
+           ErrorResult& aRv);
+
+  const nsTArray<PCacheRequest>& SendAsRequestList();
+
+private:
+  // Allocates ~5k inline in the stack-only class
+  nsAutoTArray<PCacheRequest, 32> mRequestList;
+};
+
+class MOZ_STACK_CLASS AutoChildRequestResponse final : public AutoChildBase
+{
+public:
+  explicit AutoChildRequestResponse(TypeUtils* aTypeUtils);
+  ~AutoChildRequestResponse();
 
   void Add(InternalRequest* aRequest, BodyAction aBodyAction,
            ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
            ErrorResult& aRv);
-  void Add(InternalRequest* aRequest, BodyAction aBodyAction,
-           ReferrerAction aReferrerAction, SchemeAction aSchemeAction,
-           Response& aResponse, ErrorResult& aRv);
+  void Add(Response& aResponse, ErrorResult& aRv);
 
-  const CacheOpArgs& SendAsOpArgs();
+  const CacheRequestResponse& SendAsRequestResponse();
 
 private:
-  TypeUtils* mTypeUtils;
-  CacheOpArgs mOpArgs;
+  CacheRequestResponse mRequestResponse;
+};
+
+class MOZ_STACK_CLASS AutoParentBase
+{
+protected:
+  explicit AutoParentBase(mozilla::ipc::PBackgroundParent* aManager);
+  virtual ~AutoParentBase() = 0;
+
+  void SerializeReadStream(const nsID& aId, StreamList* aStreamList,
+                           PCacheReadStream* aReadStreamOut);
+
+  mozilla::ipc::PBackgroundParent* mManager;
+  CacheStreamControlParent* mStreamControl;
   bool mSent;
 };
 
-class MOZ_STACK_CLASS AutoParentOpResult final
+class MOZ_STACK_CLASS AutoParentRequestList final : public AutoParentBase
 {
 public:
-  AutoParentOpResult(mozilla::ipc::PBackgroundParent* aManager,
-                     const CacheOpResult& aOpResult);
-  ~AutoParentOpResult();
+  AutoParentRequestList(mozilla::ipc::PBackgroundParent* aManager,
+                        uint32_t aCapacity);
+  ~AutoParentRequestList();
 
-  void Add(CacheId aOpenedCacheId, Manager* aManager);
-  void Add(const SavedResponse& aSavedResponse, StreamList* aStreamList);
   void Add(const SavedRequest& aSavedRequest, StreamList* aStreamList);
 
-  const CacheOpResult& SendAsOpResult();
+  const nsTArray<PCacheRequest>& SendAsRequestList();
 
 private:
-  void SerializeResponseBody(const SavedResponse& aSavedResponse,
-                             StreamList* aStreamList,
-                             CacheResponse* aResponseOut);
+  // Allocates ~5k inline in the stack-only class
+  nsAutoTArray<PCacheRequest, 32> mRequestList;
+};
+
+class MOZ_STACK_CLASS AutoParentResponseList final : public AutoParentBase
+{
+public:
+  AutoParentResponseList(mozilla::ipc::PBackgroundParent* aManager,
+                         uint32_t aCapacity);
+  ~AutoParentResponseList();
+
+  void Add(const SavedResponse& aSavedResponse, StreamList* aStreamList);
+
+  const nsTArray<PCacheResponse>& SendAsResponseList();
 
-  void SerializeReadStream(const nsID& aId, StreamList* aStreamList,
-                           CacheReadStream* aReadStreamOut);
+private:
+  // Allocates ~4k inline in the stack-only class
+  nsAutoTArray<PCacheResponse, 32> mResponseList;
+};
 
-  mozilla::ipc::PBackgroundParent* mManager;
-  CacheOpResult mOpResult;
-  CacheStreamControlParent* mStreamControl;
-  bool mSent;
+class MOZ_STACK_CLASS AutoParentResponseOrVoid final : public AutoParentBase
+{
+public:
+  explicit AutoParentResponseOrVoid(mozilla::ipc::PBackgroundParent* aManager);
+  ~AutoParentResponseOrVoid();
+
+  void Add(const SavedResponse& aSavedResponse, StreamList* aStreamList);
+
+  const PCacheResponseOrVoid& SendAsResponseOrVoid();
+
+private:
+  PCacheResponseOrVoid mResponseOrVoid;
 };
 
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_cache_AutoUtils_h
--- a/dom/cache/Cache.cpp
+++ b/dom/cache/Cache.cpp
@@ -9,19 +9,19 @@
 #include "mozilla/dom/Headers.h"
 #include "mozilla/dom/InternalResponse.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/Response.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/dom/CacheBinding.h"
 #include "mozilla/dom/cache/AutoUtils.h"
 #include "mozilla/dom/cache/CacheChild.h"
-#include "mozilla/dom/cache/CacheOpChild.h"
 #include "mozilla/dom/cache/CachePushStreamChild.h"
 #include "mozilla/dom/cache/ReadStream.h"
+#include "mozilla/dom/cache/TypeUtils.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/unused.h"
 #include "nsIGlobalObject.h"
 #include "nsNetUtil.h"
 
 namespace {
 
@@ -74,17 +74,27 @@ namespace cache {
 
 using mozilla::ErrorResult;
 using mozilla::unused;
 using mozilla::dom::workers::GetCurrentThreadWorkerPrivate;
 using mozilla::dom::workers::WorkerPrivate;
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(mozilla::dom::cache::Cache);
 NS_IMPL_CYCLE_COLLECTING_RELEASE(mozilla::dom::cache::Cache);
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(mozilla::dom::cache::Cache, mGlobal);
+NS_IMPL_CYCLE_COLLECTION_CLASS(mozilla::dom::cache::Cache)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(mozilla::dom::cache::Cache)
+  tmp->DisconnectFromActor();
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal, mRequestPromises)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(mozilla::dom::cache::Cache)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal, mRequestPromises)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(mozilla::dom::cache::Cache)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Cache)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 Cache::Cache(nsIGlobalObject* aGlobal, CacheChild* aActor)
   : mGlobal(aGlobal)
@@ -96,199 +106,260 @@ Cache::Cache(nsIGlobalObject* aGlobal, C
 }
 
 already_AddRefed<Promise>
 Cache::Match(const RequestOrUSVString& aRequest,
              const CacheQueryOptions& aOptions, ErrorResult& aRv)
 {
   MOZ_ASSERT(mActor);
 
+  nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
+  if (!promise) {
+    return nullptr;
+  }
+
   nsRefPtr<InternalRequest> ir = ToInternalRequest(aRequest, IgnoreBody, aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
+  if (aRv.Failed()) {
     return nullptr;
   }
 
-  CacheQueryParams params;
-  ToCacheQueryParams(params, aOptions);
+  AutoChildRequest request(this);
 
-  AutoChildOpArgs args(this, CacheMatchArgs(CacheRequest(), params));
-
-  args.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
+  request.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
+  if (aRv.Failed()) {
     return nullptr;
   }
 
-  return ExecuteOp(args, aRv);
+  PCacheQueryParams params;
+  ToPCacheQueryParams(params, aOptions);
+
+  RequestId requestId = AddRequestPromise(promise, aRv);
+
+  unused << mActor->SendMatch(requestId, request.SendAsRequest(), params);
+
+  return promise.forget();
 }
 
 already_AddRefed<Promise>
 Cache::MatchAll(const Optional<RequestOrUSVString>& aRequest,
                 const CacheQueryOptions& aOptions, ErrorResult& aRv)
 {
   MOZ_ASSERT(mActor);
 
-  CacheQueryParams params;
-  ToCacheQueryParams(params, aOptions);
+  nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
+  if (!promise) {
+    return nullptr;
+  }
 
-  AutoChildOpArgs args(this, CacheMatchAllArgs(void_t(), params));
+  AutoChildRequest request(this);
 
   if (aRequest.WasPassed()) {
     nsRefPtr<InternalRequest> ir = ToInternalRequest(aRequest.Value(),
                                                      IgnoreBody, aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
 
-    args.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
+    request.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
   }
 
-  return ExecuteOp(args, aRv);
+  PCacheQueryParams params;
+  ToPCacheQueryParams(params, aOptions);
+
+  RequestId requestId = AddRequestPromise(promise, aRv);
+
+  unused << mActor->SendMatchAll(requestId, request.SendAsRequestOrVoid(),
+                                 params);
+
+  return promise.forget();
 }
 
 already_AddRefed<Promise>
 Cache::Add(const RequestOrUSVString& aRequest, ErrorResult& aRv)
 {
   MOZ_ASSERT(mActor);
 
   if (!IsValidPutRequestMethod(aRequest, aRv)) {
     return nullptr;
   }
 
+  nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
+  if (!promise) {
+    return nullptr;
+  }
+
   nsRefPtr<InternalRequest> ir = ToInternalRequest(aRequest, ReadBody, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  AutoChildOpArgs args(this, CacheAddAllArgs());
-
-  args.Add(ir, ReadBody, ExpandReferrer, NetworkErrorOnInvalidScheme, aRv);
+  AutoChildRequestList requests(this, 1);
+  requests.Add(ir, ReadBody, ExpandReferrer, NetworkErrorOnInvalidScheme, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  return ExecuteOp(args, aRv);
+  RequestId requestId = AddRequestPromise(promise, aRv);
+
+  unused << mActor->SendAddAll(requestId, requests.SendAsRequestList());
+
+  return promise.forget();
 }
 
 already_AddRefed<Promise>
 Cache::AddAll(const Sequence<OwningRequestOrUSVString>& aRequests,
               ErrorResult& aRv)
 {
   MOZ_ASSERT(mActor);
 
+  nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
+  if (!promise) {
+    return nullptr;
+  }
+
   // If there is no work to do, then resolve immediately
   if (aRequests.IsEmpty()) {
-    nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
-    if (!promise) {
-      return nullptr;
-    }
-
     promise->MaybeResolve(JS::UndefinedHandleValue);
     return promise.forget();
   }
 
-  AutoChildOpArgs args(this, CacheAddAllArgs());
+  AutoChildRequestList requests(this, aRequests.Length());
 
   for (uint32_t i = 0; i < aRequests.Length(); ++i) {
     if (!IsValidPutRequestMethod(aRequests[i], aRv)) {
       return nullptr;
     }
 
     nsRefPtr<InternalRequest> ir = ToInternalRequest(aRequests[i], ReadBody,
                                                      aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
 
-    args.Add(ir, ReadBody, ExpandReferrer, NetworkErrorOnInvalidScheme, aRv);
+    requests.Add(ir, ReadBody, ExpandReferrer, NetworkErrorOnInvalidScheme,
+                 aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
   }
 
-  return ExecuteOp(args, aRv);
+  RequestId requestId = AddRequestPromise(promise, aRv);
+
+  unused << mActor->SendAddAll(requestId, requests.SendAsRequestList());
+
+  return promise.forget();
 }
 
 already_AddRefed<Promise>
 Cache::Put(const RequestOrUSVString& aRequest, Response& aResponse,
            ErrorResult& aRv)
 {
   MOZ_ASSERT(mActor);
 
   if (!IsValidPutRequestMethod(aRequest, aRv)) {
     return nullptr;
   }
 
+  nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
+  if (!promise) {
+    return nullptr;
+  }
+
   nsRefPtr<InternalRequest> ir = ToInternalRequest(aRequest, ReadBody, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  AutoChildOpArgs args(this, CachePutAllArgs());
-
-  args.Add(ir, ReadBody, PassThroughReferrer, TypeErrorOnInvalidScheme,
-           aResponse, aRv);
+  AutoChildRequestResponse put(this);
+  put.Add(ir, ReadBody, PassThroughReferrer, TypeErrorOnInvalidScheme, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  return ExecuteOp(args, aRv);
+  put.Add(aResponse, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  RequestId requestId = AddRequestPromise(promise, aRv);
+
+  unused << mActor->SendPut(requestId, put.SendAsRequestResponse());
+
+  return promise.forget();
 }
 
 already_AddRefed<Promise>
 Cache::Delete(const RequestOrUSVString& aRequest,
               const CacheQueryOptions& aOptions, ErrorResult& aRv)
 {
   MOZ_ASSERT(mActor);
 
+  nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
+  if (!promise) {
+    return nullptr;
+  }
+
   nsRefPtr<InternalRequest> ir = ToInternalRequest(aRequest, IgnoreBody, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  CacheQueryParams params;
-  ToCacheQueryParams(params, aOptions);
-
-  AutoChildOpArgs args(this, CacheDeleteArgs(CacheRequest(), params));
-
-  args.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
+  AutoChildRequest request(this);
+  request.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  return ExecuteOp(args, aRv);
+  PCacheQueryParams params;
+  ToPCacheQueryParams(params, aOptions);
+
+  RequestId requestId = AddRequestPromise(promise, aRv);
+
+  unused << mActor->SendDelete(requestId, request.SendAsRequest(), params);
+
+  return promise.forget();
 }
 
 already_AddRefed<Promise>
 Cache::Keys(const Optional<RequestOrUSVString>& aRequest,
             const CacheQueryOptions& aOptions, ErrorResult& aRv)
 {
   MOZ_ASSERT(mActor);
 
-  CacheQueryParams params;
-  ToCacheQueryParams(params, aOptions);
+  nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
+  if (!promise) {
+    return nullptr;
+  }
 
-  AutoChildOpArgs args(this, CacheKeysArgs(void_t(), params));
+  AutoChildRequest request(this);
 
   if (aRequest.WasPassed()) {
     nsRefPtr<InternalRequest> ir = ToInternalRequest(aRequest.Value(),
                                                      IgnoreBody, aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
 
-    args.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
+    request.Add(ir, IgnoreBody, PassThroughReferrer, IgnoreInvalidScheme, aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
   }
 
-  return ExecuteOp(args, aRv);
+  PCacheQueryParams params;
+  ToPCacheQueryParams(params, aOptions);
+
+  RequestId requestId = AddRequestPromise(promise, aRv);
+
+  unused << mActor->SendKeys(requestId, request.SendAsRequestOrVoid(), params);
+
+  return promise.forget();
 }
 
 // static
 bool
 Cache::PrefEnabled(JSContext* aCx, JSObject* aObj)
 {
   using mozilla::dom::workers::WorkerPrivate;
   using mozilla::dom::workers::GetWorkerPrivateFromContext;
@@ -325,16 +396,129 @@ void
 Cache::DestroyInternal(CacheChild* aActor)
 {
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(mActor == aActor);
   mActor->ClearListener();
   mActor = nullptr;
 }
 
+void
+Cache::RecvMatchResponse(RequestId aRequestId, nsresult aRv,
+                         const PCacheResponseOrVoid& aResponse)
+{
+  // Convert the response immediately if its present.  This ensures that
+  // any stream actors are cleaned up, even if we error out below.
+  nsRefPtr<Response> response;
+  if (aResponse.type() == PCacheResponseOrVoid::TPCacheResponse) {
+    response = ToResponse(aResponse);
+  }
+
+  nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
+
+  if (NS_FAILED(aRv)) {
+    promise->MaybeReject(aRv);
+    return;
+  }
+
+  if (!response) {
+    promise->MaybeResolve(JS::UndefinedHandleValue);
+    return;
+  }
+
+  promise->MaybeResolve(response);
+}
+
+void
+Cache::RecvMatchAllResponse(RequestId aRequestId, nsresult aRv,
+                            const nsTArray<PCacheResponse>& aResponses)
+{
+  // Convert responses immediately.  This ensures that any stream actors are
+  // cleaned up, even if we error out below.
+  nsAutoTArray<nsRefPtr<Response>, 256> responses;
+  responses.SetCapacity(aResponses.Length());
+
+  for (uint32_t i = 0; i < aResponses.Length(); ++i) {
+    nsRefPtr<Response> response = ToResponse(aResponses[i]);
+    responses.AppendElement(response.forget());
+  }
+
+  nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
+
+  if (NS_FAILED(aRv)) {
+    promise->MaybeReject(aRv);
+    return;
+  }
+
+  promise->MaybeResolve(responses);
+}
+
+void
+Cache::RecvAddAllResponse(RequestId aRequestId, nsresult aRv)
+{
+  nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
+
+  if (NS_FAILED(aRv)) {
+    promise->MaybeReject(aRv);
+    return;
+  }
+
+  promise->MaybeResolve(JS::UndefinedHandleValue);
+}
+
+void
+Cache::RecvPutResponse(RequestId aRequestId, nsresult aRv)
+{
+  nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
+
+  if (NS_FAILED(aRv)) {
+    promise->MaybeReject(aRv);
+    return;
+  }
+
+  promise->MaybeResolve(JS::UndefinedHandleValue);
+}
+
+void
+Cache::RecvDeleteResponse(RequestId aRequestId, nsresult aRv, bool aSuccess)
+{
+  nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
+
+  if (NS_FAILED(aRv)) {
+    promise->MaybeReject(aRv);
+    return;
+  }
+
+  promise->MaybeResolve(aSuccess);
+}
+
+void
+Cache::RecvKeysResponse(RequestId aRequestId, nsresult aRv,
+                        const nsTArray<PCacheRequest>& aRequests)
+{
+  // Convert requests immediately.  This ensures that any stream actors are
+  // cleaned up, even if we error out below.
+  nsAutoTArray<nsRefPtr<Request>, 256> requests;
+  requests.SetCapacity(aRequests.Length());
+
+  for (uint32_t i = 0; i < aRequests.Length(); ++i) {
+    nsRefPtr<Request> request = ToRequest(aRequests[i]);
+    requests.AppendElement(request.forget());
+  }
+
+  nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
+
+  if (NS_FAILED(aRv)) {
+    promise->MaybeReject(aRv);
+    return;
+  }
+
+  promise->MaybeResolve(requests);
+}
+
 nsIGlobalObject*
 Cache::GetGlobalObject() const
 {
   return mGlobal;
 }
 
 #ifdef DEBUG
 void
@@ -351,37 +535,82 @@ Cache::CreatePushStream(nsIAsyncInputStr
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(aStream);
   auto actor = mActor->SendPCachePushStreamConstructor(
     new CachePushStreamChild(mActor->GetFeature(), aStream));
   MOZ_ASSERT(actor);
   return static_cast<CachePushStreamChild*>(actor);
 }
 
+void
+Cache::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
+{
+  // Do nothing.  The Promise will automatically drop the ref to us after
+  // calling the callback.  This is what we want as we only registered in order
+  // to be held alive via the Promise handle.
+}
+
+void
+Cache::RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
+{
+  // Do nothing.  The Promise will automatically drop the ref to us after
+  // calling the callback.  This is what we want as we only registered in order
+  // to be held alive via the Promise handle.
+}
+
 Cache::~Cache()
 {
-  NS_ASSERT_OWNINGTHREAD(Cache);
+  DisconnectFromActor();
+}
+
+void
+Cache::DisconnectFromActor()
+{
   if (mActor) {
     mActor->StartDestroy();
     // DestroyInternal() is called synchronously by StartDestroy().  So we
     // should have already cleared the mActor.
     MOZ_ASSERT(!mActor);
   }
 }
 
-already_AddRefed<Promise>
-Cache::ExecuteOp(AutoChildOpArgs& aOpArgs, ErrorResult& aRv)
+RequestId
+Cache::AddRequestPromise(Promise* aPromise, ErrorResult& aRv)
 {
-  nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
-  if (!promise) {
-    return nullptr;
+  MOZ_ASSERT(aPromise);
+  MOZ_ASSERT(!mRequestPromises.Contains(aPromise));
+
+  // Register ourself as a promise handler so that the promise will hold us
+  // alive.  This allows the client code to drop the ref to the Cache
+  // object and just keep their promise.  This is fairly common in promise
+  // chaining code.
+  aPromise->AppendNativeHandler(this);
+
+  mRequestPromises.AppendElement(aPromise);
+
+  // (Ab)use the promise pointer as our request ID.  This is a fast, thread-safe
+  // way to get a unique ID for the promise to be resolved later.
+  return reinterpret_cast<RequestId>(aPromise);
+}
+
+already_AddRefed<Promise>
+Cache::RemoveRequestPromise(RequestId aRequestId)
+{
+  MOZ_ASSERT(aRequestId != INVALID_REQUEST_ID);
+
+  for (uint32_t i = 0; i < mRequestPromises.Length(); ++i) {
+    nsRefPtr<Promise>& promise = mRequestPromises.ElementAt(i);
+    // To be safe, only cast promise pointers to our integer RequestId
+    // type and never cast an integer to a pointer.
+    if (aRequestId == reinterpret_cast<RequestId>(promise.get())) {
+      nsRefPtr<Promise> ref;
+      ref.swap(promise);
+      mRequestPromises.RemoveElementAt(i);
+      return ref.forget();
+    }
   }
-
-  unused << mActor->SendPCacheOpConstructor(
-    new CacheOpChild(mActor->GetFeature(), mGlobal, this, promise),
-    aOpArgs.SendAsOpArgs());
-
-  return promise.forget();
+  MOZ_ASSERT_UNREACHABLE("Received response without a matching promise!");
+  return nullptr;
 }
 
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
--- a/dom/cache/Cache.h
+++ b/dom/cache/Cache.h
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 mozilla_dom_cache_Cache_h
 #define mozilla_dom_cache_Cache_h
 
+#include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/dom/cache/Types.h"
 #include "mozilla/dom/cache/TypeUtils.h"
 #include "nsCOMPtr.h"
 #include "nsISupportsImpl.h"
 #include "nsString.h"
 #include "nsWrapperCache.h"
 
 class nsIGlobalObject;
@@ -27,20 +28,22 @@ class Promise;
 struct CacheQueryOptions;
 class RequestOrUSVString;
 class Response;
 template<typename T> class Optional;
 template<typename T> class Sequence;
 
 namespace cache {
 
-class AutoChildOpArgs;
 class CacheChild;
+class PCacheRequest;
+class PCacheResponse;
+class PCacheResponseOrVoid;
 
-class Cache final : public nsISupports
+class Cache final : public PromiseNativeHandler
                   , public nsWrapperCache
                   , public TypeUtils
 {
 public:
   Cache(nsIGlobalObject* aGlobal, CacheChild* aActor);
 
   // webidl interface methods
   already_AddRefed<Promise>
@@ -68,35 +71,60 @@ public:
   static bool PrefEnabled(JSContext* aCx, JSObject* aObj);
 
   nsISupports* GetParentObject() const;
   virtual JSObject* WrapObject(JSContext* aContext, JS::Handle<JSObject*> aGivenProto) override;
 
   // Called when CacheChild actor is being destroyed
   void DestroyInternal(CacheChild* aActor);
 
+  // methods forwarded from CacheChild
+  void RecvMatchResponse(RequestId aRequestId, nsresult aRv,
+                         const PCacheResponseOrVoid& aResponse);
+  void RecvMatchAllResponse(RequestId aRequestId, nsresult aRv,
+                            const nsTArray<PCacheResponse>& aResponses);
+  void RecvAddAllResponse(RequestId aRequestId, nsresult aRv);
+  void RecvPutResponse(RequestId aRequestId, nsresult aRv);
+
+  void RecvDeleteResponse(RequestId aRequestId, nsresult aRv,
+                          bool aSuccess);
+  void RecvKeysResponse(RequestId aRequestId, nsresult aRv,
+                        const nsTArray<PCacheRequest>& aRequests);
+
   // TypeUtils methods
   virtual nsIGlobalObject*
   GetGlobalObject() const override;
 
 #ifdef DEBUG
   virtual void AssertOwningThread() const override;
 #endif
 
   virtual CachePushStreamChild*
   CreatePushStream(nsIAsyncInputStream* aStream) override;
 
+  // PromiseNativeHandler methods
+  virtual void
+  ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
+
+  virtual void
+  RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
+
 private:
   ~Cache();
 
-  already_AddRefed<Promise>
-  ExecuteOp(AutoChildOpArgs& aOpArgs, ErrorResult& aRv);
+  // Called when we're destroyed or CCed.
+  void DisconnectFromActor();
+
+  // TODO: Replace with actor-per-request model during refactor (bug 1110485)
+  RequestId AddRequestPromise(Promise* aPromise, ErrorResult& aRv);
+  already_AddRefed<Promise> RemoveRequestPromise(RequestId aRequestId);
 
   nsCOMPtr<nsIGlobalObject> mGlobal;
   CacheChild* mActor;
+  nsTArray<nsRefPtr<Promise>> mRequestPromises;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Cache)
 };
 
 } // namespace cache
 } // namespace dom
--- a/dom/cache/CacheChild.cpp
+++ b/dom/cache/CacheChild.cpp
@@ -4,17 +4,16 @@
  * 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 "mozilla/dom/cache/CacheChild.h"
 
 #include "mozilla/unused.h"
 #include "mozilla/dom/cache/ActorUtils.h"
 #include "mozilla/dom/cache/Cache.h"
-#include "mozilla/dom/cache/PCacheOpChild.h"
 #include "mozilla/dom/cache/PCachePushStreamChild.h"
 #include "mozilla/dom/cache/StreamUtils.h"
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 // Declared in ActorUtils.h
@@ -68,18 +67,16 @@ CacheChild::StartDestroy()
 
   // StartDestroy() can get called from either Cache or the Feature.
   // Theoretically we can get double called if the right race happens.  Handle
   // that by just ignoring the second StartDestroy() call.
   if (!listener) {
     return;
   }
 
-  // TODO: only destroy if there are no ops or push streams still running
-
   listener->DestroyInternal(this);
 
   // Cache listener should call ClearListener() in DestroyInternal()
   MOZ_ASSERT(!mListener);
 
   // Start actor destruction from parent process
   unused << SendTeardown();
 }
@@ -93,39 +90,113 @@ CacheChild::ActorDestroy(ActorDestroyRea
     listener->DestroyInternal(this);
     // Cache listener should call ClearListener() in DestroyInternal()
     MOZ_ASSERT(!mListener);
   }
 
   RemoveFeature();
 }
 
-PCacheOpChild*
-CacheChild::AllocPCacheOpChild(const CacheOpArgs& aOpArgs)
-{
-  MOZ_CRASH("CacheOpChild should be manually constructed.");
-  return nullptr;
-}
-
-bool
-CacheChild::DeallocPCacheOpChild(PCacheOpChild* aActor)
-{
-  delete aActor;
-  return true;
-}
-
 PCachePushStreamChild*
 CacheChild::AllocPCachePushStreamChild()
 {
   MOZ_CRASH("CachePushStreamChild should be manually constructed.");
   return nullptr;
 }
 
 bool
 CacheChild::DeallocPCachePushStreamChild(PCachePushStreamChild* aActor)
 {
   delete aActor;
   return true;
 }
 
+bool
+CacheChild::RecvMatchResponse(const RequestId& requestId, const nsresult& aRv,
+                              const PCacheResponseOrVoid& aResponse)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheChild);
+
+  AddFeatureToStreamChild(aResponse, GetFeature());
+
+  nsRefPtr<Cache> listener = mListener;
+  if (!listener) {
+    StartDestroyStreamChild(aResponse);
+    return true;
+  }
+
+  listener->RecvMatchResponse(requestId, aRv, aResponse);
+  return true;
+}
+
+bool
+CacheChild::RecvMatchAllResponse(const RequestId& requestId, const nsresult& aRv,
+                                 nsTArray<PCacheResponse>&& aResponses)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheChild);
+
+  AddFeatureToStreamChild(aResponses, GetFeature());
+
+  nsRefPtr<Cache> listener = mListener;
+  if (!listener) {
+    StartDestroyStreamChild(aResponses);
+    return true;
+  }
+
+  listener->RecvMatchAllResponse(requestId, aRv, aResponses);
+  return true;
+}
+
+bool
+CacheChild::RecvAddAllResponse(const RequestId& requestId, const nsresult& aRv)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheChild);
+  nsRefPtr<Cache> listener = mListener;
+  if (listener) {
+    listener->RecvAddAllResponse(requestId, aRv);
+  }
+  return true;
+}
+
+bool
+CacheChild::RecvPutResponse(const RequestId& aRequestId, const nsresult& aRv)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheChild);
+  nsRefPtr<Cache> listener = mListener;
+  if (listener) {
+    listener->RecvPutResponse(aRequestId, aRv);
+  }
+  return true;
+}
+
+bool
+CacheChild::RecvDeleteResponse(const RequestId& requestId, const nsresult& aRv,
+                               const bool& result)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheChild);
+  nsRefPtr<Cache> listener = mListener;
+  if (listener) {
+    listener->RecvDeleteResponse(requestId, aRv, result);
+  }
+  return true;
+}
+
+bool
+CacheChild::RecvKeysResponse(const RequestId& requestId, const nsresult& aRv,
+                             nsTArray<PCacheRequest>&& aRequests)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheChild);
+
+  AddFeatureToStreamChild(aRequests, GetFeature());
+
+  nsRefPtr<Cache> listener = mListener;
+  if (!listener) {
+    StartDestroyStreamChild(aRequests);
+    return true;
+  }
+
+  listener->RecvKeysResponse(requestId, aRv, aRequests);
+  return true;
+}
+
 } // namespace cache
 } // namespace dom
 } // namesapce mozilla
--- a/dom/cache/CacheChild.h
+++ b/dom/cache/CacheChild.h
@@ -36,28 +36,41 @@ public:
   // actor destruction asynchronously from the parent-side.
   virtual void StartDestroy() override;
 
 private:
   // PCacheChild methods
   virtual void
   ActorDestroy(ActorDestroyReason aReason) override;
 
-  virtual PCacheOpChild*
-  AllocPCacheOpChild(const CacheOpArgs& aOpArgs) override;
-
-  virtual bool
-  DeallocPCacheOpChild(PCacheOpChild* aActor) override;
-
   virtual PCachePushStreamChild*
   AllocPCachePushStreamChild() override;
 
   virtual bool
   DeallocPCachePushStreamChild(PCachePushStreamChild* aActor) override;
 
+  virtual bool
+  RecvMatchResponse(const RequestId& requestId, const nsresult& aRv,
+                    const PCacheResponseOrVoid& aResponse) override;
+  virtual bool
+  RecvMatchAllResponse(const RequestId& requestId, const nsresult& aRv,
+                       nsTArray<PCacheResponse>&& responses) override;
+  virtual bool
+  RecvAddAllResponse(const RequestId& requestId,
+                     const nsresult& aRv) override;
+  virtual bool
+  RecvPutResponse(const RequestId& aRequestId,
+                  const nsresult& aRv) override;
+  virtual bool
+  RecvDeleteResponse(const RequestId& requestId, const nsresult& aRv,
+                     const bool& result) override;
+  virtual bool
+  RecvKeysResponse(const RequestId& requestId, const nsresult& aRv,
+                   nsTArray<PCacheRequest>&& requests) override;
+
   // Use a weak ref so actor does not hold DOM object alive past content use.
   // The Cache object must call ClearListener() to null this before its
   // destroyed.
   Cache* MOZ_NON_OWNING_REF mListener;
 
   NS_DECL_OWNINGTHREAD
 };
 
new file mode 100644
--- /dev/null
+++ b/dom/cache/CacheInitData.ipdlh
@@ -0,0 +1,24 @@
+/* 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 PBackgroundSharedTypes;
+
+using mozilla::dom::cache::Namespace from "mozilla/dom/cache/Types.h";
+
+namespace mozilla {
+namespace dom {
+namespace cache {
+
+// Data needed to initialize a CacheStorage or Cache backend.  Don't put
+// this with the other types in PCacheTypes.ipdlh since we want to import
+// it into PBackground.ipdl.
+struct CacheInitData
+{
+  Namespace namespaceEnum;
+  PrincipalInfo principalInfo;
+};
+
+} // namespace cache
+} // namespace dom
+} // namespace mozilla
deleted file mode 100644
--- a/dom/cache/CacheOpChild.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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 "mozilla/dom/cache/CacheOpChild.h"
-
-#include "mozilla/dom/Promise.h"
-#include "mozilla/dom/Request.h"
-#include "mozilla/dom/Response.h"
-#include "mozilla/dom/cache/Cache.h"
-#include "mozilla/dom/cache/CacheChild.h"
-
-namespace mozilla {
-namespace dom {
-namespace cache {
-
-CacheOpChild::CacheOpChild(Feature* aFeature, nsIGlobalObject* aGlobal,
-                           nsISupports* aParent, Promise* aPromise)
-  : mGlobal(aGlobal)
-  , mParent(aParent)
-  , mPromise(aPromise)
-{
-  MOZ_ASSERT(mGlobal);
-  MOZ_ASSERT(mParent);
-  MOZ_ASSERT(mPromise);
-
-  MOZ_ASSERT_IF(!NS_IsMainThread(), aFeature);
-  SetFeature(aFeature);
-}
-
-CacheOpChild::~CacheOpChild()
-{
-  NS_ASSERT_OWNINGTHREAD(CacheOpChild);
-  MOZ_ASSERT(!mPromise);
-}
-
-void
-CacheOpChild::ActorDestroy(ActorDestroyReason aReason)
-{
-  NS_ASSERT_OWNINGTHREAD(CacheOpChild);
-
-  // If the actor was terminated for some unknown reason, then indicate the
-  // operation is dead.
-  if (mPromise) {
-    mPromise->MaybeReject(NS_ERROR_FAILURE);
-    mPromise = nullptr;
-  }
-
-  RemoveFeature();
-}
-
-bool
-CacheOpChild::Recv__delete__(const nsresult& aStatus,
-                             const CacheOpResult& aResult)
-{
-  NS_ASSERT_OWNINGTHREAD(CacheOpChild);
-
-  if (NS_FAILED(aStatus)) {
-    mPromise->MaybeReject(aStatus);
-    mPromise = nullptr;
-    return true;
-  }
-
-  switch (aResult.type()) {
-    case CacheOpResult::TCacheMatchResult:
-    {
-      HandleResponse(aResult.get_CacheMatchResult().responseOrVoid());
-      break;
-    }
-    case CacheOpResult::TCacheMatchAllResult:
-    {
-      HandleResponseList(aResult.get_CacheMatchAllResult().responseList());
-      break;
-    }
-    case CacheOpResult::TCacheAddAllResult:
-    case CacheOpResult::TCachePutAllResult:
-    {
-      mPromise->MaybeResolve(JS::UndefinedHandleValue);
-      break;
-    }
-    case CacheOpResult::TCacheDeleteResult:
-    {
-      mPromise->MaybeResolve(aResult.get_CacheDeleteResult().success());
-      break;
-    }
-    case CacheOpResult::TCacheKeysResult:
-    {
-      HandleRequestList(aResult.get_CacheKeysResult().requestList());
-      break;
-    }
-    case CacheOpResult::TStorageMatchResult:
-    {
-      HandleResponse(aResult.get_StorageMatchResult().responseOrVoid());
-      break;
-    }
-    case CacheOpResult::TStorageHasResult:
-    {
-      mPromise->MaybeResolve(aResult.get_StorageHasResult().success());
-      break;
-    }
-    case CacheOpResult::TStorageOpenResult:
-    {
-      auto actor = static_cast<CacheChild*>(
-        aResult.get_StorageOpenResult().actorChild());
-      actor->SetFeature(GetFeature());
-      nsRefPtr<Cache> cache = new Cache(mGlobal, actor);
-      mPromise->MaybeResolve(cache);
-      break;
-    }
-    case CacheOpResult::TStorageDeleteResult:
-    {
-      mPromise->MaybeResolve(aResult.get_StorageDeleteResult().success());
-      break;
-    }
-    case CacheOpResult::TStorageKeysResult:
-    {
-      mPromise->MaybeResolve(aResult.get_StorageKeysResult().keyList());
-      break;
-    }
-    default:
-      MOZ_CRASH("Unknown Cache op result type!");
-  }
-
-  mPromise = nullptr;
-
-  return true;
-}
-
-void
-CacheOpChild::StartDestroy()
-{
-  NS_ASSERT_OWNINGTHREAD(CacheOpChild);
-
-  // Do not cancel on-going operations when Feature calls this.  Instead, keep
-  // the Worker alive until we are done.
-}
-
-nsIGlobalObject*
-CacheOpChild::GetGlobalObject() const
-{
-  return mGlobal;
-}
-
-#ifdef DEBUG
-void
-CacheOpChild::AssertOwningThread() const
-{
-  NS_ASSERT_OWNINGTHREAD(CacheOpChild);
-}
-#endif
-
-CachePushStreamChild*
-CacheOpChild::CreatePushStream(nsIAsyncInputStream* aStream)
-{
-  MOZ_CRASH("CacheOpChild should never create a push stream actor!");
-}
-
-void
-CacheOpChild::HandleResponse(const CacheResponseOrVoid& aResponseOrVoid)
-{
-  nsRefPtr<Response> response;
-  if (aResponseOrVoid.type() == CacheResponseOrVoid::TCacheResponse) {
-    response = ToResponse(aResponseOrVoid);
-  }
-
-  if (!response) {
-    mPromise->MaybeResolve(JS::UndefinedHandleValue);
-    return;
-  }
-
-  mPromise->MaybeResolve(response);
-}
-
-void
-CacheOpChild::HandleResponseList(const nsTArray<CacheResponse>& aResponseList)
-{
-  nsAutoTArray<nsRefPtr<Response>, 256> responses;
-  responses.SetCapacity(aResponseList.Length());
-
-  for (uint32_t i = 0; i < aResponseList.Length(); ++i) {
-    responses.AppendElement(ToResponse(aResponseList[i]));
-  }
-
-  mPromise->MaybeResolve(responses);
-}
-
-void
-CacheOpChild::HandleRequestList(const nsTArray<CacheRequest>& aRequestList)
-{
-  nsAutoTArray<nsRefPtr<Request>, 256> requests;
-  requests.SetCapacity(aRequestList.Length());
-
-  for (uint32_t i = 0; i < aRequestList.Length(); ++i) {
-    requests.AppendElement(ToRequest(aRequestList[i]));
-  }
-
-  mPromise->MaybeResolve(requests);
-}
-
-} // namespace cache
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/cache/CacheOpChild.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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 mozilla_dom_cache_CacheOpChild_h
-#define mozilla_dom_cache_CacheOpChild_h
-
-#include "mozilla/dom/cache/ActorChild.h"
-#include "mozilla/dom/cache/PCacheOpChild.h"
-#include "mozilla/dom/cache/TypeUtils.h"
-#include "nsRefPtr.h"
-
-class nsIGlobalObject;
-
-namespace mozilla {
-namespace dom {
-
-class Promise;
-
-namespace cache {
-
-class CacheOpChild final : public PCacheOpChild
-                         , public ActorChild
-                         , public TypeUtils
-{
-public:
-  CacheOpChild(Feature* aFeature, nsIGlobalObject* aGlobal,
-               nsISupports* aParent, Promise* aPromise);
-  ~CacheOpChild();
-
-private:
-  // PCacheOpChild methods
-  virtual void
-  ActorDestroy(ActorDestroyReason aReason) override;
-
-  virtual bool
-  Recv__delete__(const nsresult& aStatus, const CacheOpResult& aResult) override;
-
-  // ActorChild methods
-  virtual void
-  StartDestroy() override;
-
-  // TypeUtils methods
-  virtual nsIGlobalObject*
-  GetGlobalObject() const override;
-
-#ifdef DEBUG
-  virtual void
-  AssertOwningThread() const override;
-#endif
-
-  virtual CachePushStreamChild*
-  CreatePushStream(nsIAsyncInputStream* aStream) override;
-
-  // Utility methods
-  void
-  HandleResponse(const CacheResponseOrVoid& aResponseOrVoid);
-
-  void
-  HandleResponseList(const nsTArray<CacheResponse>& aResponseList);
-
-  void
-  HandleRequestList(const nsTArray<CacheRequest>& aRequestList);
-
-  nsCOMPtr<nsIGlobalObject> mGlobal;
-  nsCOMPtr<nsISupports> mParent;
-  nsRefPtr<Promise> mPromise;
-
-  NS_DECL_OWNINGTHREAD
-};
-
-} // namespace cache
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_cache_CacheOpChild_h
deleted file mode 100644
--- a/dom/cache/CacheOpParent.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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 "mozilla/dom/cache/CacheOpParent.h"
-
-#include "mozilla/unused.h"
-#include "mozilla/dom/cache/AutoUtils.h"
-#include "mozilla/dom/cache/CachePushStreamParent.h"
-#include "mozilla/dom/cache/ReadStream.h"
-#include "mozilla/dom/cache/SavedTypes.h"
-#include "mozilla/ipc/FileDescriptorSetParent.h"
-#include "mozilla/ipc/InputStreamUtils.h"
-
-namespace mozilla {
-namespace dom {
-namespace cache {
-
-using mozilla::ipc::FileDescriptorSetParent;
-using mozilla::ipc::PBackgroundParent;
-
-CacheOpParent::CacheOpParent(PBackgroundParent* aIpcManager, CacheId aCacheId,
-                             const CacheOpArgs& aOpArgs)
-  : mIpcManager(aIpcManager)
-  , mCacheId(aCacheId)
-  , mNamespace(INVALID_NAMESPACE)
-  , mOpArgs(aOpArgs)
-{
-  MOZ_ASSERT(mIpcManager);
-}
-
-CacheOpParent::CacheOpParent(PBackgroundParent* aIpcManager,
-                             Namespace aNamespace, const CacheOpArgs& aOpArgs)
-  : mIpcManager(aIpcManager)
-  , mCacheId(INVALID_CACHE_ID)
-  , mNamespace(aNamespace)
-  , mOpArgs(aOpArgs)
-{
-  MOZ_ASSERT(mIpcManager);
-}
-
-CacheOpParent::~CacheOpParent()
-{
-  NS_ASSERT_OWNINGTHREAD(CacheOpParent);
-}
-
-void
-CacheOpParent::Execute(ManagerId* aManagerId)
-{
-  NS_ASSERT_OWNINGTHREAD(CacheOpParent);
-  MOZ_ASSERT(!mManager);
-  MOZ_ASSERT(!mVerifier);
-
-  nsRefPtr<Manager> manager;
-  nsresult rv = Manager::GetOrCreate(aManagerId, getter_AddRefs(manager));
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    unused << Send__delete__(this, rv, void_t());
-    return;
-  }
-
-  Execute(manager);
-}
-
-void
-CacheOpParent::Execute(Manager* aManager)
-{
-  NS_ASSERT_OWNINGTHREAD(CacheOpParent);
-  MOZ_ASSERT(!mManager);
-  MOZ_ASSERT(!mVerifier);
-
-  mManager = aManager;
-
-  // Handle add/addAll op with a FetchPut object
-  if (mOpArgs.type() == CacheOpArgs::TCacheAddAllArgs) {
-    MOZ_ASSERT(mCacheId != INVALID_CACHE_ID);
-
-    const CacheAddAllArgs& args = mOpArgs.get_CacheAddAllArgs();
-    const nsTArray<CacheRequest>& list = args.requestList();
-
-    nsAutoTArray<nsCOMPtr<nsIInputStream>, 256> requestStreamList;
-    for (uint32_t i = 0; i < list.Length(); ++i) {
-      requestStreamList.AppendElement(DeserializeCacheStream(list[i].body()));
-    }
-
-    nsRefPtr<FetchPut> fetchPut;
-    nsresult rv = FetchPut::Create(this, mManager, mCacheId, list,
-                                   requestStreamList, getter_AddRefs(fetchPut));
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      OnOpComplete(rv, CacheAddAllResult());
-      return;
-    }
-
-    mFetchPutList.AppendElement(fetchPut.forget());
-    return;
-  }
-
-  // Handle put op
-  if (mOpArgs.type() == CacheOpArgs::TCachePutAllArgs) {
-    MOZ_ASSERT(mCacheId != INVALID_CACHE_ID);
-
-    const CachePutAllArgs& args = mOpArgs.get_CachePutAllArgs();
-    const nsTArray<CacheRequestResponse>& list = args.requestResponseList();
-
-    nsAutoTArray<nsCOMPtr<nsIInputStream>, 256> requestStreamList;
-    nsAutoTArray<nsCOMPtr<nsIInputStream>, 256> responseStreamList;
-
-    for (uint32_t i = 0; i < list.Length(); ++i) {
-      requestStreamList.AppendElement(
-        DeserializeCacheStream(list[i].request().body()));
-      responseStreamList.AppendElement(
-        DeserializeCacheStream(list[i].response().body()));
-    }
-
-    mManager->ExecutePutAll(this, mCacheId, args.requestResponseList(),
-                            requestStreamList, responseStreamList);
-    return;
-  }
-
-  // Handle all other cache ops
-  if (mCacheId != INVALID_CACHE_ID) {
-    MOZ_ASSERT(mNamespace == INVALID_NAMESPACE);
-    mManager->ExecuteCacheOp(this, mCacheId, mOpArgs);
-    return;
-  }
-
-  // Handle all storage ops
-  MOZ_ASSERT(mNamespace != INVALID_NAMESPACE);
-  mManager->ExecuteStorageOp(this, mNamespace, mOpArgs);
-}
-
-void
-CacheOpParent::WaitForVerification(PrincipalVerifier* aVerifier)
-{
-  NS_ASSERT_OWNINGTHREAD(CacheOpParent);
-  MOZ_ASSERT(!mManager);
-  MOZ_ASSERT(!mVerifier);
-
-  mVerifier = aVerifier;
-  mVerifier->AddListener(this);
-}
-
-void
-CacheOpParent::ActorDestroy(ActorDestroyReason aReason)
-{
-  NS_ASSERT_OWNINGTHREAD(CacheOpParent);
-
-  if (mVerifier) {
-    mVerifier->RemoveListener(this);
-    mVerifier = nullptr;
-  }
-
-  for (uint32_t i = 0; i < mFetchPutList.Length(); ++i) {
-    mFetchPutList[i]->ClearListener();
-  }
-  mFetchPutList.Clear();
-
-  if (mManager) {
-    mManager->RemoveListener(this);
-    mManager = nullptr;
-  }
-
-  mIpcManager = nullptr;
-}
-
-void
-CacheOpParent::OnPrincipalVerified(nsresult aRv, ManagerId* aManagerId)
-{
-  NS_ASSERT_OWNINGTHREAD(CacheOpParent);
-
-  mVerifier->RemoveListener(this);
-  mVerifier = nullptr;
-
-  if (NS_WARN_IF(NS_FAILED(aRv))) {
-    unused << Send__delete__(this, aRv, void_t());
-    return;
-  }
-
-  Execute(aManagerId);
-}
-
-void
-CacheOpParent::OnOpComplete(nsresult aRv, const CacheOpResult& aResult,
-                            CacheId aOpenedCacheId,
-                            const nsTArray<SavedResponse>& aSavedResponseList,
-                            const nsTArray<SavedRequest>& aSavedRequestList,
-                            StreamList* aStreamList)
-{
-  NS_ASSERT_OWNINGTHREAD(CacheOpParent);
-  MOZ_ASSERT(mIpcManager);
-  MOZ_ASSERT(mManager);
-
-  // The result must contain the appropriate type at this point.  It may
-  // or may not contain the additional result data yet.  For types that
-  // do not need special processing, it should already be set.  If the
-  // result requires actor-specific operations, then we do that below.
-  // If the type and data types don't match, then we will trigger an
-  // assertion in AutoParentOpResult::Add().
-  AutoParentOpResult result(mIpcManager, aResult);
-
-  if (NS_FAILED(aRv)) {
-    unused << Send__delete__(this, aRv, result.SendAsOpResult());
-    return;
-  }
-
-  if (aOpenedCacheId != INVALID_CACHE_ID) {
-    result.Add(aOpenedCacheId, mManager);
-  }
-
-  for (uint32_t i = 0; i < aSavedResponseList.Length(); ++i) {
-    result.Add(aSavedResponseList[i], aStreamList);
-  }
-
-  for (uint32_t i = 0; i < aSavedRequestList.Length(); ++i) {
-    result.Add(aSavedRequestList[i], aStreamList);
-  }
-
-  unused << Send__delete__(this, aRv, result.SendAsOpResult());
-}
-
-void
-CacheOpParent::OnFetchPut(FetchPut* aFetchPut, nsresult aRv)
-{
-  NS_ASSERT_OWNINGTHREAD(CacheOpParent);
-  MOZ_ASSERT(aFetchPut);
-
-  aFetchPut->ClearListener();
-  MOZ_ALWAYS_TRUE(mFetchPutList.RemoveElement(aFetchPut));
-
-  OnOpComplete(aRv, CacheAddAllResult());
-}
-
-already_AddRefed<nsIInputStream>
-CacheOpParent::DeserializeCacheStream(const CacheReadStreamOrVoid& aStreamOrVoid)
-{
-  if (aStreamOrVoid.type() == CacheReadStreamOrVoid::Tvoid_t) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsIInputStream> stream;
-  const CacheReadStream& readStream = aStreamOrVoid.get_CacheReadStream();
-
-  // Option 1: A push stream actor was sent for nsPipe data
-  if (readStream.pushStreamParent()) {
-    MOZ_ASSERT(!readStream.controlParent());
-    CachePushStreamParent* pushStream =
-      static_cast<CachePushStreamParent*>(readStream.pushStreamParent());
-    stream = pushStream->TakeReader();
-    MOZ_ASSERT(stream);
-    return stream.forget();
-  }
-
-  // Option 2: One of our own ReadStreams was passed back to us with a stream
-  //           control actor.
-  stream = ReadStream::Create(readStream);
-  if (stream) {
-    return stream.forget();
-  }
-
-  // Option 3: A stream was serialized using normal methods.
-  nsAutoTArray<FileDescriptor, 4> fds;
-  if (readStream.fds().type() ==
-      OptionalFileDescriptorSet::TPFileDescriptorSetChild) {
-
-    FileDescriptorSetParent* fdSetActor =
-      static_cast<FileDescriptorSetParent*>(readStream.fds().get_PFileDescriptorSetParent());
-    MOZ_ASSERT(fdSetActor);
-
-    fdSetActor->ForgetFileDescriptors(fds);
-    MOZ_ASSERT(!fds.IsEmpty());
-
-    if (!fdSetActor->Send__delete__(fdSetActor)) {
-      // child process is gone, warn and allow actor to clean up normally
-      NS_WARNING("Cache failed to delete fd set actor.");
-    }
-  }
-
-  return DeserializeInputStream(readStream.params(), fds);
-}
-
-} // namespace cache
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/cache/CacheOpParent.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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 mozilla_dom_cache_CacheOpParent_h
-#define mozilla_dom_cache_CacheOpParent_h
-
-#include "mozilla/dom/cache/FetchPut.h"
-#include "mozilla/dom/cache/Manager.h"
-#include "mozilla/dom/cache/PCacheOpParent.h"
-#include "mozilla/dom/cache/PrincipalVerifier.h"
-#include "nsTArray.h"
-
-namespace mozilla {
-namespace ipc {
-class PBackgroundParent;
-}
-namespace dom {
-namespace cache {
-
-class CacheOpParent final : public PCacheOpParent
-                          , public PrincipalVerifier::Listener
-                          , public Manager::Listener
-                          , public FetchPut::Listener
-{
-  // to allow use of convenience overrides
-  using Manager::Listener::OnOpComplete;
-
-public:
-  CacheOpParent(mozilla::ipc::PBackgroundParent* aIpcManager, CacheId aCacheId,
-                const CacheOpArgs& aOpArgs);
-  CacheOpParent(mozilla::ipc::PBackgroundParent* aIpcManager,
-                Namespace aNamespace, const CacheOpArgs& aOpArgs);
-  ~CacheOpParent();
-
-  void
-  Execute(ManagerId* aManagerId);
-
-  void
-  Execute(Manager* aManager);
-
-  void
-  WaitForVerification(PrincipalVerifier* aVerifier);
-
-private:
-  // PCacheOpParent methods
-  virtual void
-  ActorDestroy(ActorDestroyReason aReason) override;
-
-  // PrincipalVerifier::Listener methods
-  virtual void
-  OnPrincipalVerified(nsresult aRv, ManagerId* aManagerId) override;
-
-  // Manager::Listener methods
-  virtual void
-  OnOpComplete(nsresult aRv, const CacheOpResult& aResult,
-               CacheId aOpenedCacheId,
-               const nsTArray<SavedResponse>& aSavedResponseList,
-               const nsTArray<SavedRequest>& aSavedRequestList,
-               StreamList* aStreamList) override;
-
-  // FetchPut::Listener methods
-  virtual void
-  OnFetchPut(FetchPut* aFetchPut, nsresult aRv) override;
-
-  // utility methods
-  already_AddRefed<nsIInputStream>
-  DeserializeCacheStream(const CacheReadStreamOrVoid& aStreamOrVoid);
-
-  mozilla::ipc::PBackgroundParent* mIpcManager;
-  const CacheId mCacheId;
-  const Namespace mNamespace;
-  const CacheOpArgs mOpArgs;
-  nsRefPtr<Manager> mManager;
-  nsRefPtr<PrincipalVerifier> mVerifier;
-  nsTArray<nsRefPtr<FetchPut>> mFetchPutList;
-
-  NS_DECL_OWNINGTHREAD
-};
-
-} // namespace cache
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_cache_CacheOpParent_h
--- a/dom/cache/CacheParent.cpp
+++ b/dom/cache/CacheParent.cpp
@@ -1,24 +1,35 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "mozilla/dom/cache/CacheParent.h"
 
-#include "mozilla/dom/cache/CacheOpParent.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/dom/cache/AutoUtils.h"
 #include "mozilla/dom/cache/CachePushStreamParent.h"
+#include "mozilla/dom/cache/CacheStreamControlParent.h"
+#include "mozilla/dom/cache/ReadStream.h"
+#include "mozilla/dom/cache/SavedTypes.h"
+#include "mozilla/dom/cache/StreamList.h"
+#include "mozilla/ipc/InputStreamUtils.h"
+#include "mozilla/ipc/PBackgroundParent.h"
+#include "mozilla/ipc/FileDescriptorSetParent.h"
+#include "mozilla/ipc/PFileDescriptorSetParent.h"
 #include "nsCOMPtr.h"
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
+using mozilla::ipc::FileDescriptorSetParent;
+using mozilla::ipc::PFileDescriptorSetParent;
 
 // Declared in ActorUtils.h
 void
 DeallocPCacheParent(PCacheParent* aActor)
 {
   delete aActor;
 }
 
@@ -30,58 +41,32 @@ CacheParent::CacheParent(cache::Manager*
   MOZ_ASSERT(mManager);
   mManager->AddRefCacheId(mCacheId);
 }
 
 CacheParent::~CacheParent()
 {
   MOZ_COUNT_DTOR(cache::CacheParent);
   MOZ_ASSERT(!mManager);
+  MOZ_ASSERT(mFetchPutList.IsEmpty());
 }
 
 void
 CacheParent::ActorDestroy(ActorDestroyReason aReason)
 {
   MOZ_ASSERT(mManager);
+  for (uint32_t i = 0; i < mFetchPutList.Length(); ++i) {
+    mFetchPutList[i]->ClearListener();
+  }
+  mFetchPutList.Clear();
+  mManager->RemoveListener(this);
   mManager->ReleaseCacheId(mCacheId);
   mManager = nullptr;
 }
 
-PCacheOpParent*
-CacheParent::AllocPCacheOpParent(const CacheOpArgs& aOpArgs)
-{
-  if (aOpArgs.type() != CacheOpArgs::TCacheMatchArgs &&
-      aOpArgs.type() != CacheOpArgs::TCacheMatchAllArgs &&
-      aOpArgs.type() != CacheOpArgs::TCacheAddAllArgs &&
-      aOpArgs.type() != CacheOpArgs::TCachePutAllArgs &&
-      aOpArgs.type() != CacheOpArgs::TCacheDeleteArgs &&
-      aOpArgs.type() != CacheOpArgs::TCacheKeysArgs)
-  {
-    MOZ_CRASH("Invalid operation sent to Cache actor!");
-  }
-
-  return new CacheOpParent(Manager(), mCacheId, aOpArgs);
-}
-
-bool
-CacheParent::DeallocPCacheOpParent(PCacheOpParent* aActor)
-{
-  delete aActor;
-  return true;
-}
-
-bool
-CacheParent::RecvPCacheOpConstructor(PCacheOpParent* aActor,
-                                     const CacheOpArgs& aOpArgs)
-{
-  auto actor = static_cast<CacheOpParent*>(aActor);
-  actor->Execute(mManager);
-  return true;
-}
-
 PCachePushStreamParent*
 CacheParent::AllocPCachePushStreamParent()
 {
   return CachePushStreamParent::Create();
 }
 
 bool
 CacheParent::DeallocPCachePushStreamParent(PCachePushStreamParent* aActor)
@@ -95,11 +80,240 @@ CacheParent::RecvTeardown()
 {
   if (!Send__delete__(this)) {
     // child process is gone, warn and allow actor to clean up normally
     NS_WARNING("Cache failed to send delete.");
   }
   return true;
 }
 
+bool
+CacheParent::RecvMatch(const RequestId& aRequestId, const PCacheRequest& aRequest,
+                       const PCacheQueryParams& aParams)
+{
+  MOZ_ASSERT(mManager);
+  mManager->CacheMatch(this, aRequestId, mCacheId, aRequest,
+                       aParams);
+  return true;
+}
+
+bool
+CacheParent::RecvMatchAll(const RequestId& aRequestId,
+                          const PCacheRequestOrVoid& aRequest,
+                          const PCacheQueryParams& aParams)
+{
+  MOZ_ASSERT(mManager);
+  mManager->CacheMatchAll(this, aRequestId, mCacheId, aRequest, aParams);
+  return true;
+}
+
+bool
+CacheParent::RecvAddAll(const RequestId& aRequestId,
+                        nsTArray<PCacheRequest>&& aRequests)
+{
+  nsAutoTArray<nsCOMPtr<nsIInputStream>, 256> requestStreams;
+  requestStreams.SetCapacity(aRequests.Length());
+
+  for (uint32_t i = 0; i < aRequests.Length(); ++i) {
+    requestStreams.AppendElement(DeserializeCacheStream(aRequests[i].body()));
+  }
+
+  nsRefPtr<FetchPut> fetchPut;
+  nsresult rv = FetchPut::Create(this, mManager, aRequestId, mCacheId,
+                                 aRequests, requestStreams,
+                                 getter_AddRefs(fetchPut));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    if (!SendAddAllResponse(aRequestId, rv)) {
+      // child process is gone, warn and allow actor to clean up normally
+      NS_WARNING("Cache failed to send AddAll response.");
+    }
+    return true;
+  }
+
+  mFetchPutList.AppendElement(fetchPut.forget());
+
+  return true;
+}
+
+bool
+CacheParent::RecvPut(const RequestId& aRequestId,
+                     const CacheRequestResponse& aPut)
+{
+  MOZ_ASSERT(mManager);
+
+  nsAutoTArray<CacheRequestResponse, 1> putList;
+  putList.AppendElement(aPut);
+
+  nsAutoTArray<nsCOMPtr<nsIInputStream>, 1> requestStreamList;
+  nsAutoTArray<nsCOMPtr<nsIInputStream>, 1> responseStreamList;
+
+  requestStreamList.AppendElement(
+    DeserializeCacheStream(aPut.request().body()));
+  responseStreamList.AppendElement(
+    DeserializeCacheStream(aPut.response().body()));
+
+
+  mManager->CachePutAll(this, aRequestId, mCacheId, putList, requestStreamList,
+                        responseStreamList);
+
+  return true;
+}
+
+bool
+CacheParent::RecvDelete(const RequestId& aRequestId,
+                        const PCacheRequest& aRequest,
+                        const PCacheQueryParams& aParams)
+{
+  MOZ_ASSERT(mManager);
+  mManager->CacheDelete(this, aRequestId, mCacheId, aRequest, aParams);
+  return true;
+}
+
+bool
+CacheParent::RecvKeys(const RequestId& aRequestId,
+                      const PCacheRequestOrVoid& aRequest,
+                      const PCacheQueryParams& aParams)
+{
+  MOZ_ASSERT(mManager);
+  mManager->CacheKeys(this, aRequestId, mCacheId, aRequest, aParams);
+  return true;
+}
+
+void
+CacheParent::OnCacheMatch(RequestId aRequestId, nsresult aRv,
+                          const SavedResponse* aSavedResponse,
+                          StreamList* aStreamList)
+{
+  AutoParentResponseOrVoid response(Manager());
+
+  // no match
+  if (NS_FAILED(aRv) || !aSavedResponse || !aStreamList) {
+    if (!SendMatchResponse(aRequestId, aRv, response.SendAsResponseOrVoid())) {
+      // child process is gone, warn and allow actor to clean up normally
+      NS_WARNING("Cache failed to send Match response.");
+    }
+    return;
+  }
+
+  if (aSavedResponse) {
+    response.Add(*aSavedResponse, aStreamList);
+  }
+
+  if (!SendMatchResponse(aRequestId, aRv, response.SendAsResponseOrVoid())) {
+    // child process is gone, warn and allow actor to clean up normally
+    NS_WARNING("Cache failed to send Match response.");
+  }
+}
+
+void
+CacheParent::OnCacheMatchAll(RequestId aRequestId, nsresult aRv,
+                             const nsTArray<SavedResponse>& aSavedResponses,
+                             StreamList* aStreamList)
+{
+  AutoParentResponseList responses(Manager(), aSavedResponses.Length());
+
+  for (uint32_t i = 0; i < aSavedResponses.Length(); ++i) {
+    responses.Add(aSavedResponses[i], aStreamList);
+  }
+
+  if (!SendMatchAllResponse(aRequestId, aRv, responses.SendAsResponseList())) {
+    // child process is gone, warn and allow actor to clean up normally
+    NS_WARNING("Cache failed to send MatchAll response.");
+  }
+}
+
+void
+CacheParent::OnCachePutAll(RequestId aRequestId, nsresult aRv)
+{
+  if (!SendPutResponse(aRequestId, aRv)) {
+    // child process is gone, warn and allow actor to clean up normally
+    NS_WARNING("Cache failed to send Put response.");
+  }
+}
+
+void
+CacheParent::OnCacheDelete(RequestId aRequestId, nsresult aRv, bool aSuccess)
+{
+  if (!SendDeleteResponse(aRequestId, aRv, aSuccess)) {
+    // child process is gone, warn and allow actor to clean up normally
+    NS_WARNING("Cache failed to send Delete response.");
+  }
+}
+
+void
+CacheParent::OnCacheKeys(RequestId aRequestId, nsresult aRv,
+                         const nsTArray<SavedRequest>& aSavedRequests,
+                         StreamList* aStreamList)
+{
+  AutoParentRequestList requests(Manager(), aSavedRequests.Length());
+
+  for (uint32_t i = 0; i < aSavedRequests.Length(); ++i) {
+    requests.Add(aSavedRequests[i], aStreamList);
+  }
+
+  if (!SendKeysResponse(aRequestId, aRv, requests.SendAsRequestList())) {
+    // child process is gone, warn and allow actor to clean up normally
+    NS_WARNING("Cache failed to send Keys response.");
+  }
+}
+
+void
+CacheParent::OnFetchPut(FetchPut* aFetchPut, RequestId aRequestId, nsresult aRv)
+{
+  aFetchPut->ClearListener();
+  mFetchPutList.RemoveElement(aFetchPut);
+  if (!SendAddAllResponse(aRequestId, aRv)) {
+    // child process is gone, warn and allow actor to clean up normally
+    NS_WARNING("Cache failed to send AddAll response.");
+  }
+}
+
+already_AddRefed<nsIInputStream>
+CacheParent::DeserializeCacheStream(const PCacheReadStreamOrVoid& aStreamOrVoid)
+{
+  if (aStreamOrVoid.type() == PCacheReadStreamOrVoid::Tvoid_t) {
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIInputStream> stream;
+  const PCacheReadStream& readStream = aStreamOrVoid.get_PCacheReadStream();
+
+  // Option 1: A push stream actor was sent for nsPipe data
+  if (readStream.pushStreamParent()) {
+    MOZ_ASSERT(!readStream.controlParent());
+    CachePushStreamParent* pushStream =
+      static_cast<CachePushStreamParent*>(readStream.pushStreamParent());
+    stream = pushStream->TakeReader();
+    MOZ_ASSERT(stream);
+    return stream.forget();
+  }
+
+  // Option 2: One of our own ReadStreams was passed back to us with a stream
+  //           control actor.
+  stream = ReadStream::Create(readStream);
+  if (stream) {
+    return stream.forget();
+  }
+
+  // Option 3: A stream was serialized using normal methods.
+  nsAutoTArray<FileDescriptor, 4> fds;
+  if (readStream.fds().type() ==
+      OptionalFileDescriptorSet::TPFileDescriptorSetChild) {
+
+    FileDescriptorSetParent* fdSetActor =
+      static_cast<FileDescriptorSetParent*>(readStream.fds().get_PFileDescriptorSetParent());
+    MOZ_ASSERT(fdSetActor);
+
+    fdSetActor->ForgetFileDescriptors(fds);
+    MOZ_ASSERT(!fds.IsEmpty());
+
+    if (!fdSetActor->Send__delete__(fdSetActor)) {
+      // child process is gone, warn and allow actor to clean up normally
+      NS_WARNING("Cache failed to delete fd set actor.");
+    }
+  }
+
+  return DeserializeInputStream(readStream.params(), fds);
+}
+
 } // namespace cache
 } // namespace dom
 } // namesapce mozilla
--- a/dom/cache/CacheParent.h
+++ b/dom/cache/CacheParent.h
@@ -2,55 +2,86 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 mozilla_dom_cache_CacheParent_h
 #define mozilla_dom_cache_CacheParent_h
 
+#include "mozilla/dom/cache/FetchPut.h"
+#include "mozilla/dom/cache/Manager.h"
 #include "mozilla/dom/cache/PCacheParent.h"
 #include "mozilla/dom/cache/Types.h"
 
+struct nsID;
+template <class T> class nsRefPtr;
+
 namespace mozilla {
 namespace dom {
 namespace cache {
 
-class Manager;
+struct SavedResponse;
 
 class CacheParent final : public PCacheParent
+                        , public Manager::Listener
+                        , public FetchPut::Listener
 {
 public:
   CacheParent(cache::Manager* aManager, CacheId aCacheId);
   virtual ~CacheParent();
 
 private:
-  // PCacheParent methods
+  // PCacheParent method
   virtual void ActorDestroy(ActorDestroyReason aReason) override;
-
-  virtual PCacheOpParent*
-  AllocPCacheOpParent(const CacheOpArgs& aOpArgs) override;
-
+  virtual PCachePushStreamParent* AllocPCachePushStreamParent() override;
+  virtual bool DeallocPCachePushStreamParent(PCachePushStreamParent* aActor) override;
+  virtual bool RecvTeardown() override;
+  virtual bool
+  RecvMatch(const RequestId& aRequestId, const PCacheRequest& aRequest,
+            const PCacheQueryParams& aParams) override;
   virtual bool
-  DeallocPCacheOpParent(PCacheOpParent* aActor) override;
-
+  RecvMatchAll(const RequestId& aRequestId, const PCacheRequestOrVoid& aRequest,
+               const PCacheQueryParams& aParams) override;
+  virtual bool
+  RecvAddAll(const RequestId& aRequestId,
+             nsTArray<PCacheRequest>&& aRequests) override;
+  virtual bool
+  RecvPut(const RequestId& aRequestId,
+          const CacheRequestResponse& aPut) override;
+  virtual bool
+  RecvDelete(const RequestId& aRequestId, const PCacheRequest& aRequest,
+             const PCacheQueryParams& aParams) override;
   virtual bool
-  RecvPCacheOpConstructor(PCacheOpParent* actor,
-                          const CacheOpArgs& aOpArgs) override;
-
-  virtual PCachePushStreamParent*
-  AllocPCachePushStreamParent() override;
+  RecvKeys(const RequestId& aRequestId, const PCacheRequestOrVoid& aRequest,
+           const PCacheQueryParams& aParams) override;
 
-  virtual bool
-  DeallocPCachePushStreamParent(PCachePushStreamParent* aActor) override;
+  // Manager::Listener methods
+  virtual void OnCacheMatch(RequestId aRequestId, nsresult aRv,
+                            const SavedResponse* aSavedResponse,
+                            StreamList* aStreamList) override;
+  virtual void OnCacheMatchAll(RequestId aRequestId, nsresult aRv,
+                               const nsTArray<SavedResponse>& aSavedResponses,
+                               StreamList* aStreamList) override;
+  virtual void OnCachePutAll(RequestId aRequestId, nsresult aRv) override;
+  virtual void OnCacheDelete(RequestId aRequestId, nsresult aRv,
+                             bool aSuccess) override;
+  virtual void OnCacheKeys(RequestId aRequestId, nsresult aRv,
+                           const nsTArray<SavedRequest>& aSavedRequests,
+                           StreamList* aStreamList) override;
 
-  virtual bool
-  RecvTeardown() override;
+  // FetchPut::Listener methods
+  virtual void OnFetchPut(FetchPut* aFetchPut, RequestId aRequestId,
+                          nsresult aRv) override;
+
+  already_AddRefed<nsIInputStream>
+  DeserializeCacheStream(const PCacheReadStreamOrVoid& aStreamOrVoid);
 
   nsRefPtr<cache::Manager> mManager;
   const CacheId mCacheId;
+  nsTArray<nsRefPtr<FetchPut>> mFetchPutList;
 };
 
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_cache_CacheParent_h
--- a/dom/cache/CacheStorage.cpp
+++ b/dom/cache/CacheStorage.cpp
@@ -8,17 +8,16 @@
 
 #include "mozilla/unused.h"
 #include "mozilla/dom/CacheStorageBinding.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/Response.h"
 #include "mozilla/dom/cache/AutoUtils.h"
 #include "mozilla/dom/cache/Cache.h"
 #include "mozilla/dom/cache/CacheChild.h"
-#include "mozilla/dom/cache/CacheOpChild.h"
 #include "mozilla/dom/cache/CacheStorageChild.h"
 #include "mozilla/dom/cache/Feature.h"
 #include "mozilla/dom/cache/PCacheChild.h"
 #include "mozilla/dom/cache/ReadStream.h"
 #include "mozilla/dom/cache/TypeUtils.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/PBackgroundChild.h"
@@ -37,36 +36,34 @@ using mozilla::dom::workers::WorkerPriva
 using mozilla::ipc::BackgroundChild;
 using mozilla::ipc::PBackgroundChild;
 using mozilla::ipc::IProtocol;
 using mozilla::ipc::PrincipalInfo;
 using mozilla::ipc::PrincipalToPrincipalInfo;
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(mozilla::dom::cache::CacheStorage);
 NS_IMPL_CYCLE_COLLECTING_RELEASE(mozilla::dom::cache::CacheStorage);
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(mozilla::dom::cache::CacheStorage,
-                                      mGlobal);
+NS_IMPL_CYCLE_COLLECTION_CLASS(mozilla::dom::cache::CacheStorage)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(mozilla::dom::cache::CacheStorage)
+  tmp->DisconnectFromActor();
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobal, mRequestPromises)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(mozilla::dom::cache::CacheStorage)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal, mRequestPromises)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(mozilla::dom::cache::CacheStorage)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CacheStorage)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIIPCBackgroundChildCreateCallback)
   NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback)
 NS_INTERFACE_MAP_END
 
-// We cannot reference IPC types in a webidl binding implementation header.  So
-// define this in the .cpp and use heap storage in the mPendingRequests list.
-struct CacheStorage::Entry final
-{
-  nsRefPtr<Promise> mPromise;
-  CacheOpArgs mArgs;
-  // We cannot add the requests until after the actor is present.  So store
-  // the request data separately for now.
-  nsRefPtr<InternalRequest> mRequest;
-};
-
 // static
 already_AddRefed<CacheStorage>
 CacheStorage::CreateOnMainThread(Namespace aNamespace, nsIGlobalObject* aGlobal,
                                  nsIPrincipal* aPrincipal, ErrorResult& aRv)
 {
   MOZ_ASSERT(aGlobal);
   MOZ_ASSERT(aPrincipal);
   MOZ_ASSERT(NS_IsMainThread());
@@ -173,141 +170,146 @@ CacheStorage::CacheStorage(Namespace aNa
 }
 
 already_AddRefed<Promise>
 CacheStorage::Match(const RequestOrUSVString& aRequest,
                     const CacheQueryOptions& aOptions, ErrorResult& aRv)
 {
   NS_ASSERT_OWNINGTHREAD(CacheStorage);
 
-  if (mFailedActor) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
-  nsRefPtr<InternalRequest> request = ToInternalRequest(aRequest, IgnoreBody,
-                                                        aRv);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return nullptr;
-  }
-
   nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
   if (!promise) {
     return nullptr;
   }
 
-  CacheQueryParams params;
-  ToCacheQueryParams(params, aOptions);
+  if (mFailedActor) {
+    promise->MaybeReject(NS_ERROR_UNEXPECTED);
+    return promise.forget();
+  }
+
+  RequestId requestId = AddRequestPromise(promise, aRv);
 
-  nsAutoPtr<Entry> entry(new Entry());
-  entry->mPromise = promise;
-  entry->mArgs = StorageMatchArgs(CacheRequest(), params);
-  entry->mRequest = request;
+  Entry entry;
+  entry.mRequestId = requestId;
+  entry.mOp = OP_MATCH;
+  entry.mOptions = aOptions;
+  entry.mRequest = ToInternalRequest(aRequest, IgnoreBody, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
 
-  mPendingRequests.AppendElement(entry.forget());
+  mPendingRequests.AppendElement(entry);
+
   MaybeRunPendingRequests();
 
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 CacheStorage::Has(const nsAString& aKey, ErrorResult& aRv)
 {
   NS_ASSERT_OWNINGTHREAD(CacheStorage);
 
-  if (mFailedActor) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
   nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
   if (!promise) {
     return nullptr;
   }
 
-  nsAutoPtr<Entry> entry(new Entry());
-  entry->mPromise = promise;
-  entry->mArgs = StorageHasArgs(nsString(aKey));
+  if (mFailedActor) {
+    promise->MaybeReject(NS_ERROR_UNEXPECTED);
+    return promise.forget();
+  }
 
-  mPendingRequests.AppendElement(entry.forget());
+  RequestId requestId = AddRequestPromise(promise, aRv);
+
+  Entry* entry = mPendingRequests.AppendElement();
+  entry->mRequestId = requestId;
+  entry->mOp = OP_HAS;
+  entry->mKey = aKey;
+
   MaybeRunPendingRequests();
 
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 CacheStorage::Open(const nsAString& aKey, ErrorResult& aRv)
 {
   NS_ASSERT_OWNINGTHREAD(CacheStorage);
 
-  if (mFailedActor) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
   nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
   if (!promise) {
     return nullptr;
   }
 
-  nsAutoPtr<Entry> entry(new Entry());
-  entry->mPromise = promise;
-  entry->mArgs = StorageOpenArgs(nsString(aKey));
+  if (mFailedActor) {
+    promise->MaybeReject(NS_ERROR_UNEXPECTED);
+    return promise.forget();
+  }
 
-  mPendingRequests.AppendElement(entry.forget());
+  RequestId requestId = AddRequestPromise(promise, aRv);
+
+  Entry* entry = mPendingRequests.AppendElement();
+  entry->mRequestId = requestId;
+  entry->mOp = OP_OPEN;
+  entry->mKey = aKey;
+
   MaybeRunPendingRequests();
 
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 CacheStorage::Delete(const nsAString& aKey, ErrorResult& aRv)
 {
   NS_ASSERT_OWNINGTHREAD(CacheStorage);
 
-  if (mFailedActor) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
   nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
   if (!promise) {
     return nullptr;
   }
 
-  nsAutoPtr<Entry> entry(new Entry());
-  entry->mPromise = promise;
-  entry->mArgs = StorageDeleteArgs(nsString(aKey));
+  if (mFailedActor) {
+    promise->MaybeReject(NS_ERROR_UNEXPECTED);
+    return promise.forget();
+  }
 
-  mPendingRequests.AppendElement(entry.forget());
+  RequestId requestId = AddRequestPromise(promise, aRv);
+
+  Entry* entry = mPendingRequests.AppendElement();
+  entry->mRequestId = requestId;
+  entry->mOp = OP_DELETE;
+  entry->mKey = aKey;
+
   MaybeRunPendingRequests();
 
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 CacheStorage::Keys(ErrorResult& aRv)
 {
   NS_ASSERT_OWNINGTHREAD(CacheStorage);
 
-  if (mFailedActor) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
-  }
-
   nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv);
   if (!promise) {
     return nullptr;
   }
 
-  nsAutoPtr<Entry> entry(new Entry());
-  entry->mPromise = promise;
-  entry->mArgs = StorageKeysArgs();
+  if (mFailedActor) {
+    promise->MaybeReject(NS_ERROR_UNEXPECTED);
+    return promise.forget();
+  }
 
-  mPendingRequests.AppendElement(entry.forget());
+  RequestId requestId = AddRequestPromise(promise, aRv);
+
+  Entry* entry = mPendingRequests.AppendElement();
+  entry->mRequestId = requestId;
+  entry->mOp = OP_KEYS;
+
   MaybeRunPendingRequests();
 
   return promise.forget();
 }
 
 // static
 bool
 CacheStorage::PrefEnabled(JSContext* aCx, JSObject* aObj)
@@ -364,18 +366,19 @@ CacheStorage::ActorFailed()
 {
   NS_ASSERT_OWNINGTHREAD(CacheStorage);
   MOZ_ASSERT(!mFailedActor);
 
   mFailedActor = true;
   mFeature = nullptr;
 
   for (uint32_t i = 0; i < mPendingRequests.Length(); ++i) {
-    nsAutoPtr<Entry> entry(mPendingRequests[i].forget());
-    entry->mPromise->MaybeReject(NS_ERROR_UNEXPECTED);
+    RequestId requestId = mPendingRequests[i].mRequestId;
+    nsRefPtr<Promise> promise = RemoveRequestPromise(requestId);
+    promise->MaybeReject(NS_ERROR_UNEXPECTED);
   }
   mPendingRequests.Clear();
 }
 
 void
 CacheStorage::DestroyInternal(CacheStorageChild* aActor)
 {
   NS_ASSERT_OWNINGTHREAD(CacheStorage);
@@ -384,16 +387,127 @@ CacheStorage::DestroyInternal(CacheStora
   mActor->ClearListener();
   mActor = nullptr;
 
   // Note that we will never get an actor again in case another request is
   // made before this object is destructed.
   ActorFailed();
 }
 
+void
+CacheStorage::RecvMatchResponse(RequestId aRequestId, nsresult aRv,
+                                const PCacheResponseOrVoid& aResponse)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheStorage);
+
+  // Convert the response immediately if its present.  This ensures that
+  // any stream actors are cleaned up, even if we error out below.
+  nsRefPtr<Response> response;
+  if (aResponse.type() == PCacheResponseOrVoid::TPCacheResponse) {
+    response = ToResponse(aResponse);
+  }
+
+  nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
+
+  if (NS_FAILED(aRv)) {
+    promise->MaybeReject(aRv);
+    return;
+  }
+
+  // If cache name was specified in the request options and the cache does
+  // not exist, then an error code will already have been set.  If we
+  // still do not have a response, then we just resolve undefined like a
+  // normal Cache::Match.
+  if (!response) {
+    promise->MaybeResolve(JS::UndefinedHandleValue);
+    return;
+  }
+
+  promise->MaybeResolve(response);
+}
+
+void
+CacheStorage::RecvHasResponse(RequestId aRequestId, nsresult aRv, bool aSuccess)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheStorage);
+
+  nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
+
+  if (NS_FAILED(aRv)) {
+    promise->MaybeReject(aRv);
+    return;
+
+  }
+
+  promise->MaybeResolve(aSuccess);
+}
+
+void
+CacheStorage::RecvOpenResponse(RequestId aRequestId, nsresult aRv,
+                               CacheChild* aActor)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheStorage);
+
+  // Unlike most of our async callback Recv*() methods, this one gets back
+  // an actor.  We need to make sure to clean it up in case of error.
+
+  nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
+
+  if (NS_FAILED(aRv)) {
+    if (aActor) {
+      // We cannot use the CacheChild::StartDestroy() method because there
+      // is no Cache object associated with the actor yet.  Instead, just
+      // send the underlying Teardown message.
+      unused << aActor->SendTeardown();
+    }
+    promise->MaybeReject(aRv);
+    return;
+  }
+
+  if (!aActor) {
+    promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
+    return;
+  }
+
+  nsRefPtr<Cache> cache = new Cache(mGlobal, aActor);
+  promise->MaybeResolve(cache);
+}
+
+void
+CacheStorage::RecvDeleteResponse(RequestId aRequestId, nsresult aRv,
+                                 bool aSuccess)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheStorage);
+
+  nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
+
+  if (NS_FAILED(aRv)) {
+    promise->MaybeReject(aRv);
+    return;
+  }
+
+  promise->MaybeResolve(aSuccess);
+}
+
+void
+CacheStorage::RecvKeysResponse(RequestId aRequestId, nsresult aRv,
+                               const nsTArray<nsString>& aKeys)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheStorage);
+
+  nsRefPtr<Promise> promise = RemoveRequestPromise(aRequestId);
+
+  if (NS_FAILED(aRv)) {
+    promise->MaybeReject(aRv);
+    return;
+  }
+
+  promise->MaybeResolve(aKeys);
+}
+
 nsIGlobalObject*
 CacheStorage::GetGlobalObject() const
 {
   return mGlobal;
 }
 
 #ifdef DEBUG
 void
@@ -405,48 +519,136 @@ CacheStorage::AssertOwningThread() const
 
 CachePushStreamChild*
 CacheStorage::CreatePushStream(nsIAsyncInputStream* aStream)
 {
   // This is true because CacheStorage always uses IgnoreBody for requests.
   MOZ_CRASH("CacheStorage should never create a push stream.");
 }
 
+void
+CacheStorage::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
+{
+  // Do nothing.  The Promise will automatically drop the ref to us after
+  // calling the callback.  This is what we want as we only registered in order
+  // to be held alive via the Promise handle.
+}
+
+void
+CacheStorage::RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
+{
+  // Do nothing.  The Promise will automatically drop the ref to us after
+  // calling the callback.  This is what we want as we only registered in order
+  // to be held alive via the Promise handle.
+}
+
 CacheStorage::~CacheStorage()
 {
+  DisconnectFromActor();
+}
+
+void
+CacheStorage::DisconnectFromActor()
+{
   NS_ASSERT_OWNINGTHREAD(CacheStorage);
+
   if (mActor) {
     mActor->StartDestroy();
     // DestroyInternal() is called synchronously by StartDestroy().  So we
     // should have already cleared the mActor.
     MOZ_ASSERT(!mActor);
   }
 }
 
 void
 CacheStorage::MaybeRunPendingRequests()
 {
   if (!mActor) {
     return;
   }
 
   for (uint32_t i = 0; i < mPendingRequests.Length(); ++i) {
-    ErrorResult rv;
-    nsAutoPtr<Entry> entry(mPendingRequests[i].forget());
-    AutoChildOpArgs args(this, entry->mArgs);
-    if (entry->mRequest) {
-      args.Add(entry->mRequest, IgnoreBody, PassThroughReferrer,
-               IgnoreInvalidScheme, rv);
+    // Note, the entry can be modified below due to Request/Response body
+    // being marked used.
+    Entry& entry = mPendingRequests[i];
+    RequestId requestId = entry.mRequestId;
+    switch(entry.mOp) {
+      case OP_MATCH:
+      {
+        AutoChildRequest request(this);
+        ErrorResult rv;
+        request.Add(entry.mRequest, IgnoreBody, PassThroughReferrer,
+                    IgnoreInvalidScheme, rv);
+        if (NS_WARN_IF(rv.Failed())) {
+          nsRefPtr<Promise> promise = RemoveRequestPromise(requestId);
+          promise->MaybeReject(rv);
+          break;
+        }
+
+        PCacheQueryParams params;
+        ToPCacheQueryParams(params, entry.mOptions);
+
+        unused << mActor->SendMatch(requestId, request.SendAsRequest(), params);
+        break;
+      }
+      case OP_HAS:
+        unused << mActor->SendHas(requestId, entry.mKey);
+        break;
+      case OP_OPEN:
+        unused << mActor->SendOpen(requestId, entry.mKey);
+        break;
+      case OP_DELETE:
+        unused << mActor->SendDelete(requestId, entry.mKey);
+        break;
+      case OP_KEYS:
+        unused << mActor->SendKeys(requestId);
+        break;
+      default:
+        MOZ_ASSERT_UNREACHABLE("Unknown pending CacheStorage op.");
     }
-    if (rv.Failed()) {
-      entry->mPromise->MaybeReject(rv);
-      continue;
-    }
-    unused << mActor->SendPCacheOpConstructor(
-      new CacheOpChild(mActor->GetFeature(), mGlobal, this, entry->mPromise),
-      args.SendAsOpArgs());
   }
   mPendingRequests.Clear();
 }
 
+RequestId
+CacheStorage::AddRequestPromise(Promise* aPromise, ErrorResult& aRv)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheStorage);
+  MOZ_ASSERT(aPromise);
+  MOZ_ASSERT(!mRequestPromises.Contains(aPromise));
+
+  // Register ourself as a promise handler so that the promise will hold us
+  // alive.  This allows the client code to drop the ref to the CacheStorage
+  // object and just keep their promise.  This is fairly common in promise
+  // chaining code.
+  aPromise->AppendNativeHandler(this);
+
+  mRequestPromises.AppendElement(aPromise);
+
+  // (Ab)use the promise pointer as our request ID.  This is a fast, thread-safe
+  // way to get a unique ID for the promise to be resolved later.
+  return reinterpret_cast<RequestId>(aPromise);
+}
+
+already_AddRefed<Promise>
+CacheStorage::RemoveRequestPromise(RequestId aRequestId)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheStorage);
+  MOZ_ASSERT(aRequestId != INVALID_REQUEST_ID);
+
+  for (uint32_t i = 0; i < mRequestPromises.Length(); ++i) {
+    nsRefPtr<Promise>& promise = mRequestPromises.ElementAt(i);
+    // To be safe, only cast promise pointers to our integer RequestId
+    // type and never cast an integer to a pointer.
+    if (aRequestId == reinterpret_cast<RequestId>(promise.get())) {
+      nsRefPtr<Promise> ref;
+      ref.swap(promise);
+      mRequestPromises.RemoveElementAt(i);
+      return ref.forget();
+    }
+  }
+  MOZ_ASSERT_UNREACHABLE("Received response without a matching promise!");
+  return nullptr;
+}
+
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
--- a/dom/cache/CacheStorage.h
+++ b/dom/cache/CacheStorage.h
@@ -3,16 +3,17 @@
 /* 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 mozilla_dom_cache_CacheStorage_h
 #define mozilla_dom_cache_CacheStorage_h
 
 #include "mozilla/dom/CacheBinding.h"
+#include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/dom/cache/Types.h"
 #include "mozilla/dom/cache/TypeUtils.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsISupportsImpl.h"
 #include "nsTArray.h"
 #include "nsWrapperCache.h"
 #include "nsIIPCBackgroundChildCreateCallback.h"
@@ -32,22 +33,25 @@ namespace dom {
 class Promise;
 
 namespace workers {
   class WorkerPrivate;
 }
 
 namespace cache {
 
+class CacheChild;
 class CacheStorageChild;
 class Feature;
+class PCacheResponseOrVoid;
 
 class CacheStorage final : public nsIIPCBackgroundChildCreateCallback
                          , public nsWrapperCache
                          , public TypeUtils
+                         , public PromiseNativeHandler
 {
   typedef mozilla::ipc::PBackgroundChild PBackgroundChild;
 
 public:
   static already_AddRefed<CacheStorage>
   CreateOnMainThread(Namespace aNamespace, nsIGlobalObject* aGlobal,
                      nsIPrincipal* aPrincipal, ErrorResult& aRv);
 
@@ -72,43 +76,89 @@ public:
 
   // nsIIPCbackgroundChildCreateCallback methods
   virtual void ActorCreated(PBackgroundChild* aActor) override;
   virtual void ActorFailed() override;
 
   // Called when CacheStorageChild actor is being destroyed
   void DestroyInternal(CacheStorageChild* aActor);
 
+  // Methods forwarded from CacheStorageChild
+  void RecvMatchResponse(RequestId aRequestId, nsresult aRv,
+                         const PCacheResponseOrVoid& aResponse);
+  void RecvHasResponse(RequestId aRequestId, nsresult aRv, bool aSuccess);
+  void RecvOpenResponse(RequestId aRequestId, nsresult aRv,
+                        CacheChild* aActor);
+  void RecvDeleteResponse(RequestId aRequestId, nsresult aRv, bool aSuccess);
+  void RecvKeysResponse(RequestId aRequestId, nsresult aRv,
+                        const nsTArray<nsString>& aKeys);
+
   // TypeUtils methods
   virtual nsIGlobalObject* GetGlobalObject() const override;
 #ifdef DEBUG
   virtual void AssertOwningThread() const override;
 #endif
 
   virtual CachePushStreamChild*
   CreatePushStream(nsIAsyncInputStream* aStream) override;
 
+  // PromiseNativeHandler methods
+  virtual void
+  ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
+
+  virtual void
+  RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
+
 private:
   CacheStorage(Namespace aNamespace, nsIGlobalObject* aGlobal,
                const mozilla::ipc::PrincipalInfo& aPrincipalInfo, Feature* aFeature);
   ~CacheStorage();
 
+  // Called when we're destroyed or CCed.
+  void DisconnectFromActor();
+
   void MaybeRunPendingRequests();
 
+  RequestId AddRequestPromise(Promise* aPromise, ErrorResult& aRv);
+  already_AddRefed<Promise> RemoveRequestPromise(RequestId aRequestId);
+
+  // Would like to use CacheInitData here, but we cannot because
+  // its an IPC struct which breaks webidl by including windows.h.
   const Namespace mNamespace;
   nsCOMPtr<nsIGlobalObject> mGlobal;
   UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
   nsRefPtr<Feature> mFeature;
+  CacheStorageChild* mActor;
+  nsTArray<nsRefPtr<Promise>> mRequestPromises;
 
-  // weak ref cleared in DestroyInternal
-  CacheStorageChild* mActor;
+  enum Op
+  {
+    OP_MATCH,
+    OP_HAS,
+    OP_OPEN,
+    OP_DELETE,
+    OP_KEYS
+  };
 
-  struct Entry;
-  nsTArray<nsAutoPtr<Entry>> mPendingRequests;
+  struct Entry
+  {
+    RequestId mRequestId;
+    Op mOp;
+    // Would prefer to use PCacheRequest/PCacheCacheQueryOptions, but can't
+    // because they introduce a header dependency on windows.h which
+    // breaks the bindings build.
+    nsRefPtr<InternalRequest> mRequest;
+    CacheQueryOptions mOptions;
+    // It would also be nice to union the key with the match args above,
+    // but VS2013 doesn't like these types in unions because of copy
+    // constructors.
+    nsString mKey;
+  };
 
+  nsTArray<Entry> mPendingRequests;
   bool mFailedActor;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(CacheStorage,
                                            nsIIPCBackgroundChildCreateCallback)
 };
 
--- a/dom/cache/CacheStorageChild.cpp
+++ b/dom/cache/CacheStorageChild.cpp
@@ -4,17 +4,16 @@
  * 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 "mozilla/dom/cache/CacheStorageChild.h"
 
 #include "mozilla/unused.h"
 #include "mozilla/dom/cache/CacheChild.h"
 #include "mozilla/dom/cache/CacheStorage.h"
-#include "mozilla/dom/cache/PCacheOpChild.h"
 #include "mozilla/dom/cache/StreamUtils.h"
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 // declared in ActorUtils.h
 void
@@ -56,18 +55,16 @@ CacheStorageChild::StartDestroy()
 
   // StartDestroy() can get called from either CacheStorage or the Feature.
   // Theoretically we can get double called if the right race happens.  Handle
   // that by just ignoring the second StartDestroy() call.
   if (!listener) {
     return;
   }
 
-  // TODO: don't destroy if we have outstanding ops
-
   listener->DestroyInternal(this);
 
   // CacheStorage listener should call ClearListener() in DestroyInternal()
   MOZ_ASSERT(!mListener);
 
   // Start actor destruction from parent process
   unused << SendTeardown();
 }
@@ -81,25 +78,99 @@ CacheStorageChild::ActorDestroy(ActorDes
     listener->DestroyInternal(this);
     // CacheStorage listener should call ClearListener() in DestroyInternal()
     MOZ_ASSERT(!mListener);
   }
 
   RemoveFeature();
 }
 
-PCacheOpChild*
-CacheStorageChild::AllocPCacheOpChild(const CacheOpArgs& aOpArgs)
+bool
+CacheStorageChild::RecvMatchResponse(const RequestId& aRequestId,
+                                     const nsresult& aRv,
+                                     const PCacheResponseOrVoid& aResponseOrVoid)
 {
-  MOZ_CRASH("CacheOpChild should be manually constructed.");
-  return nullptr;
+  NS_ASSERT_OWNINGTHREAD(CacheStorageChild);
+
+  AddFeatureToStreamChild(aResponseOrVoid, GetFeature());
+
+  nsRefPtr<CacheStorage> listener = mListener;
+  if (!listener) {
+    StartDestroyStreamChild(aResponseOrVoid);
+    return true;
+  }
+
+  listener->RecvMatchResponse(aRequestId, aRv, aResponseOrVoid);
+
+  return true;
+}
+
+bool
+CacheStorageChild::RecvHasResponse(const RequestId& aRequestId,
+                                   const nsresult& aRv,
+                                   const bool& aSuccess)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheStorageChild);
+  nsRefPtr<CacheStorage> listener = mListener;
+  if (listener) {
+    listener->RecvHasResponse(aRequestId, aRv, aSuccess);
+  }
+  return true;
 }
 
 bool
-CacheStorageChild::DeallocPCacheOpChild(PCacheOpChild* aActor)
+CacheStorageChild::RecvOpenResponse(const RequestId& aRequestId,
+                                    const nsresult& aRv,
+                                    PCacheChild* aActor)
 {
-  delete aActor;
+  NS_ASSERT_OWNINGTHREAD(CacheStorageChild);
+
+  nsRefPtr<CacheStorage> listener = mListener;
+  if (!listener || FeatureNotified()) {
+    if (aActor) {
+      unused << aActor->SendTeardown();
+    }
+    return true;
+  }
+
+  CacheChild* cacheChild = static_cast<CacheChild*>(aActor);
+
+  // Since FeatureNotified() returned false above, we are guaranteed that
+  // the feature won't try to shutdown the actor until after we create the
+  // Cache DOM object in the listener's RecvOpenResponse() method.  This
+  // is important because StartShutdown() expects a Cache object listener.
+  if (cacheChild) {
+    cacheChild->SetFeature(GetFeature());
+  }
+
+  listener->RecvOpenResponse(aRequestId, aRv, cacheChild);
+  return true;
+}
+
+bool
+CacheStorageChild::RecvDeleteResponse(const RequestId& aRequestId,
+                                      const nsresult& aRv,
+                                      const bool& aResult)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheStorageChild);
+  nsRefPtr<CacheStorage> listener = mListener;
+  if (listener) {
+    listener->RecvDeleteResponse(aRequestId, aRv, aResult);
+  }
+  return true;
+}
+
+bool
+CacheStorageChild::RecvKeysResponse(const RequestId& aRequestId,
+                                    const nsresult& aRv,
+                                    nsTArray<nsString>&& aKeys)
+{
+  NS_ASSERT_OWNINGTHREAD(CacheStorageChild);
+  nsRefPtr<CacheStorage> listener = mListener;
+  if (listener) {
+    listener->RecvKeysResponse(aRequestId, aRv, aKeys);
+  }
   return true;
 }
 
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
--- a/dom/cache/CacheStorageChild.h
+++ b/dom/cache/CacheStorageChild.h
@@ -22,36 +22,46 @@ class Feature;
 class CacheStorageChild final : public PCacheStorageChild
                               , public ActorChild
 {
 public:
   CacheStorageChild(CacheStorage* aListener, Feature* aFeature);
   ~CacheStorageChild();
 
   // Must be called by the associated CacheStorage listener in its
-  // ActorDestroy() method.  Also, CacheStorage must call SendDestroy() on the
+  // ActorDestroy() method.  Also, CacheStorage must Send__delete__() the
   // actor in its destructor to trigger ActorDestroy() if it has not been
   // called yet.
   void ClearListener();
 
   // ActorChild methods
 
   // Synchronously call ActorDestroy on our CacheStorage listener and then start
   // the actor destruction asynchronously from the parent-side.
   virtual void StartDestroy() override;
 
 private:
   // PCacheStorageChild methods
   virtual void ActorDestroy(ActorDestroyReason aReason) override;
 
-  virtual PCacheOpChild*
-  AllocPCacheOpChild(const CacheOpArgs& aOpArgs) override;
-
-  virtual bool
-  DeallocPCacheOpChild(PCacheOpChild* aActor) override;
+  virtual bool RecvMatchResponse(const RequestId& aRequestId,
+                                 const nsresult& aRv,
+                                 const PCacheResponseOrVoid& response) override;
+  virtual bool RecvHasResponse(const cache::RequestId& aRequestId,
+                               const nsresult& aRv,
+                               const bool& aSuccess) override;
+  virtual bool RecvOpenResponse(const cache::RequestId& aRequestId,
+                                const nsresult& aRv,
+                                PCacheChild* aActor) override;
+  virtual bool RecvDeleteResponse(const cache::RequestId& aRequestId,
+                                  const nsresult& aRv,
+                                  const bool& aResult) override;
+  virtual bool RecvKeysResponse(const cache::RequestId& aRequestId,
+                                const nsresult& aRv,
+                                nsTArray<nsString>&& aKeys) override;
 
   // Use a weak ref so actor does not hold DOM object alive past content use.
   // The CacheStorage object must call ClearListener() to null this before its
   // destroyed.
   CacheStorage* MOZ_NON_OWNING_REF mListener;
 
   NS_DECL_OWNINGTHREAD
 };
--- a/dom/cache/CacheStorageParent.cpp
+++ b/dom/cache/CacheStorageParent.cpp
@@ -1,28 +1,38 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "mozilla/dom/cache/CacheStorageParent.h"
 
-#include "mozilla/unused.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/cache/ActorUtils.h"
-#include "mozilla/dom/cache/CacheOpParent.h"
+#include "mozilla/dom/cache/AutoUtils.h"
+#include "mozilla/dom/cache/CacheParent.h"
+#include "mozilla/dom/cache/CacheStreamControlParent.h"
+#include "mozilla/dom/cache/Manager.h"
 #include "mozilla/dom/cache/ManagerId.h"
+#include "mozilla/dom/cache/ReadStream.h"
+#include "mozilla/dom/cache/SavedTypes.h"
+#include "mozilla/dom/cache/StreamList.h"
 #include "mozilla/ipc/PBackgroundParent.h"
+#include "mozilla/ipc/InputStreamUtils.h"
+#include "mozilla/ipc/PFileDescriptorSetParent.h"
+#include "mozilla/DebugOnly.h"
+#include "nsCOMPtr.h"
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 using mozilla::ipc::PBackgroundParent;
+using mozilla::ipc::PFileDescriptorSetParent;
 using mozilla::ipc::PrincipalInfo;
 
 // declared in ActorUtils.h
 PCacheStorageParent*
 AllocPCacheStorageParent(PBackgroundParent* aManagingActor,
                          Namespace aNamespace,
                          const mozilla::ipc::PrincipalInfo& aPrincipalInfo)
 {
@@ -50,92 +60,391 @@ CacheStorageParent::CacheStorageParent(P
                                                    aPrincipalInfo);
   MOZ_ASSERT(mVerifier);
 }
 
 CacheStorageParent::~CacheStorageParent()
 {
   MOZ_COUNT_DTOR(cache::CacheStorageParent);
   MOZ_ASSERT(!mVerifier);
+  MOZ_ASSERT(!mManager);
 }
 
 void
 CacheStorageParent::ActorDestroy(ActorDestroyReason aReason)
 {
   if (mVerifier) {
-    mVerifier->RemoveListener(this);
+    mVerifier->ClearListener();
     mVerifier = nullptr;
   }
-}
-
-PCacheOpParent*
-CacheStorageParent::AllocPCacheOpParent(const CacheOpArgs& aOpArgs)
-{
-  if (aOpArgs.type() != CacheOpArgs::TStorageMatchArgs &&
-      aOpArgs.type() != CacheOpArgs::TStorageHasArgs &&
-      aOpArgs.type() != CacheOpArgs::TStorageOpenArgs &&
-      aOpArgs.type() != CacheOpArgs::TStorageDeleteArgs &&
-      aOpArgs.type() != CacheOpArgs::TStorageKeysArgs)
-  {
-    MOZ_CRASH("Invalid operation sent to CacheStorage actor!");
-  }
 
-  return new CacheOpParent(Manager(), mNamespace, aOpArgs);
-}
-
-bool
-CacheStorageParent::DeallocPCacheOpParent(PCacheOpParent* aActor)
-{
-  delete aActor;
-  return true;
-}
-
-bool
-CacheStorageParent::RecvPCacheOpConstructor(PCacheOpParent* aActor,
-                                            const CacheOpArgs& aOpArgs)
-{
-  auto actor = static_cast<CacheOpParent*>(aActor);
-
-  if (mVerifier) {
-    MOZ_ASSERT(!mManagerId);
-    actor->WaitForVerification(mVerifier);
-    return true;
+  if (mManager) {
+    MOZ_ASSERT(!mActiveRequests.IsEmpty());
+    mManager->RemoveListener(this);
+    mManager = nullptr;
   }
-
-  if (NS_FAILED(mVerifiedStatus)) {
-    unused << CacheOpParent::Send__delete__(actor, mVerifiedStatus, void_t());
-    return true;
-  }
-
-  MOZ_ASSERT(mManagerId);
-  actor->Execute(mManagerId);
-  return true;
 }
 
 bool
 CacheStorageParent::RecvTeardown()
 {
   if (!Send__delete__(this)) {
     // child process is gone, warn and allow actor to clean up normally
     NS_WARNING("CacheStorage failed to delete actor.");
   }
   return true;
 }
 
+bool
+CacheStorageParent::RecvMatch(const RequestId& aRequestId,
+                              const PCacheRequest& aRequest,
+                              const PCacheQueryParams& aParams)
+{
+  if (NS_WARN_IF(NS_FAILED(mVerifiedStatus))) {
+    if (!SendMatchResponse(aRequestId, mVerifiedStatus, void_t())) {
+      // child process is gone, warn and allow actor to clean up normally
+      NS_WARNING("CacheStorage failed to send Match response.");
+    }
+    return true;
+  }
+
+  // queue requests if we are still waiting for principal verification
+  if (!mManagerId) {
+    Entry* entry = mPendingRequests.AppendElement();
+    entry->mOp = OP_MATCH;
+    entry->mRequestId = aRequestId;
+    entry->mRequest = aRequest;
+    entry->mParams = aParams;
+    return true;
+  }
+
+  nsRefPtr<cache::Manager> manager;
+  nsresult rv = RequestManager(aRequestId, getter_AddRefs(manager));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    if (!SendMatchResponse(aRequestId, rv, void_t())) {
+      // child process is gone, warn and allow actor to clean up normally
+      NS_WARNING("CacheStorage failed to send Match response.");
+    }
+    return true;
+  }
+
+  manager->StorageMatch(this, aRequestId, mNamespace, aRequest,
+                        aParams);
+
+  return true;
+}
+
+bool
+CacheStorageParent::RecvHas(const RequestId& aRequestId, const nsString& aKey)
+{
+  if (NS_WARN_IF(NS_FAILED(mVerifiedStatus))) {
+    if (!SendHasResponse(aRequestId, mVerifiedStatus, false)) {
+      // child process is gone, warn and allow actor to clean up normally
+      NS_WARNING("CacheStorage failed to send Has response.");
+    }
+    return true;
+  }
+
+  // queue requests if we are still waiting for principal verification
+  if (!mManagerId) {
+    Entry* entry = mPendingRequests.AppendElement();
+    entry->mOp = OP_HAS;
+    entry->mRequestId = aRequestId;
+    entry->mKey = aKey;
+    return true;
+  }
+
+  nsRefPtr<cache::Manager> manager;
+  nsresult rv = RequestManager(aRequestId, getter_AddRefs(manager));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    if (!SendHasResponse(aRequestId, rv, false)) {
+      // child process is gone, warn and allow actor to clean up normally
+      NS_WARNING("CacheStorage failed to send Has response.");
+    }
+    return true;
+  }
+
+  manager->StorageHas(this, aRequestId, mNamespace, aKey);
+
+  return true;
+}
+
+bool
+CacheStorageParent::RecvOpen(const RequestId& aRequestId, const nsString& aKey)
+{
+  if (NS_WARN_IF(NS_FAILED(mVerifiedStatus))) {
+    if (!SendOpenResponse(aRequestId, mVerifiedStatus, nullptr)) {
+      // child process is gone, warn and allow actor to clean up normally
+      NS_WARNING("CacheStorage failed to send Open response.");
+    }
+    return true;
+  }
+
+  // queue requests if we are still waiting for principal verification
+  if (!mManagerId) {
+    Entry* entry = mPendingRequests.AppendElement();
+    entry->mOp = OP_OPEN;
+    entry->mRequestId = aRequestId;
+    entry->mKey = aKey;
+    return true;
+  }
+
+  nsRefPtr<cache::Manager> manager;
+  nsresult rv = RequestManager(aRequestId, getter_AddRefs(manager));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    if (!SendOpenResponse(aRequestId, rv, nullptr)) {
+      // child process is gone, warn and allow actor to clean up normally
+      NS_WARNING("CacheStorage failed to send Open response.");
+    }
+    return true;
+  }
+
+  manager->StorageOpen(this, aRequestId, mNamespace, aKey);
+
+  return true;
+}
+
+bool
+CacheStorageParent::RecvDelete(const RequestId& aRequestId,
+                               const nsString& aKey)
+{
+  if (NS_WARN_IF(NS_FAILED(mVerifiedStatus))) {
+    if (!SendDeleteResponse(aRequestId, mVerifiedStatus, false)) {
+      // child process is gone, warn and allow actor to clean up normally
+      NS_WARNING("CacheStorage failed to send Delete response.");
+    }
+    return true;
+  }
+
+  // queue requests if we are still waiting for principal verification
+  if (!mManagerId) {
+    Entry* entry = mPendingRequests.AppendElement();
+    entry->mOp = OP_DELETE;
+    entry->mRequestId = aRequestId;
+    entry->mKey = aKey;
+    return true;
+  }
+
+  nsRefPtr<cache::Manager> manager;
+  nsresult rv = RequestManager(aRequestId, getter_AddRefs(manager));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    if (!SendDeleteResponse(aRequestId, rv, false)) {
+      // child process is gone, warn and allow actor to clean up normally
+      NS_WARNING("CacheStorage failed to send Delete response.");
+    }
+    return true;
+  }
+
+  manager->StorageDelete(this, aRequestId, mNamespace, aKey);
+
+  return true;
+}
+
+bool
+CacheStorageParent::RecvKeys(const RequestId& aRequestId)
+{
+  if (NS_WARN_IF(NS_FAILED(mVerifiedStatus))) {
+    if (!SendKeysResponse(aRequestId, mVerifiedStatus, nsTArray<nsString>())) {
+      // child process is gone, warn and allow actor to clean up normally
+      NS_WARNING("CacheStorage failed to send Keys response.");
+    }
+  }
+
+  // queue requests if we are still waiting for principal verification
+  if (!mManagerId) {
+    Entry* entry = mPendingRequests.AppendElement();
+    entry->mOp = OP_DELETE;
+    entry->mRequestId = aRequestId;
+    return true;
+  }
+
+  nsRefPtr<cache::Manager> manager;
+  nsresult rv = RequestManager(aRequestId, getter_AddRefs(manager));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    if (!SendKeysResponse(aRequestId, rv, nsTArray<nsString>())) {
+      // child process is gone, warn and allow actor to clean up normally
+      NS_WARNING("CacheStorage failed to send Keys response.");
+    }
+    return true;
+  }
+
+  manager->StorageKeys(this, aRequestId, mNamespace);
+
+  return true;
+}
+
 void
 CacheStorageParent::OnPrincipalVerified(nsresult aRv, ManagerId* aManagerId)
 {
   MOZ_ASSERT(mVerifier);
   MOZ_ASSERT(!mManagerId);
+  MOZ_ASSERT(!mManager);
   MOZ_ASSERT(NS_SUCCEEDED(mVerifiedStatus));
 
   if (NS_WARN_IF(NS_FAILED(aRv))) {
     mVerifiedStatus = aRv;
   }
 
   mManagerId = aManagerId;
-  mVerifier->RemoveListener(this);
+  mVerifier->ClearListener();
   mVerifier = nullptr;
+
+  RetryPendingRequests();
+}
+
+void
+CacheStorageParent::OnStorageMatch(RequestId aRequestId, nsresult aRv,
+                                   const SavedResponse* aSavedResponse,
+                                   StreamList* aStreamList)
+{
+  PCacheResponseOrVoid responseOrVoid;
+
+  ReleaseManager(aRequestId);
+
+  AutoParentResponseOrVoid response(Manager());
+
+  // no match
+  if (NS_FAILED(aRv) || !aSavedResponse) {
+    if (!SendMatchResponse(aRequestId, aRv, response.SendAsResponseOrVoid())) {
+      // child process is gone, warn and allow actor to clean up normally
+      NS_WARNING("CacheStorage failed to send Match response.");
+    }
+    return;
+  }
+
+  if (aSavedResponse) {
+    response.Add(*aSavedResponse, aStreamList);
+  }
+
+  if (!SendMatchResponse(aRequestId, aRv, response.SendAsResponseOrVoid())) {
+    // child process is gone, warn and allow actor to clean up normally
+    NS_WARNING("CacheStorage failed to send Match response.");
+  }
+}
+
+void
+CacheStorageParent::OnStorageHas(RequestId aRequestId, nsresult aRv,
+                                 bool aCacheFound)
+{
+  ReleaseManager(aRequestId);
+  if (!SendHasResponse(aRequestId, aRv, aCacheFound)) {
+    // child process is gone, warn and allow actor to clean up normally
+    NS_WARNING("CacheStorage failed to send Has response.");
+  }
+}
+
+void
+CacheStorageParent::OnStorageOpen(RequestId aRequestId, nsresult aRv,
+                                  CacheId aCacheId)
+{
+  if (NS_FAILED(aRv)) {
+    ReleaseManager(aRequestId);
+    if (!SendOpenResponse(aRequestId, aRv, nullptr)) {
+      // child process is gone, warn and allow actor to clean up normally
+      NS_WARNING("CacheStorage failed to send Open response.");
+    }
+    return;
+  }
+
+  MOZ_ASSERT(mManager);
+  CacheParent* actor = new CacheParent(mManager, aCacheId);
+
+  ReleaseManager(aRequestId);
+
+  PCacheParent* base = Manager()->SendPCacheConstructor(actor);
+  actor = static_cast<CacheParent*>(base);
+  if (!SendOpenResponse(aRequestId, aRv, actor)) {
+    // child process is gone, warn and allow actor to clean up normally
+    NS_WARNING("CacheStorage failed to send Open response.");
+  }
+}
+
+void
+CacheStorageParent::OnStorageDelete(RequestId aRequestId, nsresult aRv,
+                                    bool aCacheDeleted)
+{
+  ReleaseManager(aRequestId);
+  if (!SendDeleteResponse(aRequestId, aRv, aCacheDeleted)) {
+    // child process is gone, warn and allow actor to clean up normally
+    NS_WARNING("CacheStorage failed to send Delete response.");
+  }
+}
+
+void
+CacheStorageParent::OnStorageKeys(RequestId aRequestId, nsresult aRv,
+                                  const nsTArray<nsString>& aKeys)
+{
+  ReleaseManager(aRequestId);
+  if (!SendKeysResponse(aRequestId, aRv, aKeys)) {
+    // child process is gone, warn and allow actor to clean up normally
+    NS_WARNING("CacheStorage failed to send Keys response.");
+  }
+}
+
+void
+CacheStorageParent::RetryPendingRequests()
+{
+  MOZ_ASSERT(mManagerId || NS_FAILED(mVerifiedStatus));
+  for (uint32_t i = 0; i < mPendingRequests.Length(); ++i) {
+    const Entry& entry = mPendingRequests[i];
+    switch(entry.mOp) {
+      case OP_MATCH:
+        RecvMatch(entry.mRequestId, entry.mRequest, entry.mParams);
+        break;
+      case OP_HAS:
+        RecvHas(entry.mRequestId, entry.mKey);
+        break;
+      case OP_OPEN:
+        RecvOpen(entry.mRequestId, entry.mKey);
+        break;
+      case OP_DELETE:
+        RecvDelete(entry.mRequestId, entry.mKey);
+        break;
+      case OP_KEYS:
+        RecvKeys(entry.mRequestId);
+        break;
+      default:
+        MOZ_ASSERT_UNREACHABLE("Pending request within unknown op");
+    }
+  }
+  mPendingRequests.Clear();
+  mPendingRequests.Compact();
+}
+
+nsresult
+CacheStorageParent::RequestManager(RequestId aRequestId,
+                                   cache::Manager** aManagerOut)
+{
+  MOZ_ASSERT(!mActiveRequests.Contains(aRequestId));
+  nsRefPtr<cache::Manager> ref = mManager;
+  if (!ref) {
+    MOZ_ASSERT(mActiveRequests.IsEmpty());
+    nsresult rv = cache::Manager::GetOrCreate(mManagerId, getter_AddRefs(ref));
+    if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
+    mManager = ref;
+  }
+  mActiveRequests.AppendElement(aRequestId);
+  ref.forget(aManagerOut);
+  return NS_OK;
+}
+
+void
+CacheStorageParent::ReleaseManager(RequestId aRequestId)
+{
+  // Note that if the child process dies we also clean up the mManager in
+  // ActorDestroy().  There is no race with this method, however, because
+  // ActorDestroy removes this object from the Manager's listener list.
+  // Therefore ReleaseManager() should never be called after ActorDestroy()
+  // runs.
+  MOZ_ASSERT(mManager);
+  MOZ_ASSERT(!mActiveRequests.IsEmpty());
+
+  MOZ_ALWAYS_TRUE(mActiveRequests.RemoveElement(aRequestId));
+
+  if (mActiveRequests.IsEmpty()) {
+    mManager->RemoveListener(this);
+    mManager = nullptr;
+  }
 }
 
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
--- a/dom/cache/CacheStorageParent.h
+++ b/dom/cache/CacheStorageParent.h
@@ -2,59 +2,107 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 mozilla_dom_cache_CacheStorageParent_h
 #define mozilla_dom_cache_CacheStorageParent_h
 
+#include "mozilla/dom/cache/CacheInitData.h"
 #include "mozilla/dom/cache/PCacheStorageParent.h"
+#include "mozilla/dom/cache/Manager.h"
 #include "mozilla/dom/cache/PrincipalVerifier.h"
 #include "mozilla/dom/cache/Types.h"
 
+template <class T> class nsRefPtr;
+
 namespace mozilla {
 namespace dom {
 namespace cache {
 
+class CacheStreamControlParent;
 class ManagerId;
 
 class CacheStorageParent final : public PCacheStorageParent
                                , public PrincipalVerifier::Listener
+                               , public Manager::Listener
 {
 public:
   CacheStorageParent(PBackgroundParent* aManagingActor, Namespace aNamespace,
                      const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
   virtual ~CacheStorageParent();
 
 private:
   // PCacheStorageParent methods
-  virtual void
-  ActorDestroy(ActorDestroyReason aReason) override;
-
-  virtual PCacheOpParent*
-  AllocPCacheOpParent(const CacheOpArgs& aOpArgs) override;
-
-  virtual bool
-  DeallocPCacheOpParent(PCacheOpParent* aActor) override;
-
-  virtual bool
-  RecvPCacheOpConstructor(PCacheOpParent* actor,
-                          const CacheOpArgs& aOpArgs) override;
-
-  virtual bool
-  RecvTeardown() override;
+  virtual void ActorDestroy(ActorDestroyReason aReason) override;
+  virtual bool RecvTeardown() override;
+  virtual bool RecvMatch(const RequestId& aRequestId,
+                         const PCacheRequest& aRequest,
+                         const PCacheQueryParams& aParams) override;
+  virtual bool RecvHas(const RequestId& aRequestId,
+                       const nsString& aKey) override;
+  virtual bool RecvOpen(const RequestId& aRequestId,
+                        const nsString& aKey) override;
+  virtual bool RecvDelete(const RequestId& aRequestId,
+                          const nsString& aKey) override;
+  virtual bool RecvKeys(const RequestId& aRequestId) override;
 
   // PrincipalVerifier::Listener methods
   virtual void OnPrincipalVerified(nsresult aRv,
                                    ManagerId* aManagerId) override;
 
+  // Manager::Listener methods
+  virtual void OnStorageMatch(RequestId aRequestId, nsresult aRv,
+                              const SavedResponse* aResponse,
+                              StreamList* aStreamList) override;
+  virtual void OnStorageHas(RequestId aRequestId, nsresult aRv,
+                            bool aCacheFound) override;
+  virtual void OnStorageOpen(RequestId aRequestId, nsresult aRv,
+                             CacheId aCacheId) override;
+  virtual void OnStorageDelete(RequestId aRequestId, nsresult aRv,
+                               bool aCacheDeleted) override;
+  virtual void OnStorageKeys(RequestId aRequestId, nsresult aRv,
+                             const nsTArray<nsString>& aKeys) override;
+
+  CacheStreamControlParent*
+  SerializeReadStream(CacheStreamControlParent *aStreamControl, const nsID& aId,
+                      StreamList* aStreamList,
+                      PCacheReadStream* aReadStreamOut);
+
+  void RetryPendingRequests();
+
+  nsresult RequestManager(RequestId aRequestId, cache::Manager** aManagerOut);
+  void ReleaseManager(RequestId aRequestId);
+
   const Namespace mNamespace;
   nsRefPtr<PrincipalVerifier> mVerifier;
   nsresult mVerifiedStatus;
   nsRefPtr<ManagerId> mManagerId;
+  nsRefPtr<cache::Manager> mManager;
+
+  enum Op
+  {
+    OP_MATCH,
+    OP_HAS,
+    OP_OPEN,
+    OP_DELETE,
+    OP_KEYS
+  };
+
+  struct Entry
+  {
+    Op mOp;
+    RequestId mRequestId;
+    nsString mKey;
+    PCacheRequest mRequest;
+    PCacheQueryParams mParams;
+  };
+
+  nsTArray<Entry> mPendingRequests;
+  nsTArray<RequestId> mActiveRequests;
 };
 
 } // namesapce cache
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_cache_CacheStorageParent_h
--- a/dom/cache/CacheStreamControlChild.cpp
+++ b/dom/cache/CacheStreamControlChild.cpp
@@ -4,17 +4,17 @@
  * 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 "mozilla/dom/cache/CacheStreamControlChild.h"
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/unused.h"
 #include "mozilla/dom/cache/ActorUtils.h"
-#include "mozilla/dom/cache/CacheTypes.h"
+#include "mozilla/dom/cache/PCacheTypes.h"
 #include "mozilla/dom/cache/ReadStream.h"
 #include "mozilla/ipc/FileDescriptorSetChild.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "mozilla/ipc/PFileDescriptorSetChild.h"
 #include "nsISupportsImpl.h"
 
 namespace mozilla {
 namespace dom {
@@ -64,25 +64,25 @@ CacheStreamControlChild::StartDestroy()
   mDestroyStarted = true;
 
   // Begin shutting down all streams.  This is the same as if the parent had
   // asked us to shutdown.  So simulate the CloseAll IPC message.
   RecvCloseAll();
 }
 
 void
-CacheStreamControlChild::SerializeControl(CacheReadStream* aReadStreamOut)
+CacheStreamControlChild::SerializeControl(PCacheReadStream* aReadStreamOut)
 {
   NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
   aReadStreamOut->controlParent() = nullptr;
   aReadStreamOut->controlChild() = this;
 }
 
 void
-CacheStreamControlChild::SerializeFds(CacheReadStream* aReadStreamOut,
+CacheStreamControlChild::SerializeFds(PCacheReadStream* aReadStreamOut,
                                       const nsTArray<FileDescriptor>& aFds)
 {
   NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
   PFileDescriptorSetChild* fdSet = nullptr;
   if (!aFds.IsEmpty()) {
     fdSet = Manager()->SendPFileDescriptorSetConstructor(aFds[0]);
     for (uint32_t i = 1; i < aFds.Length(); ++i) {
       unused << fdSet->SendAddFileDescriptor(aFds[i]);
@@ -92,17 +92,17 @@ CacheStreamControlChild::SerializeFds(Ca
   if (fdSet) {
     aReadStreamOut->fds() = fdSet;
   } else {
     aReadStreamOut->fds() = void_t();
   }
 }
 
 void
-CacheStreamControlChild::DeserializeFds(const CacheReadStream& aReadStream,
+CacheStreamControlChild::DeserializeFds(const PCacheReadStream& aReadStream,
                                         nsTArray<FileDescriptor>& aFdsOut)
 {
   if (aReadStream.fds().type() !=
       OptionalFileDescriptorSet::TPFileDescriptorSetChild) {
     return;
   }
 
   auto fdSetActor = static_cast<FileDescriptorSetChild*>(
--- a/dom/cache/CacheStreamControlChild.h
+++ b/dom/cache/CacheStreamControlChild.h
@@ -26,24 +26,24 @@ public:
   CacheStreamControlChild();
   ~CacheStreamControlChild();
 
   // ActorChild methods
   virtual void StartDestroy() override;
 
   // StreamControl methods
   virtual void
-  SerializeControl(CacheReadStream* aReadStreamOut) override;
+  SerializeControl(PCacheReadStream* aReadStreamOut) override;
 
   virtual void
-  SerializeFds(CacheReadStream* aReadStreamOut,
+  SerializeFds(PCacheReadStream* aReadStreamOut,
                const nsTArray<mozilla::ipc::FileDescriptor>& aFds) override;
 
   virtual void
-  DeserializeFds(const CacheReadStream& aReadStream,
+  DeserializeFds(const PCacheReadStream& aReadStream,
                  nsTArray<mozilla::ipc::FileDescriptor>& aFdsOut) override;
 
 private:
   virtual void
   NoteClosedAfterForget(const nsID& aId) override;
 
 #ifdef DEBUG
   virtual void
--- a/dom/cache/CacheStreamControlParent.cpp
+++ b/dom/cache/CacheStreamControlParent.cpp
@@ -3,17 +3,17 @@
 /* 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 "mozilla/dom/cache/CacheStreamControlParent.h"
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/unused.h"
-#include "mozilla/dom/cache/CacheTypes.h"
+#include "mozilla/dom/cache/PCacheTypes.h"
 #include "mozilla/dom/cache/ReadStream.h"
 #include "mozilla/dom/cache/StreamList.h"
 #include "mozilla/ipc/FileDescriptorSetParent.h"
 #include "mozilla/ipc/PBackgroundParent.h"
 #include "mozilla/ipc/PFileDescriptorSetParent.h"
 #include "nsISupportsImpl.h"
 
 namespace mozilla {
@@ -40,25 +40,25 @@ CacheStreamControlParent::CacheStreamCon
 CacheStreamControlParent::~CacheStreamControlParent()
 {
   NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
   MOZ_ASSERT(!mStreamList);
   MOZ_COUNT_DTOR(cache::CacheStreamControlParent);
 }
 
 void
-CacheStreamControlParent::SerializeControl(CacheReadStream* aReadStreamOut)
+CacheStreamControlParent::SerializeControl(PCacheReadStream* aReadStreamOut)
 {
   NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
   aReadStreamOut->controlChild() = nullptr;
   aReadStreamOut->controlParent() = this;
 }
 
 void
-CacheStreamControlParent::SerializeFds(CacheReadStream* aReadStreamOut,
+CacheStreamControlParent::SerializeFds(PCacheReadStream* aReadStreamOut,
                                        const nsTArray<FileDescriptor>& aFds)
 {
   NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
   PFileDescriptorSetParent* fdSet = nullptr;
   if (!aFds.IsEmpty()) {
     fdSet = Manager()->SendPFileDescriptorSetConstructor(aFds[0]);
     for (uint32_t i = 1; i < aFds.Length(); ++i) {
       unused << fdSet->SendAddFileDescriptor(aFds[i]);
@@ -68,17 +68,17 @@ CacheStreamControlParent::SerializeFds(C
   if (fdSet) {
     aReadStreamOut->fds() = fdSet;
   } else {
     aReadStreamOut->fds() = void_t();
   }
 }
 
 void
-CacheStreamControlParent::DeserializeFds(const CacheReadStream& aReadStream,
+CacheStreamControlParent::DeserializeFds(const PCacheReadStream& aReadStream,
                                          nsTArray<FileDescriptor>& aFdsOut)
 {
   if (aReadStream.fds().type() !=
       OptionalFileDescriptorSet::TPFileDescriptorSetParent) {
     return;
   }
 
   FileDescriptorSetParent* fdSetActor =
--- a/dom/cache/CacheStreamControlParent.h
+++ b/dom/cache/CacheStreamControlParent.h
@@ -27,24 +27,24 @@ public:
 
   void SetStreamList(StreamList* aStreamList);
   void Close(const nsID& aId);
   void CloseAll();
   void Shutdown();
 
   // StreamControl methods
   virtual void
-  SerializeControl(CacheReadStream* aReadStreamOut) override;
+  SerializeControl(PCacheReadStream* aReadStreamOut) override;
 
   virtual void
-  SerializeFds(CacheReadStream* aReadStreamOut,
+  SerializeFds(PCacheReadStream* aReadStreamOut,
                const nsTArray<mozilla::ipc::FileDescriptor>& aFds) override;
 
   virtual void
-  DeserializeFds(const CacheReadStream& aReadStream,
+  DeserializeFds(const PCacheReadStream& aReadStream,
                  nsTArray<mozilla::ipc::FileDescriptor>& aFdsOut) override;
 
 private:
   virtual void
   NoteClosedAfterForget(const nsID& aId) override;
 
 #ifdef DEBUG
   virtual void
--- a/dom/cache/DBAction.cpp
+++ b/dom/cache/DBAction.cpp
@@ -9,17 +9,16 @@
 #include "mozilla/dom/quota/PersistenceType.h"
 #include "mozilla/net/nsFileProtocolHandler.h"
 #include "mozIStorageConnection.h"
 #include "mozIStorageService.h"
 #include "mozStorageCID.h"
 #include "nsIFile.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
-#include "nsThreadUtils.h"
 #include "DBSchema.h"
 #include "FileUtils.h"
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 using mozilla::dom::quota::PERSISTENCE_TYPE_DEFAULT;
--- a/dom/cache/DBAction.h
+++ b/dom/cache/DBAction.h
@@ -3,16 +3,17 @@
 /* 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 mozilla_dom_cache_DBAction_h
 #define mozilla_dom_cache_DBAction_h
 
 #include "mozilla/dom/cache/Action.h"
+#include "mozilla/dom/cache/CacheInitData.h"
 #include "nsRefPtr.h"
 #include "nsString.h"
 
 class mozIStorageConnection;
 class nsIFile;
 
 namespace mozilla {
 namespace dom {
--- a/dom/cache/DBSchema.cpp
+++ b/dom/cache/DBSchema.cpp
@@ -3,29 +3,28 @@
 /* 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 "mozilla/dom/cache/DBSchema.h"
 
 #include "ipc/IPCMessageUtils.h"
 #include "mozilla/dom/InternalHeaders.h"
-#include "mozilla/dom/cache/CacheTypes.h"
+#include "mozilla/dom/cache/PCacheTypes.h"
 #include "mozilla/dom/cache/SavedTypes.h"
-#include "mozilla/dom/cache/Types.h"
-#include "mozilla/dom/cache/TypeUtils.h"
 #include "mozIStorageConnection.h"
 #include "mozIStorageStatement.h"
 #include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "nsCRT.h"
 #include "nsHttp.h"
 #include "mozilla/dom/HeadersBinding.h"
 #include "mozilla/dom/RequestBinding.h"
 #include "mozilla/dom/ResponseBinding.h"
+#include "Types.h"
 #include "nsIContentPolicy.h"
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 const int32_t DBSchema::kMaxWipeSchemaVersion = 6;
 const int32_t DBSchema::kLatestSchemaVersion = 6;
@@ -413,18 +412,18 @@ DBSchema::IsCacheOrphaned(mozIStorageCon
   *aOrphanedOut = refCount == 0;
 
   return rv;
 }
 
 // static
 nsresult
 DBSchema::CacheMatch(mozIStorageConnection* aConn, CacheId aCacheId,
-                     const CacheRequest& aRequest,
-                     const CacheQueryParams& aParams,
+                     const PCacheRequest& aRequest,
+                     const PCacheQueryParams& aParams,
                      bool* aFoundResponseOut,
                      SavedResponse* aSavedResponseOut)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aConn);
   MOZ_ASSERT(aFoundResponseOut);
   MOZ_ASSERT(aSavedResponseOut);
 
@@ -445,26 +444,26 @@ DBSchema::CacheMatch(mozIStorageConnecti
   *aFoundResponseOut = true;
 
   return rv;
 }
 
 // static
 nsresult
 DBSchema::CacheMatchAll(mozIStorageConnection* aConn, CacheId aCacheId,
-                        const CacheRequestOrVoid& aRequestOrVoid,
-                        const CacheQueryParams& aParams,
+                        const PCacheRequestOrVoid& aRequestOrVoid,
+                        const PCacheQueryParams& aParams,
                         nsTArray<SavedResponse>& aSavedResponsesOut)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aConn);
   nsresult rv;
 
   nsAutoTArray<EntryId, 256> matches;
-  if (aRequestOrVoid.type() == CacheRequestOrVoid::Tvoid_t) {
+  if (aRequestOrVoid.type() == PCacheRequestOrVoid::Tvoid_t) {
     rv = QueryAll(aConn, aCacheId, matches);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
   } else {
     rv = QueryCache(aConn, aCacheId, aRequestOrVoid, aParams, matches);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
   }
 
   // TODO: replace this with a bulk load using SQL IN clause (bug 1110458)
@@ -477,26 +476,26 @@ DBSchema::CacheMatchAll(mozIStorageConne
   }
 
   return rv;
 }
 
 // static
 nsresult
 DBSchema::CachePut(mozIStorageConnection* aConn, CacheId aCacheId,
-                   const CacheRequest& aRequest,
+                   const PCacheRequest& aRequest,
                    const nsID* aRequestBodyId,
-                   const CacheResponse& aResponse,
+                   const PCacheResponse& aResponse,
                    const nsID* aResponseBodyId,
                    nsTArray<nsID>& aDeletedBodyIdListOut)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aConn);
 
-  CacheQueryParams params(false, false, false, false,
+  PCacheQueryParams params(false, false, false, false,
                            NS_LITERAL_STRING(""));
   nsAutoTArray<EntryId, 256> matches;
   nsresult rv = QueryCache(aConn, aCacheId, aRequest, params, matches);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   rv = DeleteEntries(aConn, matches, aDeletedBodyIdListOut);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
@@ -505,18 +504,18 @@ DBSchema::CachePut(mozIStorageConnection
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   return rv;
 }
 
 // static
 nsresult
 DBSchema::CacheDelete(mozIStorageConnection* aConn, CacheId aCacheId,
-                      const CacheRequest& aRequest,
-                      const CacheQueryParams& aParams,
+                      const PCacheRequest& aRequest,
+                      const PCacheQueryParams& aParams,
                       nsTArray<nsID>& aDeletedBodyIdListOut, bool* aSuccessOut)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aConn);
   MOZ_ASSERT(aSuccessOut);
 
   *aSuccessOut = false;
 
@@ -534,26 +533,26 @@ DBSchema::CacheDelete(mozIStorageConnect
   *aSuccessOut = true;
 
   return rv;
 }
 
 // static
 nsresult
 DBSchema::CacheKeys(mozIStorageConnection* aConn, CacheId aCacheId,
-                    const CacheRequestOrVoid& aRequestOrVoid,
-                    const CacheQueryParams& aParams,
+                    const PCacheRequestOrVoid& aRequestOrVoid,
+                    const PCacheQueryParams& aParams,
                     nsTArray<SavedRequest>& aSavedRequestsOut)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aConn);
   nsresult rv;
 
   nsAutoTArray<EntryId, 256> matches;
-  if (aRequestOrVoid.type() == CacheRequestOrVoid::Tvoid_t) {
+  if (aRequestOrVoid.type() == PCacheRequestOrVoid::Tvoid_t) {
     rv = QueryAll(aConn, aCacheId, matches);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
   } else {
     rv = QueryCache(aConn, aCacheId, aRequestOrVoid, aParams, matches);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
   }
 
   // TODO: replace this with a bulk load using SQL IN clause (bug 1110458)
@@ -567,18 +566,18 @@ DBSchema::CacheKeys(mozIStorageConnectio
 
   return rv;
 }
 
 // static
 nsresult
 DBSchema::StorageMatch(mozIStorageConnection* aConn,
                        Namespace aNamespace,
-                       const CacheRequest& aRequest,
-                       const CacheQueryParams& aParams,
+                       const PCacheRequest& aRequest,
+                       const PCacheQueryParams& aParams,
                        bool* aFoundResponseOut,
                        SavedResponse* aSavedResponseOut)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aConn);
   MOZ_ASSERT(aFoundResponseOut);
   MOZ_ASSERT(aSavedResponseOut);
 
@@ -789,18 +788,18 @@ DBSchema::QueryAll(mozIStorageConnection
   }
 
   return rv;
 }
 
 // static
 nsresult
 DBSchema::QueryCache(mozIStorageConnection* aConn, CacheId aCacheId,
-                     const CacheRequest& aRequest,
-                     const CacheQueryParams& aParams,
+                     const PCacheRequest& aRequest,
+                     const PCacheQueryParams& aParams,
                      nsTArray<EntryId>& aEntryIdListOut,
                      uint32_t aMaxResults)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aConn);
   MOZ_ASSERT(aMaxResults > 0);
 
   if (!aParams.ignoreMethod() && !aRequest.method().LowerCaseEqualsLiteral("get")
@@ -867,17 +866,17 @@ DBSchema::QueryCache(mozIStorageConnecti
   }
 
   return rv;
 }
 
 // static
 nsresult
 DBSchema::MatchByVaryHeader(mozIStorageConnection* aConn,
-                            const CacheRequest& aRequest,
+                            const PCacheRequest& aRequest,
                             EntryId entryId, bool* aSuccessOut)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aConn);
 
   *aSuccessOut = false;
 
   nsCOMPtr<mozIStorageStatement> state;
@@ -909,36 +908,34 @@ DBSchema::MatchByVaryHeader(mozIStorageC
     "SELECT name, value FROM request_headers "
     "WHERE entry_id=?1;"
   ), getter_AddRefs(state));
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   rv = state->BindInt32Parameter(0, entryId);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
-  nsRefPtr<InternalHeaders> cachedHeaders =
-    new InternalHeaders(HeadersGuardEnum::None);
+  nsRefPtr<InternalHeaders> cachedHeaders = new InternalHeaders(HeadersGuardEnum::None);
 
   while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) {
     nsAutoCString name;
     nsAutoCString value;
     rv = state->GetUTF8String(0, name);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
     rv = state->GetUTF8String(1, value);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     ErrorResult errorResult;
 
     cachedHeaders->Append(name, value, errorResult);
     if (errorResult.Failed()) { return errorResult.ErrorCode(); };
   }
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
-  nsRefPtr<InternalHeaders> queryHeaders =
-    TypeUtils::ToInternalHeaders(aRequest.headers());
+  nsRefPtr<InternalHeaders> queryHeaders = new InternalHeaders(aRequest.headers());
 
   // Assume the vary headers match until we find a conflict
   bool varyHeadersMatch = true;
 
   for (uint32_t i = 0; i < varyValues.Length(); ++i) {
     // Extract the header names inside the Vary header value.
     nsAutoCString varyValue(varyValues[i]);
     char* rawBuffer = varyValue.BeginWriting();
@@ -1069,19 +1066,19 @@ DBSchema::DeleteEntries(mozIStorageConne
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   return rv;
 }
 
 // static
 nsresult
 DBSchema::InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
-                      const CacheRequest& aRequest,
+                      const PCacheRequest& aRequest,
                       const nsID* aRequestBodyId,
-                      const CacheResponse& aResponse,
+                      const PCacheResponse& aResponse,
                       const nsID* aResponseBodyId)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aConn);
 
   nsCOMPtr<mozIStorageStatement> state;
   nsresult rv = aConn->CreateStatement(NS_LITERAL_CSTRING(
     "INSERT INTO entries ("
@@ -1193,17 +1190,17 @@ DBSchema::InsertEntry(mozIStorageConnect
     "INSERT INTO request_headers ("
       "name, "
       "value, "
       "entry_id "
     ") VALUES (?1, ?2, ?3)"
   ), getter_AddRefs(state));
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
-  const nsTArray<HeadersEntry>& requestHeaders = aRequest.headers();
+  const nsTArray<PHeadersEntry>& requestHeaders = aRequest.headers();
   for (uint32_t i = 0; i < requestHeaders.Length(); ++i) {
     rv = state->BindUTF8StringParameter(0, requestHeaders[i].name());
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     rv = state->BindUTF8StringParameter(1, requestHeaders[i].value());
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     rv = state->BindInt32Parameter(2, entryId);
@@ -1217,17 +1214,17 @@ DBSchema::InsertEntry(mozIStorageConnect
     "INSERT INTO response_headers ("
       "name, "
       "value, "
       "entry_id "
     ") VALUES (?1, ?2, ?3)"
   ), getter_AddRefs(state));
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
-  const nsTArray<HeadersEntry>& responseHeaders = aResponse.headers();
+  const nsTArray<PHeadersEntry>& responseHeaders = aResponse.headers();
   for (uint32_t i = 0; i < responseHeaders.Length(); ++i) {
     rv = state->BindUTF8StringParameter(0, responseHeaders[i].name());
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     rv = state->BindUTF8StringParameter(1, responseHeaders[i].value());
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     rv = state->BindInt32Parameter(2, entryId);
@@ -1318,17 +1315,17 @@ DBSchema::ReadResponse(mozIStorageConnec
     "WHERE entry_id=?1;"
   ), getter_AddRefs(state));
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   rv = state->BindInt32Parameter(0, aEntryId);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) {
-    HeadersEntry header;
+    PHeadersEntry header;
 
     rv = state->GetUTF8String(0, header.name());
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     rv = state->GetUTF8String(1, header.value());
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     aSavedResponseOut->mValue.headers().AppendElement(header);
@@ -1437,17 +1434,17 @@ DBSchema::ReadRequest(mozIStorageConnect
     "WHERE entry_id=?1;"
   ), getter_AddRefs(state));
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   rv = state->BindInt32Parameter(0, aEntryId);
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   while (NS_SUCCEEDED(state->ExecuteStep(&hasMoreData)) && hasMoreData) {
-    HeadersEntry header;
+    PHeadersEntry header;
 
     rv = state->GetUTF8String(0, header.name());
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     rv = state->GetUTF8String(1, header.value());
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     aSavedRequestOut->mValue.headers().AppendElement(header);
--- a/dom/cache/DBSchema.h
+++ b/dom/cache/DBSchema.h
@@ -16,20 +16,20 @@
 class mozIStorageConnection;
 class mozIStorageStatement;
 struct nsID;
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
-class CacheQueryParams;
-class CacheRequest;
-class CacheRequestOrVoid;
-class CacheResponse;
+class PCacheQueryParams;
+class PCacheRequest;
+class PCacheRequestOrVoid;
+class PCacheResponse;
 struct SavedRequest;
 struct SavedResponse;
 
 // TODO: remove static class and use functions in cache namespace (bug 1110485)
 class DBSchema final
 {
 public:
   static nsresult CreateSchema(mozIStorageConnection* aConn);
@@ -41,44 +41,44 @@ public:
   static nsresult DeleteCache(mozIStorageConnection* aConn, CacheId aCacheId,
                               nsTArray<nsID>& aDeletedBodyIdListOut);
 
   // TODO: Consider removing unused IsCacheOrphaned after writing cleanup code. (bug 1110446)
   static nsresult IsCacheOrphaned(mozIStorageConnection* aConn,
                                   CacheId aCacheId, bool* aOrphanedOut);
 
   static nsresult CacheMatch(mozIStorageConnection* aConn, CacheId aCacheId,
-                             const CacheRequest& aRequest,
-                             const CacheQueryParams& aParams,
+                             const PCacheRequest& aRequest,
+                             const PCacheQueryParams& aParams,
                              bool* aFoundResponseOut,
                              SavedResponse* aSavedResponseOut);
   static nsresult CacheMatchAll(mozIStorageConnection* aConn, CacheId aCacheId,
-                                const CacheRequestOrVoid& aRequestOrVoid,
-                                const CacheQueryParams& aParams,
+                                const PCacheRequestOrVoid& aRequestOrVoid,
+                                const PCacheQueryParams& aParams,
                                 nsTArray<SavedResponse>& aSavedResponsesOut);
   static nsresult CachePut(mozIStorageConnection* aConn, CacheId aCacheId,
-                           const CacheRequest& aRequest,
+                           const PCacheRequest& aRequest,
                            const nsID* aRequestBodyId,
-                           const CacheResponse& aResponse,
+                           const PCacheResponse& aResponse,
                            const nsID* aResponseBodyId,
                            nsTArray<nsID>& aDeletedBodyIdListOut);
   static nsresult CacheDelete(mozIStorageConnection* aConn, CacheId aCacheId,
-                              const CacheRequest& aRequest,
-                              const CacheQueryParams& aParams,
+                              const PCacheRequest& aRequest,
+                              const PCacheQueryParams& aParams,
                               nsTArray<nsID>& aDeletedBodyIdListOut,
                               bool* aSuccessOut);
   static nsresult CacheKeys(mozIStorageConnection* aConn, CacheId aCacheId,
-                            const CacheRequestOrVoid& aRequestOrVoid,
-                            const CacheQueryParams& aParams,
+                            const PCacheRequestOrVoid& aRequestOrVoid,
+                            const PCacheQueryParams& aParams,
                             nsTArray<SavedRequest>& aSavedRequestsOut);
 
   static nsresult StorageMatch(mozIStorageConnection* aConn,
                                Namespace aNamespace,
-                               const CacheRequest& aRequest,
-                               const CacheQueryParams& aParams,
+                               const PCacheRequest& aRequest,
+                               const PCacheQueryParams& aParams,
                                bool* aFoundResponseOut,
                                SavedResponse* aSavedResponseOut);
   static nsresult StorageGetCacheId(mozIStorageConnection* aConn,
                                     Namespace aNamespace, const nsAString& aKey,
                                     bool* aFoundCacheOut, CacheId* aCacheIdOut);
   static nsresult StoragePutCache(mozIStorageConnection* aConn,
                                   Namespace aNamespace, const nsAString& aKey,
                                   CacheId aCacheId);
@@ -93,31 +93,31 @@ public:
   static const int32_t kMaxWipeSchemaVersion;
 
 private:
   typedef int32_t EntryId;
 
   static nsresult QueryAll(mozIStorageConnection* aConn, CacheId aCacheId,
                            nsTArray<EntryId>& aEntryIdListOut);
   static nsresult QueryCache(mozIStorageConnection* aConn, CacheId aCacheId,
-                             const CacheRequest& aRequest,
-                             const CacheQueryParams& aParams,
+                             const PCacheRequest& aRequest,
+                             const PCacheQueryParams& aParams,
                              nsTArray<EntryId>& aEntryIdListOut,
                              uint32_t aMaxResults = UINT32_MAX);
   static nsresult MatchByVaryHeader(mozIStorageConnection* aConn,
-                                    const CacheRequest& aRequest,
+                                    const PCacheRequest& aRequest,
                                     EntryId entryId, bool* aSuccessOut);
   static nsresult DeleteEntries(mozIStorageConnection* aConn,
                                 const nsTArray<EntryId>& aEntryIdList,
                                 nsTArray<nsID>& aDeletedBodyIdListOut,
                                 uint32_t aPos=0, int32_t aLen=-1);
   static nsresult InsertEntry(mozIStorageConnection* aConn, CacheId aCacheId,
-                              const CacheRequest& aRequest,
+                              const PCacheRequest& aRequest,
                               const nsID* aRequestBodyId,
-                              const CacheResponse& aResponse,
+                              const PCacheResponse& aResponse,
                               const nsID* aResponseBodyId);
   static nsresult ReadResponse(mozIStorageConnection* aConn, EntryId aEntryId,
                                SavedResponse* aSavedResponseOut);
   static nsresult ReadRequest(mozIStorageConnection* aConn, EntryId aEntryId,
                               SavedRequest* aSavedRequestOut);
 
   static void AppendListParamsToQuery(nsACString& aQuery,
                                       const nsTArray<EntryId>& aEntryIdList,
--- a/dom/cache/FetchPut.cpp
+++ b/dom/cache/FetchPut.cpp
@@ -11,16 +11,17 @@
 #include "mozilla/dom/Headers.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/dom/Request.h"
 #include "mozilla/dom/Response.h"
 #include "mozilla/dom/ResponseBinding.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/cache/ManagerId.h"
+#include "mozilla/dom/cache/PCacheTypes.h"
 #include "nsContentUtils.h"
 #include "nsNetUtil.h"
 #include "nsThreadUtils.h"
 #include "nsCRT.h"
 #include "nsHttp.h"
 
 namespace mozilla {
 namespace dom {
@@ -84,33 +85,34 @@ protected:
 
 private:
   nsRefPtr<FetchPut> mFetchPut;
   nsRefPtr<InternalResponse> mInternalResponse;
 };
 
 // static
 nsresult
-FetchPut::Create(Listener* aListener, Manager* aManager, CacheId aCacheId,
-                 const nsTArray<CacheRequest>& aRequests,
+FetchPut::Create(Listener* aListener, Manager* aManager,
+                 RequestId aRequestId, CacheId aCacheId,
+                 const nsTArray<PCacheRequest>& aRequests,
                  const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreams,
                  FetchPut** aFetchPutOut)
 {
   MOZ_ASSERT(aRequests.Length() == aRequestStreams.Length());
 
   // The FetchDriver requires that all requests have a referrer already set.
 #ifdef DEBUG
   for (uint32_t i = 0; i < aRequests.Length(); ++i) {
     if (aRequests[i].referrer() == EmptyString()) {
       return NS_ERROR_UNEXPECTED;
     }
   }
 #endif
 
-  nsRefPtr<FetchPut> ref = new FetchPut(aListener, aManager, aCacheId,
+  nsRefPtr<FetchPut> ref = new FetchPut(aListener, aManager, aRequestId, aCacheId,
                                         aRequests, aRequestStreams);
 
   nsresult rv = ref->DispatchToMainThread();
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   ref.forget(aFetchPutOut);
 
   return NS_OK;
@@ -118,34 +120,36 @@ FetchPut::Create(Listener* aListener, Ma
 
 void
 FetchPut::ClearListener()
 {
   MOZ_ASSERT(mListener);
   mListener = nullptr;
 }
 
-FetchPut::FetchPut(Listener* aListener, Manager* aManager, CacheId aCacheId,
-                   const nsTArray<CacheRequest>& aRequests,
+FetchPut::FetchPut(Listener* aListener, Manager* aManager,
+                   RequestId aRequestId, CacheId aCacheId,
+                   const nsTArray<PCacheRequest>& aRequests,
                    const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreams)
   : mListener(aListener)
   , mManager(aManager)
+  , mRequestId(aRequestId)
   , mCacheId(aCacheId)
   , mInitiatingThread(NS_GetCurrentThread())
   , mStateList(aRequests.Length())
   , mPendingCount(0)
   , mResult(NS_OK)
 {
   MOZ_ASSERT(mListener);
   MOZ_ASSERT(mManager);
   MOZ_ASSERT(aRequests.Length() == aRequestStreams.Length());
 
   for (uint32_t i = 0; i < aRequests.Length(); ++i) {
     State* s = mStateList.AppendElement();
-    s->mCacheRequest = aRequests[i];
+    s->mPCacheRequest = aRequests[i];
     s->mRequestStream = aRequestStreams[i];
   }
 
   mManager->AddRefCacheId(mCacheId);
 }
 
 FetchPut::~FetchPut()
 {
@@ -201,17 +205,17 @@ FetchPut::DoFetchOnMainThread()
   if (NS_WARN_IF(NS_FAILED(rv))) {
     MaybeSetError(rv);
     MaybeCompleteOnMainThread();
     return;
   }
 
   for (uint32_t i = 0; i < mStateList.Length(); ++i) {
     nsRefPtr<InternalRequest> internalRequest =
-      ToInternalRequest(mStateList[i].mCacheRequest);
+      ToInternalRequest(mStateList[i].mPCacheRequest);
 
     // If there is a stream we must clone it so that its still available
     // to store in the cache later;
     if (mStateList[i].mRequestStream) {
       internalRequest->SetBody(mStateList[i].mRequestStream);
       nsRefPtr<InternalRequest> clone = internalRequest->Clone();
 
       // The copy construction clone above can change the source stream,
@@ -247,17 +251,17 @@ FetchPut::FetchComplete(FetchObserver* a
 
   if (aInternalResponse->IsError() && NS_SUCCEEDED(mResult)) {
     MaybeSetError(NS_ERROR_FAILURE);
   }
 
   for (uint32_t i = 0; i < mStateList.Length(); ++i) {
     if (mStateList[i].mFetchObserver == aObserver) {
       ErrorResult rv;
-      ToCacheResponseWithoutBody(mStateList[i].mCacheResponse,
+      ToPCacheResponseWithoutBody(mStateList[i].mPCacheResponse,
                                   *aInternalResponse, rv);
       if (rv.Failed()) {
         MaybeSetError(rv.ErrorCode());
         return;
       }
       aInternalResponse->GetBody(getter_AddRefs(mStateList[i].mResponseStream));
       mStateList[i].mFetchObserver = nullptr;
       MOZ_ASSERT(mPendingCount > 0);
@@ -299,67 +303,67 @@ FetchPut::DoPutOnWorkerThread()
 
   putList.SetCapacity(mStateList.Length());
   requestStreamList.SetCapacity(mStateList.Length());
   responseStreamList.SetCapacity(mStateList.Length());
 
   for (uint32_t i = 0; i < mStateList.Length(); ++i) {
     // The spec requires us to catch if content tries to insert a set of
     // requests that would overwrite each other.
-    if (MatchInPutList(mStateList[i].mCacheRequest, putList)) {
+    if (MatchInPutList(mStateList[i].mPCacheRequest, putList)) {
       MaybeSetError(NS_ERROR_DOM_INVALID_STATE_ERR);
       MaybeNotifyListener();
       return;
     }
 
     CacheRequestResponse* entry = putList.AppendElement();
-    entry->request() = mStateList[i].mCacheRequest;
-    entry->response() = mStateList[i].mCacheResponse;
+    entry->request() = mStateList[i].mPCacheRequest;
+    entry->response() = mStateList[i].mPCacheResponse;
     requestStreamList.AppendElement(mStateList[i].mRequestStream.forget());
     responseStreamList.AppendElement(mStateList[i].mResponseStream.forget());
   }
   mStateList.Clear();
 
-  mManager->ExecutePutAll(this, mCacheId, putList, requestStreamList,
-                          responseStreamList);
+  mManager->CachePutAll(this, mRequestId, mCacheId, putList, requestStreamList,
+                        responseStreamList);
 }
 
 // static
 bool
-FetchPut::MatchInPutList(const CacheRequest& aRequest,
+FetchPut::MatchInPutList(const PCacheRequest& aRequest,
                          const nsTArray<CacheRequestResponse>& aPutList)
 {
   // This method implements the SW spec QueryCache algorithm against an
   // in memory array of Request/Response objects.  This essentially the
   // same algorithm that is implemented in DBSchema.cpp.  Unfortunately
   // we cannot unify them because when operating against the real database
   // we don't want to load all request/response objects into memory.
 
   if (!aRequest.method().LowerCaseEqualsLiteral("get") &&
       !aRequest.method().LowerCaseEqualsLiteral("head")) {
     return false;
   }
 
   nsRefPtr<InternalHeaders> requestHeaders =
-    ToInternalHeaders(aRequest.headers());
+    new InternalHeaders(aRequest.headers());
 
   for (uint32_t i = 0; i < aPutList.Length(); ++i) {
-    const CacheRequest& cachedRequest = aPutList[i].request();
-    const CacheResponse& cachedResponse = aPutList[i].response();
+    const PCacheRequest& cachedRequest = aPutList[i].request();
+    const PCacheResponse& cachedResponse = aPutList[i].response();
 
     // If the URLs don't match, then just skip to the next entry.
     if (aRequest.url() != cachedRequest.url()) {
       continue;
     }
 
     nsRefPtr<InternalHeaders> cachedRequestHeaders =
-      ToInternalHeaders(cachedRequest.headers());
+      new InternalHeaders(cachedRequest.headers());
 
     nsRefPtr<InternalHeaders> cachedResponseHeaders =
-      ToInternalHeaders(cachedResponse.headers());
+      new InternalHeaders(cachedResponse.headers());
 
     nsAutoTArray<nsCString, 16> varyHeaders;
     ErrorResult rv;
     cachedResponseHeaders->GetAll(NS_LITERAL_CSTRING("vary"), varyHeaders, rv);
     MOZ_ALWAYS_TRUE(!rv.Failed());
 
     // Assume the vary headers match until we find a conflict
     bool varyHeadersMatch = true;
@@ -409,24 +413,19 @@ FetchPut::MatchInPutList(const CacheRequ
       return true;
     }
   }
 
   return false;
 }
 
 void
-FetchPut::OnOpComplete(nsresult aRv, const CacheOpResult& aResult,
-                       CacheId aOpenedCacheId,
-                       const nsTArray<SavedResponse>& aSavedResponseList,
-                       const nsTArray<SavedRequest>& aSavedRequestList,
-                       StreamList* aStreamList)
+FetchPut::OnCachePutAll(RequestId aRequestId, nsresult aRv)
 {
   MOZ_ASSERT(mInitiatingThread == NS_GetCurrentThread());
-  MOZ_ASSERT(aResult.type() == CacheOpResult::TCachePutAllResult);
   MaybeSetError(aRv);
   MaybeNotifyListener();
 }
 
 void
 FetchPut::MaybeSetError(nsresult aRv)
 {
   if (NS_FAILED(mResult) || NS_SUCCEEDED(aRv)) {
@@ -437,17 +436,17 @@ FetchPut::MaybeSetError(nsresult aRv)
 
 void
 FetchPut::MaybeNotifyListener()
 {
   MOZ_ASSERT(mInitiatingThread == NS_GetCurrentThread());
   if (!mListener) {
     return;
   }
-  mListener->OnFetchPut(this, mResult);
+  mListener->OnFetchPut(this, mRequestId, mResult);
 }
 
 nsIGlobalObject*
 FetchPut::GetGlobalObject() const
 {
   MOZ_CRASH("No global object in parent-size FetchPut operation!");
 }
 
--- a/dom/cache/FetchPut.h
+++ b/dom/cache/FetchPut.h
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_cache_FetchPut_h
 #define mozilla_dom_cache_FetchPut_h
 
 #include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/cache/Manager.h"
-#include "mozilla/dom/cache/CacheTypes.h"
+#include "mozilla/dom/cache/PCacheTypes.h"
 #include "mozilla/dom/cache/Types.h"
 #include "mozilla/dom/cache/TypeUtils.h"
 #include "nsRefPtr.h"
 #include "nsTArray.h"
 #include <utility>
 
 class nsIInputStream;
 class nsIRunnable;
@@ -34,80 +34,77 @@ class FetchPut final : public Manager::L
 {
 public:
   typedef std::pair<nsRefPtr<Request>, nsRefPtr<Response>> PutPair;
 
   class Listener
   {
   public:
     virtual void
-    OnFetchPut(FetchPut* aFetchPut, nsresult aRv) = 0;
+    OnFetchPut(FetchPut* aFetchPut, RequestId aRequestId, nsresult aRv) = 0;
   };
 
   static nsresult
-  Create(Listener* aListener, Manager* aManager, CacheId aCacheId,
-         const nsTArray<CacheRequest>& aRequests,
+  Create(Listener* aListener, Manager* aManager,
+         RequestId aRequestId, CacheId aCacheId,
+         const nsTArray<PCacheRequest>& aRequests,
          const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreams,
          FetchPut** aFetchPutOut);
 
   void ClearListener();
 
 private:
   class Runnable;
   class FetchObserver;
   struct State
   {
-    CacheRequest mCacheRequest;
+    PCacheRequest mPCacheRequest;
     nsCOMPtr<nsIInputStream> mRequestStream;
     nsRefPtr<FetchObserver> mFetchObserver;
-    CacheResponse mCacheResponse;
+    PCacheResponse mPCacheResponse;
     nsCOMPtr<nsIInputStream> mResponseStream;
 
     nsRefPtr<Request> mRequest;
     nsRefPtr<Response> mResponse;
   };
 
-  FetchPut(Listener* aListener, Manager* aManager, CacheId aCacheId,
-           const nsTArray<CacheRequest>& aRequests,
+  FetchPut(Listener* aListener, Manager* aManager,
+           RequestId aRequestId, CacheId aCacheId,
+           const nsTArray<PCacheRequest>& aRequests,
            const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreams);
   ~FetchPut();
 
   nsresult DispatchToMainThread();
   void DispatchToInitiatingThread();
 
   void DoFetchOnMainThread();
   void FetchComplete(FetchObserver* aObserver,
                      InternalResponse* aInternalResponse);
   void MaybeCompleteOnMainThread();
 
   void DoPutOnWorkerThread();
-  static bool MatchInPutList(const CacheRequest& aRequest,
+  static bool MatchInPutList(const PCacheRequest& aRequest,
                              const nsTArray<CacheRequestResponse>& aPutList);
-
-  virtual void
-  OnOpComplete(nsresult aRv, const CacheOpResult& aResult,
-               CacheId aOpenedCacheId,
-               const nsTArray<SavedResponse>& aSavedResponseList,
-               const nsTArray<SavedRequest>& aSavedRequestList,
-               StreamList* aStreamList) override;
+  virtual void OnCachePutAll(RequestId aRequestId, nsresult aRv) override;
 
   void MaybeSetError(nsresult aRv);
   void MaybeNotifyListener();
 
   // TypeUtils methods
   virtual nsIGlobalObject* GetGlobalObject() const override;
 #ifdef DEBUG
   virtual void AssertOwningThread() const override;
 #endif
 
   virtual CachePushStreamChild*
   CreatePushStream(nsIAsyncInputStream* aStream) override;
 
   Listener* mListener;
   nsRefPtr<Manager> mManager;
+  const RequestId mRequestId;
   const CacheId mCacheId;
   nsCOMPtr<nsIThread> mInitiatingThread;
   nsTArray<State> mStateList;
   uint32_t mPendingCount;
   nsresult mResult;
   nsCOMPtr<nsIRunnable> mRunnable;
 
 public:
--- a/dom/cache/IPCUtils.h
+++ b/dom/cache/IPCUtils.h
@@ -3,57 +3,20 @@
 /* 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 mozilla_dom_cache_IPCUtils_h
 #define mozilla_dom_cache_IPCUtils_h
 
 #include "ipc/IPCMessageUtils.h"
-
-// Fix X11 header brain damage that conflicts with HeadersGuardEnum::None
-#undef None
-
-#include "mozilla/dom/HeadersBinding.h"
-#include "mozilla/dom/RequestBinding.h"
-#include "mozilla/dom/ResponseBinding.h"
 #include "mozilla/dom/cache/Types.h"
 
 namespace IPC {
   template<>
-  struct ParamTraits<mozilla::dom::HeadersGuardEnum> :
-    public ContiguousEnumSerializer<mozilla::dom::HeadersGuardEnum,
-                                    mozilla::dom::HeadersGuardEnum::None,
-                                    mozilla::dom::HeadersGuardEnum::EndGuard_> {};
-  template<>
-  struct ParamTraits<mozilla::dom::RequestMode> :
-    public ContiguousEnumSerializer<mozilla::dom::RequestMode,
-                                    mozilla::dom::RequestMode::Same_origin,
-                                    mozilla::dom::RequestMode::EndGuard_> {};
-  template<>
-  struct ParamTraits<mozilla::dom::RequestCredentials> :
-    public ContiguousEnumSerializer<mozilla::dom::RequestCredentials,
-                                    mozilla::dom::RequestCredentials::Omit,
-                                    mozilla::dom::RequestCredentials::EndGuard_> {};
-  template<>
-  struct ParamTraits<mozilla::dom::RequestCache> :
-    public ContiguousEnumSerializer<mozilla::dom::RequestCache,
-                                    mozilla::dom::RequestCache::Default,
-                                    mozilla::dom::RequestCache::EndGuard_> {};
-  template<>
-  struct ParamTraits<mozilla::dom::RequestContext> :
-    public ContiguousEnumSerializer<mozilla::dom::RequestContext,
-                                    mozilla::dom::RequestContext::Audio,
-                                    mozilla::dom::RequestContext::EndGuard_> {};
-  template<>
-  struct ParamTraits<mozilla::dom::ResponseType> :
-    public ContiguousEnumSerializer<mozilla::dom::ResponseType,
-                                    mozilla::dom::ResponseType::Basic,
-                                    mozilla::dom::ResponseType::EndGuard_> {};
-  template<>
   struct ParamTraits<mozilla::dom::cache::Namespace> :
     public ContiguousEnumSerializer<mozilla::dom::cache::Namespace,
                                     mozilla::dom::cache::DEFAULT_NAMESPACE,
                                     mozilla::dom::cache::NUMBER_OF_NAMESPACES>
   {};
 }
 
 #endif // mozilla_dom_cache_IPCUtils_h
--- a/dom/cache/Manager.cpp
+++ b/dom/cache/Manager.cpp
@@ -11,17 +11,17 @@
 #include "mozilla/StaticMutex.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/unused.h"
 #include "mozilla/dom/cache/Context.h"
 #include "mozilla/dom/cache/DBAction.h"
 #include "mozilla/dom/cache/DBSchema.h"
 #include "mozilla/dom/cache/FileUtils.h"
 #include "mozilla/dom/cache/ManagerId.h"
-#include "mozilla/dom/cache/CacheTypes.h"
+#include "mozilla/dom/cache/PCacheTypes.h"
 #include "mozilla/dom/cache/SavedTypes.h"
 #include "mozilla/dom/cache/StreamList.h"
 #include "mozilla/dom/cache/Types.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozStorageHelper.h"
 #include "nsAutoPtr.h"
 #include "nsIInputStream.h"
 #include "nsID.h"
@@ -404,20 +404,21 @@ StaticRefPtr<nsIThread> Manager::Factory
 // ----------------------------------------------------------------------------
 
 // Abstract class to help implement the various Actions.  The vast majority
 // of Actions are synchronous and need to report back to a Listener on the
 // Manager.
 class Manager::BaseAction : public SyncDBAction
 {
 protected:
-  BaseAction(Manager* aManager, ListenerId aListenerId)
+  BaseAction(Manager* aManager, ListenerId aListenerId, RequestId aRequestId)
     : SyncDBAction(DBAction::Existing)
     , mManager(aManager)
     , mListenerId(aListenerId)
+    , mRequestId (aRequestId)
   {
   }
 
   virtual void
   Complete(Listener* aListener, nsresult aRv) = 0;
 
   virtual void
   CompleteOnInitiatingThread(nsresult aRv) override
@@ -429,16 +430,17 @@ protected:
     }
 
     // ensure we release the manager on the initiating thread
     mManager = nullptr;
   }
 
   nsRefPtr<Manager> mManager;
   const ListenerId mListenerId;
+  const RequestId mRequestId;
 };
 
 // ----------------------------------------------------------------------------
 
 // Action that is executed when we determine that content has stopped using
 // a Cache object that has been orphaned.
 class Manager::DeleteOrphanedCacheAction final : public SyncDBAction
 {
@@ -481,32 +483,34 @@ private:
 };
 
 // ----------------------------------------------------------------------------
 
 class Manager::CacheMatchAction final : public Manager::BaseAction
 {
 public:
   CacheMatchAction(Manager* aManager, ListenerId aListenerId,
-                   CacheId aCacheId, const CacheMatchArgs& aArgs,
+                   RequestId aRequestId, CacheId aCacheId,
+                   const PCacheRequest& aRequest,
+                   const PCacheQueryParams& aParams,
                    StreamList* aStreamList)
-    : BaseAction(aManager, aListenerId)
+    : BaseAction(aManager, aListenerId, aRequestId)
     , mCacheId(aCacheId)
-    , mArgs(aArgs)
+    , mRequest(aRequest)
+    , mParams(aParams)
     , mStreamList(aStreamList)
     , mFoundResponse(false)
   { }
 
   virtual nsresult
   RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
                         mozIStorageConnection* aConn) override
   {
-    nsresult rv = DBSchema::CacheMatch(aConn, mCacheId, mArgs.request(),
-                                       mArgs.params(), &mFoundResponse,
-                                       &mResponse);
+    nsresult rv = DBSchema::CacheMatch(aConn, mCacheId, mRequest, mParams,
+                                       &mFoundResponse, &mResponse);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     if (!mFoundResponse || !mResponse.mHasBodyId) {
       return rv;
     }
 
     nsCOMPtr<nsIInputStream> stream;
     rv = FileUtils::BodyOpen(aQuotaInfo, aDBDir, mResponse.mBodyId,
@@ -518,58 +522,61 @@ public:
 
     return rv;
   }
 
   virtual void
   Complete(Listener* aListener, nsresult aRv) override
   {
     if (!mFoundResponse) {
-      aListener->OnOpComplete(aRv, CacheMatchResult(void_t()));
+      aListener->OnCacheMatch(mRequestId, aRv, nullptr, nullptr);
     } else {
       mStreamList->Activate(mCacheId);
-      aListener->OnOpComplete(aRv, CacheMatchResult(void_t()), mResponse,
-                              mStreamList);
+      aListener->OnCacheMatch(mRequestId, aRv, &mResponse, mStreamList);
     }
     mStreamList = nullptr;
   }
 
   virtual bool MatchesCacheId(CacheId aCacheId) const override
   {
     return aCacheId == mCacheId;
   }
 
 private:
   const CacheId mCacheId;
-  const CacheMatchArgs mArgs;
+  const PCacheRequest mRequest;
+  const PCacheQueryParams mParams;
   nsRefPtr<StreamList> mStreamList;
   bool mFoundResponse;
   SavedResponse mResponse;
 };
 
 // ----------------------------------------------------------------------------
 
 class Manager::CacheMatchAllAction final : public Manager::BaseAction
 {
 public:
   CacheMatchAllAction(Manager* aManager, ListenerId aListenerId,
-                      CacheId aCacheId, const CacheMatchAllArgs& aArgs,
+                      RequestId aRequestId, CacheId aCacheId,
+                      const PCacheRequestOrVoid& aRequestOrVoid,
+                      const PCacheQueryParams& aParams,
                       StreamList* aStreamList)
-    : BaseAction(aManager, aListenerId)
+    : BaseAction(aManager, aListenerId, aRequestId)
     , mCacheId(aCacheId)
-    , mArgs(aArgs)
+    , mRequestOrVoid(aRequestOrVoid)
+    , mParams(aParams)
     , mStreamList(aStreamList)
   { }
 
   virtual nsresult
   RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
                         mozIStorageConnection* aConn) override
   {
-    nsresult rv = DBSchema::CacheMatchAll(aConn, mCacheId, mArgs.requestOrVoid(),
-                                          mArgs.params(), mSavedResponses);
+    nsresult rv = DBSchema::CacheMatchAll(aConn, mCacheId, mRequestOrVoid,
+                                          mParams, mSavedResponses);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     for (uint32_t i = 0; i < mSavedResponses.Length(); ++i) {
       if (!mSavedResponses[i].mHasBodyId) {
         continue;
       }
 
       nsCOMPtr<nsIInputStream> stream;
@@ -584,49 +591,50 @@ public:
 
     return rv;
   }
 
   virtual void
   Complete(Listener* aListener, nsresult aRv) override
   {
     mStreamList->Activate(mCacheId);
-    aListener->OnOpComplete(aRv, CacheMatchAllResult(), mSavedResponses,
-                            mStreamList);
+    aListener->OnCacheMatchAll(mRequestId, aRv, mSavedResponses, mStreamList);
     mStreamList = nullptr;
   }
 
   virtual bool MatchesCacheId(CacheId aCacheId) const override
   {
     return aCacheId == mCacheId;
   }
 
 private:
   const CacheId mCacheId;
-  const CacheMatchAllArgs mArgs;
+  const PCacheRequestOrVoid mRequestOrVoid;
+  const PCacheQueryParams mParams;
   nsRefPtr<StreamList> mStreamList;
   nsTArray<SavedResponse> mSavedResponses;
 };
 
 // ----------------------------------------------------------------------------
 
 // This is the most complex Action.  It puts a request/response pair into the
 // Cache.  It does not complete until all of the body data has been saved to
 // disk.  This means its an asynchronous Action.
 class Manager::CachePutAllAction final : public DBAction
 {
 public:
   CachePutAllAction(Manager* aManager, ListenerId aListenerId,
-                    CacheId aCacheId,
+                    RequestId aRequestId, CacheId aCacheId,
                     const nsTArray<CacheRequestResponse>& aPutList,
                     const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreamList,
                     const nsTArray<nsCOMPtr<nsIInputStream>>& aResponseStreamList)
     : DBAction(DBAction::Existing)
     , mManager(aManager)
     , mListenerId(aListenerId)
+    , mRequestId(aRequestId)
     , mCacheId(aCacheId)
     , mList(aPutList.Length())
     , mExpectedAsyncCopyCompletions(1)
     , mAsyncResult(NS_OK)
     , mMutex("cache::Manager::CachePutAllAction")
   {
     MOZ_ASSERT(!aPutList.IsEmpty());
     MOZ_ASSERT(aPutList.Length() == aRequestStreamList.Length());
@@ -801,17 +809,17 @@ private:
       mList[i].mResponseStream = nullptr;
     }
 
     mManager->NoteOrphanedBodyIdList(mDeletedBodyIdList);
 
     Listener* listener = mManager->GetListener(mListenerId);
     mManager = nullptr;
     if (listener) {
-      listener->OnOpComplete(aRv, CachePutAllResult());
+      listener->OnCachePutAll(mRequestId, aRv);
     }
   }
 
   virtual void
   CancelOnInitiatingThread() override
   {
     NS_ASSERT_OWNINGTHREAD(Action);
     Action::CancelOnInitiatingThread();
@@ -821,22 +829,22 @@ private:
   virtual bool MatchesCacheId(CacheId aCacheId) const override
   {
     NS_ASSERT_OWNINGTHREAD(Action);
     return aCacheId == mCacheId;
   }
 
   struct Entry
   {
-    CacheRequest mRequest;
+    PCacheRequest mRequest;
     nsCOMPtr<nsIInputStream> mRequestStream;
     nsID mRequestBodyId;
     nsCOMPtr<nsISupports> mRequestCopyContext;
 
-    CacheResponse mResponse;
+    PCacheResponse mResponse;
     nsCOMPtr<nsIInputStream> mResponseStream;
     nsID mResponseBodyId;
     nsCOMPtr<nsISupports> mResponseCopyContext;
   };
 
   enum StreamId
   {
     RequestStream,
@@ -954,16 +962,17 @@ private:
     nsRefPtr<Action::Resolver> resolver;
     mResolver.swap(resolver);
     resolver->Resolve(aRv);
   }
 
   // initiating thread only
   nsRefPtr<Manager> mManager;
   const ListenerId mListenerId;
+  const RequestId mRequestId;
 
   // Set on initiating thread, read on target thread.  State machine guarantees
   // these are not modified while being read by the target thread.
   const CacheId mCacheId;
   nsTArray<Entry> mList;
   uint32_t mExpectedAsyncCopyCompletions;
 
   // target thread only
@@ -984,83 +993,89 @@ private:
 };
 
 // ----------------------------------------------------------------------------
 
 class Manager::CacheDeleteAction final : public Manager::BaseAction
 {
 public:
   CacheDeleteAction(Manager* aManager, ListenerId aListenerId,
-                    CacheId aCacheId, const CacheDeleteArgs& aArgs)
-    : BaseAction(aManager, aListenerId)
+                    RequestId aRequestId, CacheId aCacheId,
+                    const PCacheRequest& aRequest,
+                    const PCacheQueryParams& aParams)
+    : BaseAction(aManager, aListenerId, aRequestId)
     , mCacheId(aCacheId)
-    , mArgs(aArgs)
+    , mRequest(aRequest)
+    , mParams(aParams)
     , mSuccess(false)
   { }
 
   virtual nsresult
   RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
                         mozIStorageConnection* aConn) override
   {
     mozStorageTransaction trans(aConn, false,
                                 mozIStorageConnection::TRANSACTION_IMMEDIATE);
 
-    nsresult rv = DBSchema::CacheDelete(aConn, mCacheId, mArgs.request(),
-                                        mArgs.params(), mDeletedBodyIdList,
-                                        &mSuccess);
+    nsresult rv = DBSchema::CacheDelete(aConn, mCacheId, mRequest, mParams,
+                                        mDeletedBodyIdList, &mSuccess);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     rv = trans.Commit();
     if (NS_WARN_IF(NS_FAILED(rv))) {
       mSuccess = false;
       return rv;
     }
 
     return rv;
   }
 
   virtual void
   Complete(Listener* aListener, nsresult aRv) override
   {
     mManager->NoteOrphanedBodyIdList(mDeletedBodyIdList);
-    aListener->OnOpComplete(aRv, CacheDeleteResult(mSuccess));
+    aListener->OnCacheDelete(mRequestId, aRv, mSuccess);
   }
 
   virtual bool MatchesCacheId(CacheId aCacheId) const override
   {
     return aCacheId == mCacheId;
   }
 
 private:
   const CacheId mCacheId;
-  const CacheDeleteArgs mArgs;
+  const PCacheRequest mRequest;
+  const PCacheQueryParams mParams;
   bool mSuccess;
   nsTArray<nsID> mDeletedBodyIdList;
 };
 
 // ----------------------------------------------------------------------------
 
 class Manager::CacheKeysAction final : public Manager::BaseAction
 {
 public:
   CacheKeysAction(Manager* aManager, ListenerId aListenerId,
-                  CacheId aCacheId, const CacheKeysArgs& aArgs,
+                  RequestId aRequestId, CacheId aCacheId,
+                  const PCacheRequestOrVoid& aRequestOrVoid,
+                  const PCacheQueryParams& aParams,
                   StreamList* aStreamList)
-    : BaseAction(aManager, aListenerId)
+    : BaseAction(aManager, aListenerId, aRequestId)
     , mCacheId(aCacheId)
-    , mArgs(aArgs)
+    , mRequestOrVoid(aRequestOrVoid)
+    , mParams(aParams)
     , mStreamList(aStreamList)
   { }
 
   virtual nsresult
   RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
                         mozIStorageConnection* aConn) override
   {
-    nsresult rv = DBSchema::CacheKeys(aConn, mCacheId, mArgs.requestOrVoid(),
-                                      mArgs.params(), mSavedRequests);
+    nsresult rv = DBSchema::CacheKeys(aConn, mCacheId, mRequestOrVoid, mParams,
+                                      mSavedRequests);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     for (uint32_t i = 0; i < mSavedRequests.Length(); ++i) {
       if (!mSavedRequests[i].mHasBodyId) {
         continue;
       }
 
       nsCOMPtr<nsIInputStream> stream;
@@ -1075,56 +1090,57 @@ public:
 
     return rv;
   }
 
   virtual void
   Complete(Listener* aListener, nsresult aRv) override
   {
     mStreamList->Activate(mCacheId);
-    aListener->OnOpComplete(aRv, CacheKeysResult(), mSavedRequests,
-                            mStreamList);
+    aListener->OnCacheKeys(mRequestId, aRv, mSavedRequests, mStreamList);
     mStreamList = nullptr;
   }
 
   virtual bool MatchesCacheId(CacheId aCacheId) const override
   {
     return aCacheId == mCacheId;
   }
 
 private:
   const CacheId mCacheId;
-  const CacheKeysArgs mArgs;
+  const PCacheRequestOrVoid mRequestOrVoid;
+  const PCacheQueryParams mParams;
   nsRefPtr<StreamList> mStreamList;
   nsTArray<SavedRequest> mSavedRequests;
 };
 
 // ----------------------------------------------------------------------------
 
 class Manager::StorageMatchAction final : public Manager::BaseAction
 {
 public:
   StorageMatchAction(Manager* aManager, ListenerId aListenerId,
-                     Namespace aNamespace,
-                     const StorageMatchArgs& aArgs,
+                     RequestId aRequestId, Namespace aNamespace,
+                     const PCacheRequest& aRequest,
+                     const PCacheQueryParams& aParams,
                      StreamList* aStreamList)
-    : BaseAction(aManager, aListenerId)
+    : BaseAction(aManager, aListenerId, aRequestId)
     , mNamespace(aNamespace)
-    , mArgs(aArgs)
+    , mRequest(aRequest)
+    , mParams(aParams)
     , mStreamList(aStreamList)
     , mFoundResponse(false)
   { }
 
   virtual nsresult
   RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
                         mozIStorageConnection* aConn) override
   {
-    nsresult rv = DBSchema::StorageMatch(aConn, mNamespace, mArgs.request(),
-                                         mArgs.params(), &mFoundResponse,
-                                         &mSavedResponse);
+    nsresult rv = DBSchema::StorageMatch(aConn, mNamespace, mRequest, mParams,
+                                         &mFoundResponse, &mSavedResponse);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     if (!mFoundResponse || !mSavedResponse.mHasBodyId) {
       return rv;
     }
 
     nsCOMPtr<nsIInputStream> stream;
     rv = FileUtils::BodyOpen(aQuotaInfo, aDBDir, mSavedResponse.mBodyId,
@@ -1136,153 +1152,156 @@ public:
 
     return rv;
   }
 
   virtual void
   Complete(Listener* aListener, nsresult aRv) override
   {
     if (!mFoundResponse) {
-      aListener->OnOpComplete(aRv, StorageMatchResult(void_t()));
+      aListener->OnStorageMatch(mRequestId, aRv, nullptr, nullptr);
     } else {
       mStreamList->Activate(mSavedResponse.mCacheId);
-      aListener->OnOpComplete(aRv, StorageMatchResult(void_t()), mSavedResponse,
-                              mStreamList);
+      aListener->OnStorageMatch(mRequestId, aRv, &mSavedResponse, mStreamList);
     }
     mStreamList = nullptr;
   }
 
 private:
   const Namespace mNamespace;
-  const StorageMatchArgs mArgs;
+  const PCacheRequest mRequest;
+  const PCacheQueryParams mParams;
   nsRefPtr<StreamList> mStreamList;
   bool mFoundResponse;
   SavedResponse mSavedResponse;
 };
 
 // ----------------------------------------------------------------------------
 
 class Manager::StorageHasAction final : public Manager::BaseAction
 {
 public:
   StorageHasAction(Manager* aManager, ListenerId aListenerId,
-                   Namespace aNamespace, const StorageHasArgs& aArgs)
-    : BaseAction(aManager, aListenerId)
+                   RequestId aRequestId, Namespace aNamespace,
+                   const nsAString& aKey)
+    : BaseAction(aManager, aListenerId, aRequestId)
     , mNamespace(aNamespace)
-    , mArgs(aArgs)
+    , mKey(aKey)
     , mCacheFound(false)
   { }
 
   virtual nsresult
   RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
                         mozIStorageConnection* aConn) override
   {
     CacheId cacheId;
-    return DBSchema::StorageGetCacheId(aConn, mNamespace, mArgs.key(),
+    return DBSchema::StorageGetCacheId(aConn, mNamespace, mKey,
                                        &mCacheFound, &cacheId);
   }
 
   virtual void
   Complete(Listener* aListener, nsresult aRv) override
   {
-    aListener->OnOpComplete(aRv, StorageHasResult(mCacheFound));
+    aListener->OnStorageHas(mRequestId, aRv, mCacheFound);
   }
 
 private:
   const Namespace mNamespace;
-  const StorageHasArgs mArgs;
+  const nsString mKey;
   bool mCacheFound;
 };
 
 // ----------------------------------------------------------------------------
 
 class Manager::StorageOpenAction final : public Manager::BaseAction
 {
 public:
   StorageOpenAction(Manager* aManager, ListenerId aListenerId,
-                    Namespace aNamespace, const StorageOpenArgs& aArgs)
-    : BaseAction(aManager, aListenerId)
+                    RequestId aRequestId, Namespace aNamespace,
+                    const nsAString& aKey)
+    : BaseAction(aManager, aListenerId, aRequestId)
     , mNamespace(aNamespace)
-    , mArgs(aArgs)
+    , mKey(aKey)
     , mCacheId(INVALID_CACHE_ID)
   { }
 
   virtual nsresult
   RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
                         mozIStorageConnection* aConn) override
   {
     // Cache does not exist, create it instead
     mozStorageTransaction trans(aConn, false,
                                 mozIStorageConnection::TRANSACTION_IMMEDIATE);
 
     // Look for existing cache
     bool cacheFound;
-    nsresult rv = DBSchema::StorageGetCacheId(aConn, mNamespace, mArgs.key(),
+    nsresult rv = DBSchema::StorageGetCacheId(aConn, mNamespace, mKey,
                                               &cacheFound, &mCacheId);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
     if (cacheFound) {
       return rv;
     }
 
     rv = DBSchema::CreateCache(aConn, &mCacheId);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
-    rv = DBSchema::StoragePutCache(aConn, mNamespace, mArgs.key(), mCacheId);
+    rv = DBSchema::StoragePutCache(aConn, mNamespace, mKey, mCacheId);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     rv = trans.Commit();
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     return rv;
   }
 
   virtual void
   Complete(Listener* aListener, nsresult aRv) override
   {
-    aListener->OnOpComplete(aRv, StorageOpenResult(), mCacheId);
+    aListener->OnStorageOpen(mRequestId, aRv, mCacheId);
   }
 
 private:
   const Namespace mNamespace;
-  const StorageOpenArgs mArgs;
+  const nsString mKey;
   CacheId mCacheId;
 };
 
 // ----------------------------------------------------------------------------
 
 class Manager::StorageDeleteAction final : public Manager::BaseAction
 {
 public:
   StorageDeleteAction(Manager* aManager, ListenerId aListenerId,
-                      Namespace aNamespace, const StorageDeleteArgs& aArgs)
-    : BaseAction(aManager, aListenerId)
+                      RequestId aRequestId, Namespace aNamespace,
+                      const nsAString& aKey)
+    : BaseAction(aManager, aListenerId, aRequestId)
     , mNamespace(aNamespace)
-    , mArgs(aArgs)
+    , mKey(aKey)
     , mCacheDeleted(false)
     , mCacheId(INVALID_CACHE_ID)
   { }
 
   virtual nsresult
   RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
                         mozIStorageConnection* aConn) override
   {
     mozStorageTransaction trans(aConn, false,
                                 mozIStorageConnection::TRANSACTION_IMMEDIATE);
 
     bool exists;
-    nsresult rv = DBSchema::StorageGetCacheId(aConn, mNamespace, mArgs.key(),
-                                              &exists, &mCacheId);
+    nsresult rv = DBSchema::StorageGetCacheId(aConn, mNamespace, mKey, &exists,
+                                              &mCacheId);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     if (!exists) {
       mCacheDeleted = false;
       return NS_OK;
     }
 
-    rv = DBSchema::StorageForgetCache(aConn, mNamespace, mArgs.key());
+    rv = DBSchema::StorageForgetCache(aConn, mNamespace, mKey);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     rv = trans.Commit();
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     mCacheDeleted = true;
     return rv;
   }
@@ -1299,107 +1318,63 @@ public:
         nsRefPtr<Context> context = mManager->CurrentContext();
         context->CancelForCacheId(mCacheId);
         nsRefPtr<Action> action =
           new DeleteOrphanedCacheAction(mManager, mCacheId);
         context->Dispatch(mManager->mIOThread, action);
       }
     }
 
-    aListener->OnOpComplete(aRv, StorageDeleteResult(mCacheDeleted));
+    aListener->OnStorageDelete(mRequestId, aRv, mCacheDeleted);
   }
 
 private:
   const Namespace mNamespace;
-  const StorageDeleteArgs mArgs;
+  const nsString mKey;
   bool mCacheDeleted;
   CacheId mCacheId;
 };
 
 // ----------------------------------------------------------------------------
 
 class Manager::StorageKeysAction final : public Manager::BaseAction
 {
 public:
   StorageKeysAction(Manager* aManager, ListenerId aListenerId,
-                    Namespace aNamespace)
-    : BaseAction(aManager, aListenerId)
+                    RequestId aRequestId, Namespace aNamespace)
+    : BaseAction(aManager, aListenerId, aRequestId)
     , mNamespace(aNamespace)
   { }
 
   virtual nsresult
   RunSyncWithDBOnTarget(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
                         mozIStorageConnection* aConn) override
   {
     return DBSchema::StorageGetKeys(aConn, mNamespace, mKeys);
   }
 
   virtual void
   Complete(Listener* aListener, nsresult aRv) override
   {
     if (NS_FAILED(aRv)) {
       mKeys.Clear();
     }
-    aListener->OnOpComplete(aRv, StorageKeysResult(mKeys));
+    aListener->OnStorageKeys(mRequestId, aRv, mKeys);
   }
 
 private:
   const Namespace mNamespace;
   nsTArray<nsString> mKeys;
 };
 
 // ----------------------------------------------------------------------------
 
 //static
 Manager::ListenerId Manager::sNextListenerId = 0;
 
-void
-Manager::Listener::OnOpComplete(nsresult aRv, const CacheOpResult& aResult)
-{
-  OnOpComplete(aRv, aResult, INVALID_CACHE_ID, nsTArray<SavedResponse>(),
-               nsTArray<SavedRequest>(), nullptr);
-}
-
-void
-Manager::Listener::OnOpComplete(nsresult aRv, const CacheOpResult& aResult,
-                                CacheId aOpenedCacheId)
-{
-  OnOpComplete(aRv, aResult, aOpenedCacheId, nsTArray<SavedResponse>(),
-               nsTArray<SavedRequest>(), nullptr);
-}
-
-void
-Manager::Listener::OnOpComplete(nsresult aRv, const CacheOpResult& aResult,
-                                const SavedResponse& aSavedResponse,
-                                StreamList* aStreamList)
-{
-  nsAutoTArray<SavedResponse, 1> responseList;
-  responseList.AppendElement(aSavedResponse);
-  OnOpComplete(aRv, aResult, INVALID_CACHE_ID, responseList,
-               nsTArray<SavedRequest>(), aStreamList);
-}
-
-void
-Manager::Listener::OnOpComplete(nsresult aRv, const CacheOpResult& aResult,
-                                const nsTArray<SavedResponse>& aSavedResponseList,
-                                StreamList* aStreamList)
-{
-  OnOpComplete(aRv, aResult, INVALID_CACHE_ID, aSavedResponseList,
-               nsTArray<SavedRequest>(), aStreamList);
-}
-
-void
-Manager::Listener::OnOpComplete(nsresult aRv, const CacheOpResult& aResult,
-                                const nsTArray<SavedRequest>& aSavedRequestList,
-                                StreamList* aStreamList)
-{
-  OnOpComplete(aRv, aResult, INVALID_CACHE_ID, nsTArray<SavedResponse>(),
-               aSavedRequestList, aStreamList);
-}
-
 // static
 nsresult
 Manager::GetOrCreate(ManagerId* aManagerId, Manager** aManagerOut)
 {
   mozilla::ipc::AssertIsOnBackgroundThread();
   return Factory::GetOrCreate(aManagerId, aManagerOut);
 }
 
@@ -1580,125 +1555,205 @@ void
 Manager::RemoveStreamList(StreamList* aStreamList)
 {
   NS_ASSERT_OWNINGTHREAD(Manager);
   MOZ_ASSERT(aStreamList);
   mStreamLists.RemoveElement(aStreamList);
 }
 
 void
-Manager::ExecuteCacheOp(Listener* aListener, CacheId aCacheId,
-                        const CacheOpArgs& aOpArgs)
+Manager::CacheMatch(Listener* aListener, RequestId aRequestId, CacheId aCacheId,
+                    const PCacheRequest& aRequest,
+                    const PCacheQueryParams& aParams)
 {
   NS_ASSERT_OWNINGTHREAD(Manager);
   MOZ_ASSERT(aListener);
-  MOZ_ASSERT(aOpArgs.type() != CacheOpArgs::TCacheAddAllArgs);
-  MOZ_ASSERT(aOpArgs.type() != CacheOpArgs::TCachePutAllArgs);
-
   if (mShuttingDown || !mValid) {
-    aListener->OnOpComplete(NS_ERROR_FAILURE, void_t());
+    aListener->OnCacheMatch(aRequestId, NS_ERROR_FAILURE, nullptr, nullptr);
     return;
   }
+  nsRefPtr<Context> context = CurrentContext();
+  nsRefPtr<StreamList> streamList = new StreamList(this, context);
+  ListenerId listenerId = SaveListener(aListener);
+  nsRefPtr<Action> action = new CacheMatchAction(this, listenerId, aRequestId,
+                                                 aCacheId, aRequest, aParams,
+                                                 streamList);
+  context->Dispatch(mIOThread, action);
+}
 
+void
+Manager::CacheMatchAll(Listener* aListener, RequestId aRequestId,
+                       CacheId aCacheId, const PCacheRequestOrVoid& aRequest,
+                       const PCacheQueryParams& aParams)
+{
+  NS_ASSERT_OWNINGTHREAD(Manager);
+  MOZ_ASSERT(aListener);
+  if (mShuttingDown || !mValid) {
+    aListener->OnCacheMatchAll(aRequestId, NS_ERROR_FAILURE,
+                               nsTArray<SavedResponse>(), nullptr);
+    return;
+  }
   nsRefPtr<Context> context = CurrentContext();
   nsRefPtr<StreamList> streamList = new StreamList(this, context);
   ListenerId listenerId = SaveListener(aListener);
+  nsRefPtr<Action> action = new CacheMatchAllAction(this, listenerId, aRequestId,
+                                                    aCacheId, aRequest, aParams,
+                                                    streamList);
+  context->Dispatch(mIOThread, action);
+}
 
-  nsRefPtr<Action> action;
-  switch(aOpArgs.type()) {
-    case CacheOpArgs::TCacheMatchArgs:
-      action = new CacheMatchAction(this, listenerId, aCacheId,
-                                    aOpArgs.get_CacheMatchArgs(), streamList);
-      break;
-    case CacheOpArgs::TCacheMatchAllArgs:
-      action = new CacheMatchAllAction(this, listenerId, aCacheId,
-                                       aOpArgs.get_CacheMatchAllArgs(),
-                                       streamList);
-      break;
-    case CacheOpArgs::TCacheDeleteArgs:
-      action = new CacheDeleteAction(this, listenerId, aCacheId,
-                                     aOpArgs.get_CacheDeleteArgs());
-      break;
-    case CacheOpArgs::TCacheKeysArgs:
-      action = new CacheKeysAction(this, listenerId, aCacheId,
-                                   aOpArgs.get_CacheKeysArgs(), streamList);
-      break;
-    default:
-      MOZ_CRASH("Unknown Cache operation!");
+void
+Manager::CachePutAll(Listener* aListener, RequestId aRequestId, CacheId aCacheId,
+                     const nsTArray<CacheRequestResponse>& aPutList,
+                     const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreamList,
+                     const nsTArray<nsCOMPtr<nsIInputStream>>& aResponseStreamList)
+{
+  NS_ASSERT_OWNINGTHREAD(Manager);
+  MOZ_ASSERT(aListener);
+  if (mShuttingDown || !mValid) {
+    aListener->OnCachePutAll(aRequestId, NS_ERROR_FAILURE);
+    return;
   }
+  ListenerId listenerId = SaveListener(aListener);
+  nsRefPtr<Action> action = new CachePutAllAction(this, listenerId, aRequestId,
+                                                  aCacheId, aPutList,
+                                                  aRequestStreamList,
+                                                  aResponseStreamList);
+  nsRefPtr<Context> context = CurrentContext();
+  context->Dispatch(mIOThread, action);
+}
 
+void
+Manager::CacheDelete(Listener* aListener, RequestId aRequestId,
+                     CacheId aCacheId, const PCacheRequest& aRequest,
+                     const PCacheQueryParams& aParams)
+{
+  NS_ASSERT_OWNINGTHREAD(Manager);
+  MOZ_ASSERT(aListener);
+  if (mShuttingDown || !mValid) {
+    aListener->OnCacheDelete(aRequestId, NS_ERROR_FAILURE, false);
+    return;
+  }
+  ListenerId listenerId = SaveListener(aListener);
+  nsRefPtr<Action> action = new CacheDeleteAction(this, listenerId, aRequestId,
+                                                  aCacheId, aRequest, aParams);
+  nsRefPtr<Context> context = CurrentContext();
   context->Dispatch(mIOThread, action);
 }
 
 void
-Manager::ExecuteStorageOp(Listener* aListener, Namespace aNamespace,
-                          const CacheOpArgs& aOpArgs)
+Manager::CacheKeys(Listener* aListener, RequestId aRequestId,
+                   CacheId aCacheId, const PCacheRequestOrVoid& aRequestOrVoid,
+                   const PCacheQueryParams& aParams)
 {
   NS_ASSERT_OWNINGTHREAD(Manager);
   MOZ_ASSERT(aListener);
-
   if (mShuttingDown || !mValid) {
-    aListener->OnOpComplete(NS_ERROR_FAILURE, void_t());
+    aListener->OnCacheKeys(aRequestId, NS_ERROR_FAILURE,
+                           nsTArray<SavedRequest>(), nullptr);
     return;
   }
-
   nsRefPtr<Context> context = CurrentContext();
   nsRefPtr<StreamList> streamList = new StreamList(this, context);
   ListenerId listenerId = SaveListener(aListener);
+  nsRefPtr<Action> action = new CacheKeysAction(this, listenerId, aRequestId,
+                                                aCacheId, aRequestOrVoid,
+                                                aParams, streamList);
+  context->Dispatch(mIOThread, action);
+}
 
-  nsRefPtr<Action> action;
-  switch(aOpArgs.type()) {
-    case CacheOpArgs::TStorageMatchArgs:
-      action = new StorageMatchAction(this, listenerId, aNamespace,
-                                      aOpArgs.get_StorageMatchArgs(),
-                                      streamList);
-      break;
-    case CacheOpArgs::TStorageHasArgs:
-      action = new StorageHasAction(this, listenerId, aNamespace,
-                                    aOpArgs.get_StorageHasArgs());
-      break;
-    case CacheOpArgs::TStorageOpenArgs:
-      action = new StorageOpenAction(this, listenerId, aNamespace,
-                                     aOpArgs.get_StorageOpenArgs());
-      break;
-    case CacheOpArgs::TStorageDeleteArgs:
-      action = new StorageDeleteAction(this, listenerId, aNamespace,
-                                       aOpArgs.get_StorageDeleteArgs());
-      break;
-    case CacheOpArgs::TStorageKeysArgs:
-      action = new StorageKeysAction(this, listenerId, aNamespace);
-      break;
-    default:
-      MOZ_CRASH("Unknown CacheStorage operation!");
+void
+Manager::StorageMatch(Listener* aListener, RequestId aRequestId,
+                      Namespace aNamespace, const PCacheRequest& aRequest,
+                      const PCacheQueryParams& aParams)
+{
+  NS_ASSERT_OWNINGTHREAD(Manager);
+  MOZ_ASSERT(aListener);
+  if (mShuttingDown || !mValid) {
+    aListener->OnStorageMatch(aRequestId, NS_ERROR_FAILURE,
+                              nullptr, nullptr);
+    return;
   }
-
+  nsRefPtr<Context> context = CurrentContext();
+  nsRefPtr<StreamList> streamList = new StreamList(this, context);
+  ListenerId listenerId = SaveListener(aListener);
+  nsRefPtr<Action> action = new StorageMatchAction(this, listenerId, aRequestId,
+                                                   aNamespace, aRequest,
+                                                   aParams, streamList);
   context->Dispatch(mIOThread, action);
 }
 
 void
-Manager::ExecutePutAll(Listener* aListener, CacheId aCacheId,
-                       const nsTArray<CacheRequestResponse>& aPutList,
-                       const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreamList,
-                       const nsTArray<nsCOMPtr<nsIInputStream>>& aResponseStreamList)
+Manager::StorageHas(Listener* aListener, RequestId aRequestId,
+                    Namespace aNamespace, const nsAString& aKey)
+{
+  NS_ASSERT_OWNINGTHREAD(Manager);
+  MOZ_ASSERT(aListener);
+  if (mShuttingDown || !mValid) {
+    aListener->OnStorageHas(aRequestId, NS_ERROR_FAILURE,
+                            false);
+    return;
+  }
+  ListenerId listenerId = SaveListener(aListener);
+  nsRefPtr<Action> action = new StorageHasAction(this, listenerId, aRequestId,
+                                                 aNamespace, aKey);
+  nsRefPtr<Context> context = CurrentContext();
+  context->Dispatch(mIOThread, action);
+}
+
+void
+Manager::StorageOpen(Listener* aListener, RequestId aRequestId,
+                     Namespace aNamespace, const nsAString& aKey)
 {
   NS_ASSERT_OWNINGTHREAD(Manager);
   MOZ_ASSERT(aListener);
-
   if (mShuttingDown || !mValid) {
-    aListener->OnOpComplete(NS_ERROR_FAILURE, CachePutAllResult());
+    aListener->OnStorageOpen(aRequestId, NS_ERROR_FAILURE, 0);
+    return;
+  }
+  ListenerId listenerId = SaveListener(aListener);
+  nsRefPtr<Action> action = new StorageOpenAction(this, listenerId, aRequestId,
+                                                  aNamespace, aKey);
+  nsRefPtr<Context> context = CurrentContext();
+  context->Dispatch(mIOThread, action);
+}
+
+void
+Manager::StorageDelete(Listener* aListener, RequestId aRequestId,
+                       Namespace aNamespace, const nsAString& aKey)
+{
+  NS_ASSERT_OWNINGTHREAD(Manager);
+  MOZ_ASSERT(aListener);
+  if (mShuttingDown || !mValid) {
+    aListener->OnStorageDelete(aRequestId, NS_ERROR_FAILURE,
+                               false);
     return;
   }
-
+  ListenerId listenerId = SaveListener(aListener);
+  nsRefPtr<Action> action = new StorageDeleteAction(this, listenerId, aRequestId,
+                                                    aNamespace, aKey);
   nsRefPtr<Context> context = CurrentContext();
-  ListenerId listenerId = SaveListener(aListener);
+  context->Dispatch(mIOThread, action);
+}
 
-  nsRefPtr<Action> action = new CachePutAllAction(this, listenerId, aCacheId,
-                                                  aPutList, aRequestStreamList,
-                                                  aResponseStreamList);
-
+void
+Manager::StorageKeys(Listener* aListener, RequestId aRequestId,
+                     Namespace aNamespace)
+{
+  NS_ASSERT_OWNINGTHREAD(Manager);
+  MOZ_ASSERT(aListener);
+  if (mShuttingDown || !mValid) {
+    aListener->OnStorageKeys(aRequestId, NS_ERROR_FAILURE,
+                             nsTArray<nsString>());
+    return;
+  }
+  ListenerId listenerId = SaveListener(aListener);
+  nsRefPtr<Action> action = new StorageKeysAction(this, listenerId, aRequestId,
+                                                  aNamespace);
+  nsRefPtr<Context> context = CurrentContext();
   context->Dispatch(mIOThread, action);
 }
 
 Manager::Manager(ManagerId* aManagerId, nsIThread* aIOThread)
   : mManagerId(aManagerId)
   , mIOThread(aIOThread)
   , mContext(nullptr)
   , mShuttingDown(false)
--- a/dom/cache/Manager.h
+++ b/dom/cache/Manager.h
@@ -2,35 +2,37 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 mozilla_dom_cache_Manager_h
 #define mozilla_dom_cache_Manager_h
 
+#include "mozilla/dom/cache/CacheInitData.h"
+#include "mozilla/dom/cache/PCacheStreamControlParent.h"
 #include "mozilla/dom/cache/Types.h"
 #include "nsCOMPtr.h"
 #include "nsISupportsImpl.h"
-#include "nsRefPtr.h"
 #include "nsString.h"
 #include "nsTArray.h"
 
 class nsIInputStream;
 class nsIThread;
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
-class CacheOpArgs;
-class CacheOpResult;
 class CacheRequestResponse;
 class Context;
 class ManagerId;
+class PCacheQueryParams;
+class PCacheRequest;
+class PCacheRequestOrVoid;
 struct SavedRequest;
 struct SavedResponse;
 class StreamList;
 
 // The Manager is class is responsible for performing all of the underlying
 // work for a Cache or CacheStorage operation.  The DOM objects and IPC actors
 // are basically just plumbing to get the request to the right Manager object
 // running in the parent process.
@@ -79,46 +81,40 @@ public:
   // Listeners must call Manager::RemoveListener() before they are destroyed
   // to clear these weak references.
   //
   // All public methods should be invoked on the same thread used to create
   // the Manager.
   class Listener
   {
   public:
-    // convenience routines
-    void
-    OnOpComplete(nsresult aRv, const CacheOpResult& aResult);
-
-    void
-    OnOpComplete(nsresult aRv, const CacheOpResult& aResult,
-                 CacheId aOpenedCacheId);
-
-    void
-    OnOpComplete(nsresult aRv, const CacheOpResult& aResult,
-                 const SavedResponse& aSavedResponse,
-                 StreamList* aStreamList);
+    virtual void OnCacheMatch(RequestId aRequestId, nsresult aRv,
+                              const SavedResponse* aResponse,
+                              StreamList* aStreamList) { }
+    virtual void OnCacheMatchAll(RequestId aRequestId, nsresult aRv,
+                                 const nsTArray<SavedResponse>& aSavedResponses,
+                                 StreamList* aStreamList) { }
+    virtual void OnCachePutAll(RequestId aRequestId, nsresult aRv) { }
+    virtual void OnCacheDelete(RequestId aRequestId, nsresult aRv,
+                               bool aSuccess) { }
+    virtual void OnCacheKeys(RequestId aRequestId, nsresult aRv,
+                             const nsTArray<SavedRequest>& aSavedRequests,
+                             StreamList* aStreamList) { }
 
-    void
-    OnOpComplete(nsresult aRv, const CacheOpResult& aResult,
-                 const nsTArray<SavedResponse>& aSavedResponseList,
-                 StreamList* aStreamList);
-
-    void
-    OnOpComplete(nsresult aRv, const CacheOpResult& aResult,
-                 const nsTArray<SavedRequest>& aSavedRequestList,
-                 StreamList* aStreamList);
-
-    // interface to be implemented
-    virtual void
-    OnOpComplete(nsresult aRv, const CacheOpResult& aResult,
-                 CacheId aOpenedCacheId,
-                 const nsTArray<SavedResponse>& aSavedResponseList,
-                 const nsTArray<SavedRequest>& aSavedRequestList,
-                 StreamList* aStreamList) { }
+    virtual void OnStorageMatch(RequestId aRequestId, nsresult aRv,
+                                const SavedResponse* aResponse,
+                                StreamList* aStreamList) { }
+    virtual void OnStorageHas(RequestId aRequestId, nsresult aRv,
+                              bool aCacheFound) { }
+    virtual void OnStorageOpen(RequestId aRequestId, nsresult aRv,
+                               CacheId aCacheId) { }
+    virtual void OnStorageDelete(RequestId aRequestId, nsresult aRv,
+                                 bool aCacheDeleted) { }
+    virtual void OnStorageKeys(RequestId aRequestId, nsresult aRv,
+                               const nsTArray<nsString>& aKeys) { }
 
   protected:
     ~Listener() { }
   };
 
   static nsresult GetOrCreate(ManagerId* aManagerId, Manager** aManagerOut);
   static already_AddRefed<Manager> Get(ManagerId* aManagerId);
 
@@ -149,25 +145,45 @@ public:
 
   already_AddRefed<ManagerId> GetManagerId() const;
 
   // Methods to allow a StreamList to register themselves with the Manager.
   // StreamList objects must call RemoveStreamList() before they are destroyed.
   void AddStreamList(StreamList* aStreamList);
   void RemoveStreamList(StreamList* aStreamList);
 
-  void ExecuteCacheOp(Listener* aListener, CacheId aCacheId,
-                      const CacheOpArgs& aOpArgs);
-  void ExecutePutAll(Listener* aListener, CacheId aCacheId,
-                     const nsTArray<CacheRequestResponse>& aPutList,
-                     const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreamList,
-                     const nsTArray<nsCOMPtr<nsIInputStream>>& aResponseStreamList);
+  // TODO: consider moving CacheId up in the argument lists below (bug 1110485)
+  void CacheMatch(Listener* aListener, RequestId aRequestId, CacheId aCacheId,
+                  const PCacheRequest& aRequest,
+                  const PCacheQueryParams& aParams);
+  void CacheMatchAll(Listener* aListener, RequestId aRequestId,
+                     CacheId aCacheId, const PCacheRequestOrVoid& aRequestOrVoid,
+                     const PCacheQueryParams& aParams);
+  void CachePutAll(Listener* aListener, RequestId aRequestId, CacheId aCacheId,
+                   const nsTArray<CacheRequestResponse>& aPutList,
+                   const nsTArray<nsCOMPtr<nsIInputStream>>& aRequestStreamList,
+                   const nsTArray<nsCOMPtr<nsIInputStream>>& aResponseStreamList);
+  void CacheDelete(Listener* aListener, RequestId aRequestId,
+                   CacheId aCacheId, const PCacheRequest& aRequest,
+                   const PCacheQueryParams& aParams);
+  void CacheKeys(Listener* aListener, RequestId aRequestId,
+                 CacheId aCacheId, const PCacheRequestOrVoid& aRequestOrVoid,
+                 const PCacheQueryParams& aParams);
 
-  void ExecuteStorageOp(Listener* aListener, Namespace aNamespace,
-                        const CacheOpArgs& aOpArgs);
+  void StorageMatch(Listener* aListener, RequestId aRequestId,
+                    Namespace aNamespace, const PCacheRequest& aRequest,
+                    const PCacheQueryParams& aParams);
+  void StorageHas(Listener* aListener, RequestId aRequestId,
+                  Namespace aNamespace, const nsAString& aKey);
+  void StorageOpen(Listener* aListener, RequestId aRequestId,
+                   Namespace aNamespace, const nsAString& aKey);
+  void StorageDelete(Listener* aListener, RequestId aRequestId,
+                     Namespace aNamespace, const nsAString& aKey);
+  void StorageKeys(Listener* aListener, RequestId aRequestId,
+                   Namespace aNamespace);
 
 private:
   class Factory;
   class BaseAction;
   class DeleteOrphanedCacheAction;
 
   class CacheMatchAction;
   class CacheMatchAllAction;
--- a/dom/cache/PCache.ipdl
+++ b/dom/cache/PCache.ipdl
@@ -1,35 +1,49 @@
 /* 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 protocol PBackground;
-include protocol PBlob; // FIXME: bug 792908
-include protocol PCacheOp;
 include protocol PCachePushStream;
-include protocol PCacheStreamControl;
+include PCacheTypes;
 include protocol PFileDescriptorSet;
 
-include CacheTypes;
+include protocol PBlob; // FIXME: bug 792908
+include protocol PCacheStreamControl;
+
+using mozilla::dom::cache::RequestId from "mozilla/dom/cache/Types.h";
+include "mozilla/dom/cache/IPCUtils.h";
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 protocol PCache
 {
   manager PBackground;
-  manages PCacheOp;
   manages PCachePushStream;
 
 parent:
-  PCacheOp(CacheOpArgs aOpArgs);
   PCachePushStream();
   Teardown();
+  Match(RequestId requestId, PCacheRequest request, PCacheQueryParams params);
+  MatchAll(RequestId requestId, PCacheRequestOrVoid request, PCacheQueryParams params);
+  AddAll(RequestId requestId, PCacheRequest[] requests);
+  Put(RequestId requestId, CacheRequestResponse aPut);
+  Delete(RequestId requestId, PCacheRequest request, PCacheQueryParams params);
+  Keys(RequestId requestId, PCacheRequestOrVoid request, PCacheQueryParams params);
 
 child:
+  MatchResponse(RequestId requestId, nsresult aRv, PCacheResponseOrVoid aResponse);
+  MatchAllResponse(RequestId requestId, nsresult aRv, PCacheResponse[] responses);
+  AddAllResponse(RequestId requestId, nsresult aRv);
+  PutResponse(RequestId requestId, nsresult aRv);
+  DeleteResponse(RequestId requestId, nsresult aRv, bool success);
+  KeysResponse(RequestId requestId, nsresult aRv, PCacheRequest[] requests);
+
+both:
   __delete__();
 };
 
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
deleted file mode 100644
--- a/dom/cache/PCacheOp.ipdl
+++ /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/. */
-
-include protocol PCache;
-include protocol PCachePushStream;
-include protocol PCacheStorage;
-include protocol PCacheStreamControl;
-include protocol PFileDescriptorSet;
-
-include CacheTypes;
-
-namespace mozilla {
-namespace dom {
-namespace cache {
-
-protocol PCacheOp
-{
-  manager PCache or PCacheStorage;
-
-child:
-  __delete__(nsresult aStatus, CacheOpResult aResult);
-};
-
-} // namespace cache
-} // namespace dom
-} // namespace mozilla
--- a/dom/cache/PCacheStorage.ipdl
+++ b/dom/cache/PCacheStorage.ipdl
@@ -1,33 +1,44 @@
 /* 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 protocol PBackground;
-include protocol PBlob; // FIXME: bug 792908
 include protocol PCache;
-include protocol PCacheOp;
-include protocol PCacheStreamControl;
+include PCacheTypes;
 include protocol PFileDescriptorSet;
 
-include CacheTypes;
+include protocol PBlob; // FIXME: bug 792908
+include protocol PCacheStreamControl;
+
+using mozilla::dom::cache::RequestId from "mozilla/dom/cache/IPCUtils.h";
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 protocol PCacheStorage
 {
   manager PBackground;
-  manages PCacheOp;
 
 parent:
-  PCacheOp(CacheOpArgs aOpArgs);
   Teardown();
+  Match(RequestId aRequestId, PCacheRequest aRequest,
+        PCacheQueryParams aParams);
+  Has(RequestId aRequestId, nsString aKey);
+  Open(RequestId aRequestId, nsString aKey);
+  Delete(RequestId aRequestId, nsString aKey);
+  Keys(RequestId aRequestId);
 
 child:
+  MatchResponse(RequestId aRequestId, nsresult aRv,
+                PCacheResponseOrVoid aResponseOrVoid);
+  HasResponse(RequestId aRequestId, nsresult aRv, bool aSuccess);
+  OpenResponse(RequestId aRequestId, nsresult aRv, nullable PCache aActor);
+  DeleteResponse(RequestId aRequestId, nsresult aRv, bool aSuccess);
+  KeysResponse(RequestId aRequestId, nsresult aRv, nsString[] aKeys);
   __delete__();
 };
 
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
rename from dom/cache/CacheTypes.ipdlh
rename to dom/cache/PCacheTypes.ipdlh
--- a/dom/cache/CacheTypes.ipdlh
+++ b/dom/cache/PCacheTypes.ipdlh
@@ -1,244 +1,95 @@
 /* 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 protocol PCache;
 include protocol PCachePushStream;
 include protocol PCacheStreamControl;
+include PHeaders;
 include InputStreamParams;
 
-using HeadersGuardEnum from "mozilla/dom/cache/IPCUtils.h";
-using RequestCredentials from "mozilla/dom/cache/IPCUtils.h";
-using RequestMode from "mozilla/dom/cache/IPCUtils.h";
-using RequestCache from "mozilla/dom/cache/IPCUtils.h";
-using RequestContext from "mozilla/dom/cache/IPCUtils.h";
-using ResponseType from "mozilla/dom/cache/IPCUtils.h";
+using HeadersGuardEnum from "mozilla/dom/FetchIPCUtils.h";
+using RequestCredentials from "mozilla/dom/FetchIPCUtils.h";
+using RequestMode from "mozilla/dom/FetchIPCUtils.h";
+using RequestCache from "mozilla/dom/FetchIPCUtils.h";
+using RequestContext from "mozilla/dom/FetchIPCUtils.h";
+using mozilla::dom::ResponseType from "mozilla/dom/FetchIPCUtils.h";
 using mozilla::void_t from "ipc/IPCMessageUtils.h";
 using struct nsID from "nsID.h";
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
-struct CacheQueryParams
+struct PCacheQueryParams
 {
   bool ignoreSearch;
   bool ignoreMethod;
   bool ignoreVary;
   bool cacheNameSet;
   nsString cacheName;
 };
 
-struct CacheReadStream
+struct PCacheReadStream
 {
   nsID id;
   OptionalInputStreamParams params;
   OptionalFileDescriptorSet fds;
   nullable PCacheStreamControl control;
   nullable PCachePushStream pushStream;
 };
 
-union CacheReadStreamOrVoid
+union PCacheReadStreamOrVoid
 {
   void_t;
-  CacheReadStream;
+  PCacheReadStream;
 };
 
-struct HeadersEntry
-{
-  nsCString name;
-  nsCString value;
-};
-
-struct CacheRequest
+struct PCacheRequest
 {
   nsCString method;
   nsString url;
   nsString urlWithoutQuery;
-  HeadersEntry[] headers;
+  PHeadersEntry[] headers;
   HeadersGuardEnum headersGuard;
   nsString referrer;
   RequestMode mode;
   RequestCredentials credentials;
-  CacheReadStreamOrVoid body;
+  PCacheReadStreamOrVoid body;
   uint32_t contentPolicyType;
   RequestContext context;
   RequestCache requestCache;
 };
 
-union CacheRequestOrVoid
+union PCacheRequestOrVoid
 {
   void_t;
-  CacheRequest;
+  PCacheRequest;
 };
 
-struct CacheResponse
+struct PCacheResponse
 {
   ResponseType type;
   nsString url;
   uint32_t status;
   nsCString statusText;
-  HeadersEntry[] headers;
+  PHeadersEntry[] headers;
   HeadersGuardEnum headersGuard;
-  CacheReadStreamOrVoid body;
+  PCacheReadStreamOrVoid body;
   nsCString securityInfo;
 };
 
-union CacheResponseOrVoid
+union PCacheResponseOrVoid
 {
   void_t;
-  CacheResponse;
+  PCacheResponse;
 };
 
 struct CacheRequestResponse
 {
-  CacheRequest request;
-  CacheResponse response;
-};
-
-struct CacheMatchArgs
-{
-  CacheRequest request;
-  CacheQueryParams params;
-};
-
-struct CacheMatchAllArgs
-{
-  CacheRequestOrVoid requestOrVoid;
-  CacheQueryParams params;
-};
-
-struct CacheAddAllArgs
-{
-  CacheRequest[] requestList;
-};
-
-struct CachePutAllArgs
-{
-  CacheRequestResponse[] requestResponseList;
-};
-
-struct CacheDeleteArgs
-{
-  CacheRequest request;
-  CacheQueryParams params;
-};
-
-struct CacheKeysArgs
-{
-  CacheRequestOrVoid requestOrVoid;
-  CacheQueryParams params;
-};
-
-struct StorageMatchArgs
-{
-  CacheRequest request;
-  CacheQueryParams params;
-};
-
-struct StorageHasArgs
-{
-  nsString key;
-};
-
-struct StorageOpenArgs
-{
-  nsString key;
-};
-
-struct StorageDeleteArgs
-{
-  nsString key;
-};
-
-struct StorageKeysArgs
-{
-};
-
-union CacheOpArgs
-{
-  CacheMatchArgs;
-  CacheMatchAllArgs;
-  CacheAddAllArgs;
-  CachePutAllArgs;
-  CacheDeleteArgs;
-  CacheKeysArgs;
-  StorageMatchArgs;
-  StorageHasArgs;
-  StorageOpenArgs;
-  StorageDeleteArgs;
-  StorageKeysArgs;
-};
-
-struct CacheMatchResult
-{
-  CacheResponseOrVoid responseOrVoid;
-};
-
-struct CacheMatchAllResult
-{
-  CacheResponse[] responseList;
-};
-
-struct CacheAddAllResult
-{
-};
-
-struct CachePutAllResult
-{
-};
-
-struct CacheDeleteResult
-{
-  bool success;
-};
-
-struct CacheKeysResult
-{
-  CacheRequest[] requestList;
-};
-
-struct StorageMatchResult
-{
-  CacheResponseOrVoid responseOrVoid;
-};
-
-struct StorageHasResult
-{
-  bool success;
-};
-
-struct StorageOpenResult
-{
-  nullable PCache actor;
-};
-
-struct StorageDeleteResult
-{
-  bool success;
-};
-
-struct StorageKeysResult
-{
-  nsString[] keyList;
-};
-
-union CacheOpResult
-{
-  void_t;
-  CacheMatchResult;
-  CacheMatchAllResult;
-  CacheAddAllResult;
-  CachePutAllResult;
-  CacheDeleteResult;
-  CacheKeysResult;
-  StorageMatchResult;
-  StorageHasResult;
-  StorageOpenResult;
-  StorageDeleteResult;
-  StorageKeysResult;
+  PCacheRequest request;
+  PCacheResponse response;
 };
 
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
--- a/dom/cache/PrincipalVerifier.cpp
+++ b/dom/cache/PrincipalVerifier.cpp
@@ -41,54 +41,44 @@ PrincipalVerifier::CreateAndDispatch(Lis
                                                                aPrincipalInfo);
 
   MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(verifier)));
 
   return verifier.forget();
 }
 
 void
-PrincipalVerifier::AddListener(Listener* aListener)
+PrincipalVerifier::ClearListener()
 {
   AssertIsOnBackgroundThread();
-  MOZ_ASSERT(aListener);
-  MOZ_ASSERT(!mListenerList.Contains(aListener));
-  mListenerList.AppendElement(aListener);
-}
-
-void
-PrincipalVerifier::RemoveListener(Listener* aListener)
-{
-  AssertIsOnBackgroundThread();
-  MOZ_ASSERT(aListener);
-  MOZ_ALWAYS_TRUE(mListenerList.RemoveElement(aListener));
+  MOZ_ASSERT(mListener);
+  mListener = nullptr;
 }
 
 PrincipalVerifier::PrincipalVerifier(Listener* aListener,
                                      PBackgroundParent* aActor,
                                      const PrincipalInfo& aPrincipalInfo)
-  : mActor(BackgroundParent::GetContentParent(aActor))
+  : mListener(aListener)
+  , mActor(BackgroundParent::GetContentParent(aActor))
   , mPrincipalInfo(aPrincipalInfo)
   , mInitiatingThread(NS_GetCurrentThread())
   , mResult(NS_OK)
 {
   AssertIsOnBackgroundThread();
+  MOZ_ASSERT(mListener);
   MOZ_ASSERT(mInitiatingThread);
-  MOZ_ASSERT(aListener);
-
-  mListenerList.AppendElement(aListener);
 }
 
 PrincipalVerifier::~PrincipalVerifier()
 {
   // Since the PrincipalVerifier is a Runnable that executes on multiple
   // threads, its a race to see which thread de-refs us last.  Therefore
   // we cannot guarantee which thread we destruct on.
 
-  MOZ_ASSERT(mListenerList.IsEmpty());
+  MOZ_ASSERT(!mListener);
 
   // We should always be able to explicitly release the actor on the main
   // thread.
   MOZ_ASSERT(!mActor);
 }
 
 NS_IMETHODIMP
 PrincipalVerifier::Run()
@@ -177,23 +167,27 @@ PrincipalVerifier::VerifyOnMainThread()
 
   DispatchToInitiatingThread(NS_OK);
 }
 
 void
 PrincipalVerifier::CompleteOnInitiatingThread()
 {
   AssertIsOnBackgroundThread();
-  ListenerList::ForwardIterator iter(mListenerList);
-  while (iter.HasMore()) {
-    iter.GetNext()->OnPrincipalVerified(mResult, mManagerId);
+
+  // This can happen if the listener is destroyed before we finish.  For
+  // example, if the child process OOMs and the actor is destroyed.
+  if (!mListener) {
+    return;
   }
 
-  // The listener must clear its reference in OnPrincipalVerified()
-  MOZ_ASSERT(mListenerList.IsEmpty());
+  mListener->OnPrincipalVerified(mResult, mManagerId);
+
+  // The listener must clear their reference in OnPrincipalVerified()
+  MOZ_ASSERT(!mListener);
 }
 
 void
 PrincipalVerifier::DispatchToInitiatingThread(nsresult aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   mResult = aRv;
--- a/dom/cache/PrincipalVerifier.h
+++ b/dom/cache/PrincipalVerifier.h
@@ -4,17 +4,16 @@
  * 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 mozilla_dom_cache_PrincipalVerifier_h
 #define mozilla_dom_cache_PrincipalVerifier_h
 
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "nsThreadUtils.h"
-#include "nsTObserverArray.h"
 
 namespace mozilla {
 
 namespace ipc {
   class PBackgroundParent;
 }
 
 namespace dom {
@@ -22,47 +21,44 @@ namespace cache {
 
 class ManagerId;
 
 class PrincipalVerifier final : public nsRunnable
 {
 public:
   // An interface to be implemented by code wishing to use the
   // PrincipalVerifier.  Note, the Listener implementation is responsible
-  // for calling RemoveListener() on the PrincipalVerifier to clear the
+  // for calling ClearListener() on the PrincipalVerifier to clear the
   // weak reference.
   class Listener
   {
   public:
     virtual void OnPrincipalVerified(nsresult aRv, ManagerId* aManagerId) = 0;
   };
 
   static already_AddRefed<PrincipalVerifier>
   CreateAndDispatch(Listener* aListener, mozilla::ipc::PBackgroundParent* aActor,
                     const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
 
-  void AddListener(Listener* aListener);
-
-  // The Listener must call RemoveListener() when OnPrincipalVerified() is
+  // The Listener must call ClearListener() when OnPrincipalVerified() is
   // called or when the Listener is destroyed.
-  void RemoveListener(Listener* aListener);
+  void ClearListener();
 
 private:
   PrincipalVerifier(Listener* aListener, mozilla::ipc::PBackgroundParent* aActor,
                     const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
   virtual ~PrincipalVerifier();
 
   void VerifyOnMainThread();
   void CompleteOnInitiatingThread();
 
   void DispatchToInitiatingThread(nsresult aRv);
 
-  // Weak reference cleared by RemoveListener()
-  typedef nsTObserverArray<Listener*> ListenerList;
-  ListenerList mListenerList;
+  // Weak reference cleared by ClearListener()
+  Listener* mListener;
 
   // set in originating thread at construction, but must be accessed and
   // released on main thread
   nsRefPtr<ContentParent> mActor;
 
   const mozilla::ipc::PrincipalInfo mPrincipalInfo;
   nsCOMPtr<nsIThread> mInitiatingThread;
   nsresult mResult;
--- a/dom/cache/ReadStream.cpp
+++ b/dom/cache/ReadStream.cpp
@@ -4,17 +4,17 @@
  * 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 "mozilla/dom/cache/ReadStream.h"
 
 #include "mozilla/unused.h"
 #include "mozilla/dom/cache/CacheStreamControlChild.h"
 #include "mozilla/dom/cache/CacheStreamControlParent.h"
-#include "mozilla/dom/cache/CacheTypes.h"
+#include "mozilla/dom/cache/PCacheTypes.h"
 #include "mozilla/ipc/FileDescriptor.h"
 #include "mozilla/ipc/InputStreamUtils.h"
 #include "mozilla/SnappyUncompressInputStream.h"
 #include "nsIAsyncInputStream.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 namespace dom {
@@ -30,20 +30,20 @@ using mozilla::ipc::FileDescriptor;
 // guaranteed by our outer ReadStream class.
 class ReadStream::Inner final : public ReadStream::Controllable
 {
 public:
   Inner(StreamControl* aControl, const nsID& aId,
         nsIInputStream* aStream);
 
   void
-  Serialize(CacheReadStreamOrVoid* aReadStreamOut);
+  Serialize(PCacheReadStreamOrVoid* aReadStreamOut);
 
   void
-  Serialize(CacheReadStream* aReadStreamOut);
+  Serialize(PCacheReadStream* aReadStreamOut);
 
   // ReadStream::Controllable methods
   virtual void
   CloseStream() override;
 
   virtual void
   CloseStreamWithoutReporting() override;
 
@@ -188,27 +188,27 @@ ReadStream::Inner::Inner(StreamControl* 
   , mState(Open)
 {
   MOZ_ASSERT(mStream);
   MOZ_ASSERT(mControl);
   mControl->AddReadStream(this);
 }
 
 void
-ReadStream::Inner::Serialize(CacheReadStreamOrVoid* aReadStreamOut)
+ReadStream::Inner::Serialize(PCacheReadStreamOrVoid* aReadStreamOut)
 {
   MOZ_ASSERT(NS_GetCurrentThread() == mOwningThread);
   MOZ_ASSERT(aReadStreamOut);
-  CacheReadStream stream;
+  PCacheReadStream stream;
   Serialize(&stream);
   *aReadStreamOut = stream;
 }
 
 void
-ReadStream::Inner::Serialize(CacheReadStream* aReadStreamOut)
+ReadStream::Inner::Serialize(PCacheReadStream* aReadStreamOut)
 {
   MOZ_ASSERT(NS_GetCurrentThread() == mOwningThread);
   MOZ_ASSERT(aReadStreamOut);
   MOZ_ASSERT(mState == Open);
   MOZ_ASSERT(mControl);
 
   // If we are sending a ReadStream, then we never want to set the
   // pushStream actors at the same time.
@@ -386,28 +386,28 @@ ReadStream::Inner::ForgetOnOwningThread(
 }
 
 // ----------------------------------------------------------------------------
 
 NS_IMPL_ISUPPORTS(cache::ReadStream, nsIInputStream, ReadStream);
 
 // static
 already_AddRefed<ReadStream>
-ReadStream::Create(const CacheReadStreamOrVoid& aReadStreamOrVoid)
+ReadStream::Create(const PCacheReadStreamOrVoid& aReadStreamOrVoid)
 {
-  if (aReadStreamOrVoid.type() == CacheReadStreamOrVoid::Tvoid_t) {
+  if (aReadStreamOrVoid.type() == PCacheReadStreamOrVoid::Tvoid_t) {
     return nullptr;
   }
 
-  return Create(aReadStreamOrVoid.get_CacheReadStream());
+  return Create(aReadStreamOrVoid.get_PCacheReadStream());
 }
 
 // static
 already_AddRefed<ReadStream>
-ReadStream::Create(const CacheReadStream& aReadStream)
+ReadStream::Create(const PCacheReadStream& aReadStream)
 {
   // The parameter may or may not be for a Cache created stream.  The way we
   // tell is by looking at the stream control actor.  If the actor exists,
   // then we know the Cache created it.
   if (!aReadStream.controlChild() && !aReadStream.controlParent()) {
     return nullptr;
   }
 
@@ -452,23 +452,23 @@ ReadStream::Create(PCacheStreamControlPa
   MOZ_ASSERT(aControl);
   auto actor = static_cast<CacheStreamControlParent*>(aControl);
   nsRefPtr<Inner> inner = new Inner(actor, aId, aStream);
   nsRefPtr<ReadStream> ref = new ReadStream(inner);
   return ref.forget();
 }
 
 void
-ReadStream::Serialize(CacheReadStreamOrVoid* aReadStreamOut)
+ReadStream::Serialize(PCacheReadStreamOrVoid* aReadStreamOut)
 {
   mInner->Serialize(aReadStreamOut);
 }
 
 void
-ReadStream::Serialize(CacheReadStream* aReadStreamOut)
+ReadStream::Serialize(PCacheReadStream* aReadStreamOut)
 {
   mInner->Serialize(aReadStreamOut);
 }
 
 ReadStream::ReadStream(ReadStream::Inner* aInner)
   : mInner(aInner)
 {
   MOZ_ASSERT(mInner);
--- a/dom/cache/ReadStream.h
+++ b/dom/cache/ReadStream.h
@@ -16,18 +16,18 @@
 #include "nsTArrayForwardDeclare.h"
 
 class nsIThread;
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
-class CacheReadStream;
-class CacheReadStreamOrVoid;
+class PCacheReadStream;
+class PCacheReadStreamOrVoid;
 class PCacheStreamControlParent;
 
 // IID for the dom::cache::ReadStream interface
 #define NS_DOM_CACHE_READSTREAM_IID \
 {0x8e5da7c9, 0x0940, 0x4f1d, \
   {0x97, 0x25, 0x5c, 0x59, 0x38, 0xdd, 0xb9, 0x9f}}
 
 
@@ -66,27 +66,27 @@ public:
     NS_IMETHOD_(MozExternalRefCountType)
     AddRef(void) = 0;
 
     NS_IMETHOD_(MozExternalRefCountType)
     Release(void) = 0;
   };
 
   static already_AddRefed<ReadStream>
-  Create(const CacheReadStreamOrVoid& aReadStreamOrVoid);
+  Create(const PCacheReadStreamOrVoid& aReadStreamOrVoid);
 
   static already_AddRefed<ReadStream>
-  Create(const CacheReadStream& aReadStream);
+  Create(const PCacheReadStream& aReadStream);
 
   static already_AddRefed<ReadStream>
   Create(PCacheStreamControlParent* aControl, const nsID& aId,
          nsIInputStream* aStream);
 
-  void Serialize(CacheReadStreamOrVoid* aReadStreamOut);
-  void Serialize(CacheReadStream* aReadStreamOut);
+  void Serialize(PCacheReadStreamOrVoid* aReadStreamOut);
+  void Serialize(PCacheReadStream* aReadStreamOut);
 
 private:
   class Inner;
 
   explicit ReadStream(Inner* aInner);
   ~ReadStream();
 
   // Hold a strong ref to an inner class that actually implements the
--- a/dom/cache/SavedTypes.h
+++ b/dom/cache/SavedTypes.h
@@ -5,39 +5,39 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_cache_SavedTypes_h
 #define mozilla_dom_cache_SavedTypes_h
 
 // NOTE: This cannot be rolled into Types.h because the IPC dependency.
 //       breaks webidl unified builds.
 
-#include "mozilla/dom/cache/CacheTypes.h"
+#include "mozilla/dom/cache/PCacheTypes.h"
 #include "mozilla/dom/cache/Types.h"
 #include "nsCOMPtr.h"
 #include "nsID.h"
 #include "nsIOutputStream.h"
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 struct SavedRequest
 {
   SavedRequest() : mHasBodyId(false) { mValue.body() = void_t(); }
-  CacheRequest mValue;
+  PCacheRequest mValue;
   bool mHasBodyId;
   nsID mBodyId;
   CacheId mCacheId;
 };
 
 struct SavedResponse
 {
   SavedResponse() : mHasBodyId(false) { mValue.body() = void_t(); }
-  CacheResponse mValue;
+  PCacheResponse mValue;
   bool mHasBodyId;
   nsID mBodyId;
   CacheId mCacheId;
 };
 
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
--- a/dom/cache/StreamControl.h
+++ b/dom/cache/StreamControl.h
@@ -15,34 +15,34 @@ struct nsID;
 
 namespace mozilla {
 namespace ipc {
  class FileDescriptor;
 }
 namespace dom {
 namespace cache {
 
-class CacheReadStream;
+class PCacheReadStream;
 
 // Abstract class to help implement the stream control Child and Parent actors.
 // This provides an interface to partly help with serialization of IPC types,
 // but also an implementation for tracking ReadStream objects.
 class StreamControl
 {
 public:
   // abstract interface that must be implemented by child class
   virtual void
-  SerializeControl(CacheReadStream* aReadStreamOut) = 0;
+  SerializeControl(PCacheReadStream* aReadStreamOut) = 0;
 
   virtual void
-  SerializeFds(CacheReadStream* aReadStreamOut,
+  SerializeFds(PCacheReadStream* aReadStreamOut,
                const nsTArray<mozilla::ipc::FileDescriptor>& aFds) = 0;
 
   virtual void
-  DeserializeFds(const CacheReadStream& aReadStream,
+  DeserializeFds(const PCacheReadStream& aReadStream,
                  nsTArray<mozilla::ipc::FileDescriptor>& aFdsOut) = 0;
 
   // inherited implementation of the ReadStream::Controllable list
 
   // Begin controlling the given ReadStream.  This causes a strong ref to
   // be held by the control.  The ReadStream must call NoteClosed() or
   // ForgetReadStream() to release this ref.
   void
--- a/dom/cache/StreamUtils.cpp
+++ b/dom/cache/StreamUtils.cpp
@@ -3,37 +3,37 @@
 /* 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 "mozilla/dom/cache/StreamUtils.h"
 
 #include "mozilla/unused.h"
 #include "mozilla/dom/cache/CacheStreamControlChild.h"
-#include "mozilla/dom/cache/CacheTypes.h"
+#include "mozilla/dom/cache/PCacheTypes.h"
 #include "mozilla/ipc/FileDescriptor.h"
 #include "mozilla/ipc/FileDescriptorSetChild.h"
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 namespace {
 
 using mozilla::unused;
 using mozilla::void_t;
 using mozilla::dom::cache::CacheStreamControlChild;
 using mozilla::dom::cache::Feature;
-using mozilla::dom::cache::CacheReadStream;
+using mozilla::dom::cache::PCacheReadStream;
 using mozilla::ipc::FileDescriptor;
 using mozilla::ipc::FileDescriptorSetChild;
 using mozilla::ipc::OptionalFileDescriptorSet;
 
 void
-StartDestroyStreamChild(const CacheReadStream& aReadStream)
+StartDestroyStreamChild(const PCacheReadStream& aReadStream)
 {
   CacheStreamControlChild* cacheControl =
     static_cast<CacheStreamControlChild*>(aReadStream.controlChild());
   if (cacheControl) {
     cacheControl->StartDestroy();
   }
 
   if (aReadStream.fds().type() ==
@@ -47,105 +47,105 @@ StartDestroyStreamChild(const CacheReadS
     fdSetActor->ForgetFileDescriptors(fds);
     MOZ_ASSERT(!fds.IsEmpty());
 
     unused << fdSetActor->Send__delete__(fdSetActor);
   }
 }
 
 void
-AddFeatureToStreamChild(const CacheReadStream& aReadStream, Feature* aFeature)
+AddFeatureToStreamChild(const PCacheReadStream& aReadStream, Feature* aFeature)
 {
   CacheStreamControlChild* cacheControl =
     static_cast<CacheStreamControlChild*>(aReadStream.controlChild());
   if (cacheControl) {
     cacheControl->SetFeature(aFeature);
   }
 }
 
 } // anonymous namespace
 
 void
-StartDestroyStreamChild(const CacheResponseOrVoid& aResponseOrVoid)
+StartDestroyStreamChild(const PCacheResponseOrVoid& aResponseOrVoid)
 {
-  if (aResponseOrVoid.type() == CacheResponseOrVoid::Tvoid_t) {
+  if (aResponseOrVoid.type() == PCacheResponseOrVoid::Tvoid_t) {
     return;
   }
 
-  StartDestroyStreamChild(aResponseOrVoid.get_CacheResponse());
+  StartDestroyStreamChild(aResponseOrVoid.get_PCacheResponse());
 }
 
 void
-StartDestroyStreamChild(const CacheResponse& aResponse)
+StartDestroyStreamChild(const PCacheResponse& aResponse)
 {
-  if (aResponse.body().type() == CacheReadStreamOrVoid::Tvoid_t) {
+  if (aResponse.body().type() == PCacheReadStreamOrVoid::Tvoid_t) {
     return;
   }
 
-  StartDestroyStreamChild(aResponse.body().get_CacheReadStream());
+  StartDestroyStreamChild(aResponse.body().get_PCacheReadStream());
 }
 
 void
-StartDestroyStreamChild(const nsTArray<CacheResponse>& aResponses)
+StartDestroyStreamChild(const nsTArray<PCacheResponse>& aResponses)
 {
   for (uint32_t i = 0; i < aResponses.Length(); ++i) {
     StartDestroyStreamChild(aResponses[i]);
   }
 }
 
 void
-StartDestroyStreamChild(const nsTArray<CacheRequest>& aRequests)
+StartDestroyStreamChild(const nsTArray<PCacheRequest>& aRequests)
 {
   for (uint32_t i = 0; i < aRequests.Length(); ++i) {
-    if (aRequests[i].body().type() == CacheReadStreamOrVoid::Tvoid_t) {
+    if (aRequests[i].body().type() == PCacheReadStreamOrVoid::Tvoid_t) {
       continue;
     }
-    StartDestroyStreamChild(aRequests[i].body().get_CacheReadStream());
+    StartDestroyStreamChild(aRequests[i].body().get_PCacheReadStream());
   }
 }
 
 void
-AddFeatureToStreamChild(const CacheResponseOrVoid& aResponseOrVoid,
+AddFeatureToStreamChild(const PCacheResponseOrVoid& aResponseOrVoid,
                         Feature* aFeature)
 {
-  if (aResponseOrVoid.type() == CacheResponseOrVoid::Tvoid_t) {
+  if (aResponseOrVoid.type() == PCacheResponseOrVoid::Tvoid_t) {
     return;
   }
 
-  AddFeatureToStreamChild(aResponseOrVoid.get_CacheResponse(), aFeature);
+  AddFeatureToStreamChild(aResponseOrVoid.get_PCacheResponse(), aFeature);
 }
 
 void
-AddFeatureToStreamChild(const CacheResponse& aResponse,
+AddFeatureToStreamChild(const PCacheResponse& aResponse,
                         Feature* aFeature)
 {
-  if (aResponse.body().type() == CacheReadStreamOrVoid::Tvoid_t) {
+  if (aResponse.body().type() == PCacheReadStreamOrVoid::Tvoid_t) {
     return;
   }
 
-  AddFeatureToStreamChild(aResponse.body().get_CacheReadStream(), aFeature);
+  AddFeatureToStreamChild(aResponse.body().get_PCacheReadStream(), aFeature);
 }
 
 void
-AddFeatureToStreamChild(const nsTArray<CacheResponse>& aResponses,
+AddFeatureToStreamChild(const nsTArray<PCacheResponse>& aResponses,
                          Feature* aFeature)
 {
   for (uint32_t i = 0; i < aResponses.Length(); ++i) {
     AddFeatureToStreamChild(aResponses[i], aFeature);
   }
 }
 
 void
-AddFeatureToStreamChild(const nsTArray<CacheRequest>& aRequests,
+AddFeatureToStreamChild(const nsTArray<PCacheRequest>& aRequests,
                          Feature* aFeature)
 {
   for (uint32_t i = 0; i < aRequests.Length(); ++i) {
-    if (aRequests[i].body().type() == CacheReadStreamOrVoid::Tvoid_t) {
+    if (aRequests[i].body().type() == PCacheReadStreamOrVoid::Tvoid_t) {
       continue;
     }
-    AddFeatureToStreamChild(aRequests[i].body().get_CacheReadStream(),
+    AddFeatureToStreamChild(aRequests[i].body().get_PCacheReadStream(),
                             aFeature);
   }
 }
 
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
--- a/dom/cache/StreamUtils.h
+++ b/dom/cache/StreamUtils.h
@@ -9,31 +9,31 @@
 
 #include "nsTArrayForwardDeclare.h"
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 class Feature;
-class CacheRequest;
-class CacheResponse;
-class CacheResponseOrVoid;
+class PCacheRequest;
+class PCacheResponse;
+class PCacheResponseOrVoid;
 
-void StartDestroyStreamChild(const CacheResponseOrVoid& aResponseOrVoid);
-void StartDestroyStreamChild(const CacheResponse& aResponse);
-void StartDestroyStreamChild(const nsTArray<CacheResponse>& aResponses);
-void StartDestroyStreamChild(const nsTArray<CacheRequest>& aRequests);
+void StartDestroyStreamChild(const PCacheResponseOrVoid& aResponseOrVoid);
+void StartDestroyStreamChild(const PCacheResponse& aResponse);
+void StartDestroyStreamChild(const nsTArray<PCacheResponse>& aResponses);
+void StartDestroyStreamChild(const nsTArray<PCacheRequest>& aRequests);
 
-void AddFeatureToStreamChild(const CacheResponseOrVoid& aResponseOrVoid,
+void AddFeatureToStreamChild(const PCacheResponseOrVoid& aResponseOrVoid,
                              Feature* aFeature);
-void AddFeatureToStreamChild(const CacheResponse& aResponse,
+void AddFeatureToStreamChild(const PCacheResponse& aResponse,
                              Feature* aFeature);
-void AddFeatureToStreamChild(const nsTArray<CacheResponse>& aResponses,
+void AddFeatureToStreamChild(const nsTArray<PCacheResponse>& aResponses,
                               Feature* aFeature);
-void AddFeatureToStreamChild(const nsTArray<CacheRequest>& aRequests,
+void AddFeatureToStreamChild(const nsTArray<PCacheRequest>& aRequests,
                               Feature* aFeature);
 
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_cache_StreamUtils_h
--- a/dom/cache/TypeUtils.cpp
+++ b/dom/cache/TypeUtils.cpp
@@ -7,17 +7,17 @@
 #include "mozilla/dom/cache/TypeUtils.h"
 
 #include "mozilla/unused.h"
 #include "mozilla/dom/CacheBinding.h"
 #include "mozilla/dom/InternalRequest.h"
 #include "mozilla/dom/Request.h"
 #include "mozilla/dom/Response.h"
 #include "mozilla/dom/cache/CachePushStreamChild.h"
-#include "mozilla/dom/cache/CacheTypes.h"
+#include "mozilla/dom/cache/PCacheTypes.h"
 #include "mozilla/dom/cache/ReadStream.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/FileDescriptorSetChild.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "mozilla/ipc/PFileDescriptorSetChild.h"
 #include "mozilla/ipc/InputStreamUtils.h"
 #include "nsCOMPtr.h"
 #include "nsIAsyncInputStream.h"
@@ -27,19 +27,17 @@
 #include "nsString.h"
 #include "nsURLParsers.h"
 
 namespace {
 
 using mozilla::ErrorResult;
 using mozilla::unused;
 using mozilla::void_t;
-using mozilla::dom::InternalHeaders;
-using mozilla::dom::cache::CacheReadStream;
-using mozilla::dom::cache::HeadersEntry;
+using mozilla::dom::cache::PCacheReadStream;
 using mozilla::ipc::BackgroundChild;
 using mozilla::ipc::FileDescriptor;
 using mozilla::ipc::PBackgroundChild;
 using mozilla::ipc::PFileDescriptorSetChild;
 
 // Utility function to remove the fragment from a URL, check its scheme, and optionally
 // provide a URL without the query.  We're not using nsIURL or URL to do this because
 // they require going to the main thread.
@@ -102,17 +100,17 @@ ProcessURL(nsAString& aUrl, bool* aSchem
   queryPos += pathPos;
 
   // We want everything before the query sine we already removed the trailing
   // fragment
   *aUrlWithoutQueryOut = Substring(aUrl, 0, queryPos - 1);
 }
 
 void
-SerializeNormalStream(nsIInputStream* aStream, CacheReadStream& aReadStreamOut)
+SerializeNormalStream(nsIInputStream* aStream, PCacheReadStream& aReadStreamOut)
 {
   nsAutoTArray<FileDescriptor, 4> fds;
   SerializeInputStream(aStream, aReadStreamOut.params(), fds);
 
   PFileDescriptorSetChild* fdSet = nullptr;
   if (!fds.IsEmpty()) {
     // We should not be serializing until we have an actor ready
     PBackgroundChild* manager = BackgroundChild::GetForCurrentThread();
@@ -126,30 +124,16 @@ SerializeNormalStream(nsIInputStream* aS
 
   if (fdSet) {
     aReadStreamOut.fds() = fdSet;
   } else {
     aReadStreamOut.fds() = void_t();
   }
 }
 
-void
-ToHeadersEntryList(nsTArray<HeadersEntry>& aOut, InternalHeaders* aHeaders)
-{
-  MOZ_ASSERT(aHeaders);
-
-  nsAutoTArray<InternalHeaders::Entry, 16> entryList;
-  aHeaders->GetEntries(entryList);
-
-  for (uint32_t i = 0; i < entryList.Length(); ++i) {
-    InternalHeaders::Entry& entry = entryList[i];
-    aOut.AppendElement(HeadersEntry(entry.mName, entry.mValue));
-  }
-}
-
 } // anonymous namespace
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 using mozilla::ipc::BackgroundChild;
 using mozilla::ipc::FileDescriptor;
@@ -192,20 +176,20 @@ TypeUtils::ToInternalRequest(const Ownin
 
     return request->GetInternalRequest();
   }
 
   return ToInternalRequest(aIn.GetAsUSVString(), aRv);
 }
 
 void
-TypeUtils::ToCacheRequest(CacheRequest& aOut, InternalRequest* aIn,
-                          BodyAction aBodyAction,
-                          ReferrerAction aReferrerAction,
-                          SchemeAction aSchemeAction, ErrorResult& aRv)
+TypeUtils::ToPCacheRequest(PCacheRequest& aOut, InternalRequest* aIn,
+                           BodyAction aBodyAction,
+                           ReferrerAction aReferrerAction,
+                           SchemeAction aSchemeAction, ErrorResult& aRv)
 {
   MOZ_ASSERT(aIn);
 
   aIn->GetMethod(aOut.method());
 
   nsAutoCString url;
   aIn->GetURL(url);
   CopyUTF8toUTF16(url, aOut.url());
@@ -231,17 +215,17 @@ TypeUtils::ToCacheRequest(CacheRequest& 
 
   if (aReferrerAction == ExpandReferrer) {
     UpdateRequestReferrer(GetGlobalObject(), aIn);
   }
   aIn->GetReferrer(aOut.referrer());
 
   nsRefPtr<InternalHeaders> headers = aIn->Headers();
   MOZ_ASSERT(headers);
-  ToHeadersEntryList(aOut.headers(), headers);
+  headers->GetPHeaders(aOut.headers());
   aOut.headersGuard() = headers->Guard();
   aOut.mode() = aIn->Mode();
   aOut.credentials() = aIn->GetCredentialsMode();
   aOut.contentPolicyType() = aIn->ContentPolicyType();
   aOut.context() = aIn->Context();
   aOut.requestCache() = aIn->GetCacheMode();
 
   if (aBodyAction == IgnoreBody) {
@@ -255,18 +239,18 @@ TypeUtils::ToCacheRequest(CacheRequest& 
   aIn->GetBody(getter_AddRefs(stream));
   SerializeCacheStream(stream, &aOut.body(), aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 }
 
 void
-TypeUtils::ToCacheResponseWithoutBody(CacheResponse& aOut,
-                                      InternalResponse& aIn, ErrorResult& aRv)
+TypeUtils::ToPCacheResponseWithoutBody(PCacheResponse& aOut,
+                                       InternalResponse& aIn, ErrorResult& aRv)
 {
   aOut.type() = aIn.Type();
 
   nsAutoCString url;
   aIn.GetUrl(url);
   CopyUTF8toUTF16(url, aOut.url());
 
   if (aOut.url() != EmptyString()) {
@@ -277,75 +261,75 @@ TypeUtils::ToCacheResponseWithoutBody(Ca
       return;
     }
   }
 
   aOut.status() = aIn.GetStatus();
   aOut.statusText() = aIn.GetStatusText();
   nsRefPtr<InternalHeaders> headers = aIn.UnfilteredHeaders();
   MOZ_ASSERT(headers);
-  ToHeadersEntryList(aOut.headers(), headers);
+  headers->GetPHeaders(aOut.headers());
   aOut.headersGuard() = headers->Guard();
   aOut.securityInfo() = aIn.GetSecurityInfo();
 }
 
 void
-TypeUtils::ToCacheResponse(CacheResponse& aOut, Response& aIn, ErrorResult& aRv)
+TypeUtils::ToPCacheResponse(PCacheResponse& aOut, Response& aIn, ErrorResult& aRv)
 {
   if (aIn.BodyUsed()) {
     aRv.ThrowTypeError(MSG_FETCH_BODY_CONSUMED_ERROR);
     return;
   }
 
   nsRefPtr<InternalResponse> ir = aIn.GetInternalResponse();
-  ToCacheResponseWithoutBody(aOut, *ir, aRv);
+  ToPCacheResponseWithoutBody(aOut, *ir, aRv);
 
   nsCOMPtr<nsIInputStream> stream;
   aIn.GetBody(getter_AddRefs(stream));
   if (stream) {
     aIn.SetBodyUsed();
   }
 
   SerializeCacheStream(stream, &aOut.body(), aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 }
 
 // static
 void
-TypeUtils::ToCacheQueryParams(CacheQueryParams& aOut,
-                              const CacheQueryOptions& aIn)
+TypeUtils::ToPCacheQueryParams(PCacheQueryParams& aOut,
+                               const CacheQueryOptions& aIn)
 {
   aOut.ignoreSearch() = aIn.mIgnoreSearch;
   aOut.ignoreMethod() = aIn.mIgnoreMethod;
   aOut.ignoreVary() = aIn.mIgnoreVary;
   aOut.cacheNameSet() = aIn.mCacheName.WasPassed();
   if (aOut.cacheNameSet()) {
     aOut.cacheName() = aIn.mCacheName.Value();
   } else {
     aOut.cacheName() = NS_LITERAL_STRING("");
   }
 }
 
 already_AddRefed<Response>
-TypeUtils::ToResponse(const CacheResponse& aIn)
+TypeUtils::ToResponse(const PCacheResponse& aIn)
 {
   if (aIn.type() == ResponseType::Error) {
     nsRefPtr<InternalResponse> error = InternalResponse::NetworkError();
     nsRefPtr<Response> r = new Response(GetGlobalObject(), error);
     return r.forget();
   }
 
   nsRefPtr<InternalResponse> ir = new InternalResponse(aIn.status(),
                                                        aIn.statusText());
   ir->SetUrl(NS_ConvertUTF16toUTF8(aIn.url()));
 
   nsRefPtr<InternalHeaders> internalHeaders =
-    ToInternalHeaders(aIn.headers(), aIn.headersGuard());
+    new InternalHeaders(aIn.headers(), aIn.headersGuard());
   ErrorResult result;
   ir->Headers()->SetGuard(aIn.headersGuard(), result);
   MOZ_ASSERT(!result.Failed());
   ir->Headers()->Fill(*internalHeaders, result);
   MOZ_ASSERT(!result.Failed());
 
   ir->SetSecurityInfo(aIn.securityInfo());
 
@@ -370,72 +354,55 @@ TypeUtils::ToResponse(const CacheRespons
   }
   MOZ_ASSERT(ir);
 
   nsRefPtr<Response> ref = new Response(GetGlobalObject(), ir);
   return ref.forget();
 }
 
 already_AddRefed<InternalRequest>
-TypeUtils::ToInternalRequest(const CacheRequest& aIn)
+TypeUtils::ToInternalRequest(const PCacheRequest& aIn)
 {
   nsRefPtr<InternalRequest> internalRequest = new InternalRequest();
 
   internalRequest->SetMethod(aIn.method());
   internalRequest->SetURL(NS_ConvertUTF16toUTF8(aIn.url()));
   internalRequest->SetReferrer(aIn.referrer());
   internalRequest->SetMode(aIn.mode());
   internalRequest->SetCredentialsMode(aIn.credentials());
   internalRequest->SetContentPolicyType(aIn.contentPolicyType());
   DebugOnly<RequestContext> contextAfterSetContentPolicyType = internalRequest->Context();
   internalRequest->SetContext(aIn.context());
   MOZ_ASSERT(contextAfterSetContentPolicyType.value == internalRequest->Context(),
              "The RequestContext and nsContentPolicyType values should not get out of sync");
   internalRequest->SetCacheMode(aIn.requestCache());
 
   nsRefPtr<InternalHeaders> internalHeaders =
-    ToInternalHeaders(aIn.headers(), aIn.headersGuard());
+    new InternalHeaders(aIn.headers(), aIn.headersGuard());
   ErrorResult result;
   internalRequest->Headers()->SetGuard(aIn.headersGuard(), result);
   MOZ_ASSERT(!result.Failed());
   internalRequest->Headers()->Fill(*internalHeaders, result);
   MOZ_ASSERT(!result.Failed());
 
   nsCOMPtr<nsIInputStream> stream = ReadStream::Create(aIn.body());
 
   internalRequest->SetBody(stream);
 
   return internalRequest.forget();
 }
 
 already_AddRefed<Request>
-TypeUtils::ToRequest(const CacheRequest& aIn)
+TypeUtils::ToRequest(const PCacheRequest& aIn)
 {
   nsRefPtr<InternalRequest> internalRequest = ToInternalRequest(aIn);
   nsRefPtr<Request> request = new Request(GetGlobalObject(), internalRequest);
   return request.forget();
 }
 
-// static
-already_AddRefed<InternalHeaders>
-TypeUtils::ToInternalHeaders(const nsTArray<HeadersEntry>& aHeadersEntryList,
-                             HeadersGuardEnum aGuard)
-{
-  nsTArray<InternalHeaders::Entry> entryList(aHeadersEntryList.Length());
-
-  for (uint32_t i = 0; i < aHeadersEntryList.Length(); ++i) {
-    const HeadersEntry& headersEntry = aHeadersEntryList[i];
-    entryList.AppendElement(InternalHeaders::Entry(headersEntry.name(),
-                                                   headersEntry.value()));
-  }
-
-  nsRefPtr<InternalHeaders> ref = new InternalHeaders(Move(entryList), aGuard);
-  return ref.forget();
-}
-
 void
 TypeUtils::CheckAndSetBodyUsed(Request* aRequest, BodyAction aBodyAction,
                                ErrorResult& aRv)
 {
   MOZ_ASSERT(aRequest);
 
   if (aBodyAction == IgnoreBody) {
     return;
@@ -473,32 +440,32 @@ TypeUtils::ToInternalRequest(const nsASt
                                                    RequestInit(), aRv);
   if (NS_WARN_IF(aRv.Failed())) { return nullptr; }
 
   return request->GetInternalRequest();
 }
 
 void
 TypeUtils::SerializeCacheStream(nsIInputStream* aStream,
-                                CacheReadStreamOrVoid* aStreamOut,
+                                PCacheReadStreamOrVoid* aStreamOut,
                                 ErrorResult& aRv)
 {
   *aStreamOut = void_t();
   if (!aStream) {
     return;
   }
 
   // Option 1: Send a cache-specific ReadStream if we can.
   nsRefPtr<ReadStream> controlled = do_QueryObject(aStream);
   if (controlled) {
     controlled->Serialize(aStreamOut);
     return;
   }
 
-  CacheReadStream readStream;
+  PCacheReadStream readStream;
   readStream.controlChild() = nullptr;
   readStream.controlParent() = nullptr;
   readStream.pushStreamChild() = nullptr;
   readStream.pushStreamParent() = nullptr;
 
   // Option 2: Do normal stream serialization if its supported.
   nsCOMPtr<nsIIPCSerializableInputStream> serial = do_QueryInterface(aStream);
   if (serial) {
@@ -512,17 +479,17 @@ TypeUtils::SerializeCacheStream(nsIInput
     if (NS_WARN_IF(aRv.Failed())) { return; }
   }
 
   *aStreamOut = readStream;
 }
 
 void
 TypeUtils::SerializePushStream(nsIInputStream* aStream,
-                               CacheReadStream& aReadStreamOut,
+                               PCacheReadStream& aReadStreamOut,
                                ErrorResult& aRv)
 {
   nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aStream);
   if (NS_WARN_IF(!asyncStream)) {
     aRv = NS_ERROR_FAILURE;
     return;
   }
 
--- a/dom/cache/TypeUtils.h
+++ b/dom/cache/TypeUtils.h
@@ -4,17 +4,16 @@
  * 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 mozilla_dom_cache_TypesUtils_h
 #define mozilla_dom_cache_TypesUtils_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/BindingUtils.h"
-#include "mozilla/dom/InternalHeaders.h"
 #include "nsError.h"
 
 class nsIGlobalObject;
 class nsIAsyncInputStream;
 class nsIInputStream;
 
 namespace mozilla {
 namespace dom {
@@ -25,22 +24,21 @@ class InternalResponse;
 class OwningRequestOrUSVString;
 class Request;
 class RequestOrUSVString;
 class Response;
 
 namespace cache {
 
 class CachePushStreamChild;
-class CacheQueryParams;
-class CacheReadStream;
-class CacheReadStreamOrVoid;
-class CacheRequest;
-class CacheResponse;
-class HeadersEntry;
+class PCacheQueryParams;
+class PCacheReadStream;
+class PCacheReadStreamOrVoid;
+class PCacheRequest;
+class PCacheResponse;
 
 class TypeUtils
 {
 public:
   enum BodyAction
   {
     IgnoreBody,
     ReadBody
@@ -74,58 +72,53 @@ public:
   ToInternalRequest(const RequestOrUSVString& aIn, BodyAction aBodyAction,
                     ErrorResult& aRv);
 
   already_AddRefed<InternalRequest>
   ToInternalRequest(const OwningRequestOrUSVString& aIn, BodyAction aBodyAction,
                     ErrorResult& aRv);
 
   void
-  ToCacheRequest(CacheRequest& aOut, InternalRequest* aIn,
-                 BodyAction aBodyAction, ReferrerAction aReferrerAction,
-                 SchemeAction aSchemeAction, ErrorResult& aRv);
+  ToPCacheRequest(PCacheRequest& aOut, InternalRequest* aIn,
+                  BodyAction aBodyAction, ReferrerAction aReferrerAction,
+                  SchemeAction aSchemeAction, ErrorResult& aRv);
 
   void
-  ToCacheResponseWithoutBody(CacheResponse& aOut, InternalResponse& aIn,
-                             ErrorResult& aRv);
-
-  void
-  ToCacheResponse(CacheResponse& aOut, Response& aIn, ErrorResult& aRv);
+  ToPCacheResponseWithoutBody(PCacheResponse& aOut, InternalResponse& aIn,
+                              ErrorResult& aRv);
 
   void
-  ToCacheQueryParams(CacheQueryParams& aOut, const CacheQueryOptions& aIn);
+  ToPCacheResponse(PCacheResponse& aOut, Response& aIn, ErrorResult& aRv);
+
+  void
+  ToPCacheQueryParams(PCacheQueryParams& aOut, const CacheQueryOptions& aIn);
 
   already_AddRefed<Response>
-  ToResponse(const CacheResponse& aIn);
+  ToResponse(const PCacheResponse& aIn);
 
   already_AddRefed<InternalRequest>
-  ToInternalRequest(const CacheRequest& aIn);
+  ToInternalRequest(const PCacheRequest& aIn);
 
   already_AddRefed<Request>
-  ToRequest(const CacheRequest& aIn);
-
-  // static methods
-  static already_AddRefed<InternalHeaders>
-  ToInternalHeaders(const nsTArray<HeadersEntry>& aHeadersEntryList,
-                    HeadersGuardEnum aGuard = HeadersGuardEnum::None);
+  ToRequest(const PCacheRequest& aIn);
 
 private:
   void
   CheckAndSetBodyUsed(Request* aRequest, BodyAction aBodyAction,
                       ErrorResult& aRv);
 
   already_AddRefed<InternalRequest>
   ToInternalRequest(const nsAString& aIn, ErrorResult& aRv);
 
   void
-  SerializeCacheStream(nsIInputStream* aStream, CacheReadStreamOrVoid* aStreamOut,
+  SerializeCacheStream(nsIInputStream* aStream, PCacheReadStreamOrVoid* aStreamOut,
                        ErrorResult& aRv);
 
   void
-  SerializePushStream(nsIInputStream* aStream, CacheReadStream& aReadStreamOut,
+  SerializePushStream(nsIInputStream* aStream, PCacheReadStream& aReadStreamOut,
                       ErrorResult& aRv);
 };
 
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_cache_TypesUtils_h
--- a/dom/cache/Types.h
+++ b/dom/cache/Types.h
@@ -17,17 +17,19 @@ namespace dom {
 namespace cache {
 
 enum Namespace
 {
   DEFAULT_NAMESPACE,
   CHROME_ONLY_NAMESPACE,
   NUMBER_OF_NAMESPACES
 };
-static const Namespace INVALID_NAMESPACE = NUMBER_OF_NAMESPACES;
+
+typedef uintptr_t RequestId;
+static const RequestId INVALID_REQUEST_ID = 0;
 
 typedef int64_t CacheId;
 static const CacheId INVALID_CACHE_ID = -1;
 
 struct QuotaInfo
 {
   QuotaInfo() : mIsApp(false) { }
   nsCOMPtr<nsIFile> mDir;
--- a/dom/cache/moz.build
+++ b/dom/cache/moz.build
@@ -6,18 +6,16 @@
 
 EXPORTS.mozilla.dom.cache += [
     'Action.h',
     'ActorChild.h',
     'ActorUtils.h',
     'AutoUtils.h',
     'Cache.h',
     'CacheChild.h',
-    'CacheOpChild.h',
-    'CacheOpParent.h',
     'CacheParent.h',
     'CachePushStreamChild.h',
     'CachePushStreamParent.h',
     'CacheStorage.h',
     'CacheStorageChild.h',
     'CacheStorageParent.h',
     'CacheStreamControlChild.h',
     'CacheStreamControlParent.h',
@@ -43,18 +41,16 @@ EXPORTS.mozilla.dom.cache += [
 ]
 
 UNIFIED_SOURCES += [
     'Action.cpp',
     'ActorChild.cpp',
     'AutoUtils.cpp',
     'Cache.cpp',
     'CacheChild.cpp',
-    'CacheOpChild.cpp',
-    'CacheOpParent.cpp',
     'CacheParent.cpp',
     'CachePushStreamChild.cpp',
     'CachePushStreamParent.cpp',
     'CacheStorage.cpp',
     'CacheStorageChild.cpp',
     'CacheStorageParent.cpp',
     'CacheStreamControlChild.cpp',
     'CacheStreamControlParent.cpp',
@@ -72,22 +68,22 @@ UNIFIED_SOURCES += [
     'ReadStream.cpp',
     'StreamControl.cpp',
     'StreamList.cpp',
     'StreamUtils.cpp',
     'TypeUtils.cpp',
 ]
 
 IPDL_SOURCES += [
-    'CacheTypes.ipdlh',
+    'CacheInitData.ipdlh',
     'PCache.ipdl',
-    'PCacheOp.ipdl',
     'PCachePushStream.ipdl',
     'PCacheStorage.ipdl',
     'PCacheStreamControl.ipdl',
+    'PCacheTypes.ipdlh',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '../workers',
 ]
 
new file mode 100644
--- /dev/null
+++ b/dom/fetch/FetchIPCUtils.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 mozilla_dom_FetchIPCUtils_h
+#define mozilla_dom_FetchIPCUtils_h
+
+#include "ipc/IPCMessageUtils.h"
+
+// Fix X11 header brain damage that conflicts with HeadersGuardEnum::None
+#undef None
+
+#include "mozilla/dom/HeadersBinding.h"
+#include "mozilla/dom/Request.h"
+#include "mozilla/dom/Response.h"
+
+namespace IPC {
+  template<>
+  struct ParamTraits<mozilla::dom::HeadersGuardEnum> :
+    public ContiguousEnumSerializer<mozilla::dom::HeadersGuardEnum,
+                                    mozilla::dom::HeadersGuardEnum::None,
+                                    mozilla::dom::HeadersGuardEnum::EndGuard_> {};
+  template<>
+  struct ParamTraits<mozilla::dom::RequestMode> :
+    public ContiguousEnumSerializer<mozilla::dom::RequestMode,
+                                    mozilla::dom::RequestMode::Same_origin,
+                                    mozilla::dom::RequestMode::EndGuard_> {};
+  template<>
+  struct ParamTraits<mozilla::dom::RequestCredentials> :
+    public ContiguousEnumSerializer<mozilla::dom::RequestCredentials,
+                                    mozilla::dom::RequestCredentials::Omit,
+                                    mozilla::dom::RequestCredentials::EndGuard_> {};
+  template<>
+  struct ParamTraits<mozilla::dom::RequestCache> :
+    public ContiguousEnumSerializer<mozilla::dom::RequestCache,
+                                    mozilla::dom::RequestCache::Default,
+                                    mozilla::dom::RequestCache::EndGuard_> {};
+  template<>
+  struct ParamTraits<mozilla::dom::RequestContext> :
+    public ContiguousEnumSerializer<mozilla::dom::RequestContext,
+                                    mozilla::dom::RequestContext::Audio,
+                                    mozilla::dom::RequestContext::EndGuard_> {};
+  template<>
+  struct ParamTraits<mozilla::dom::ResponseType> :
+    public ContiguousEnumSerializer<mozilla::dom::ResponseType,
+                                    mozilla::dom::ResponseType::Basic,
+                                    mozilla::dom::ResponseType::EndGuard_> {};
+}
+
+#endif // mozilla_dom_FetchIPCUtils_h
--- a/dom/fetch/InternalHeaders.cpp
+++ b/dom/fetch/InternalHeaders.cpp
@@ -2,30 +2,41 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "mozilla/dom/InternalHeaders.h"
 
 #include "mozilla/ErrorResult.h"
+#include "mozilla/dom/PHeaders.h"
 
 #include "nsCharSeparatedTokenizer.h"
 #include "nsContentUtils.h"
 #include "nsNetUtil.h"
 #include "nsReadableUtils.h"
 
 namespace mozilla {
 namespace dom {
 
-InternalHeaders::InternalHeaders(const nsTArray<Entry>&& aHeaders,
+InternalHeaders::InternalHeaders(const nsTArray<PHeadersEntry>& aHeaders,
                                  HeadersGuardEnum aGuard)
   : mGuard(aGuard)
-  , mList(aHeaders)
 {
+  for (uint32_t i = 0; i < aHeaders.Length(); ++i) {
+    mList.AppendElement(Entry(aHeaders[i].name(), aHeaders[i].value()));
+  }
+}
+
+void
+InternalHeaders::GetPHeaders(nsTArray<PHeadersEntry>& aPHeadersOut) const
+{
+  for (uint32_t i = 0; i < mList.Length(); ++i) {
+    aPHeadersOut.AppendElement(PHeadersEntry(mList[i].mName, mList[i].mValue));
+  }
 }
 
 void
 InternalHeaders::Append(const nsACString& aName, const nsACString& aValue,
                         ErrorResult& aRv)
 {
   nsAutoCString lowerName;
   ToLowerCase(aName, lowerName);
--- a/dom/fetch/InternalHeaders.h
+++ b/dom/fetch/InternalHeaders.h
@@ -19,16 +19,17 @@ class nsPIDOMWindow;
 namespace mozilla {
 
 class ErrorResult;
 
 namespace dom {
 
 template<typename T> class MozMap;
 class HeadersOrByteStringSequenceSequenceOrByteStringMozMap;
+class PHeadersEntry;
 
 class InternalHeaders final
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalHeaders)
 
 public:
   struct Entry
   {
@@ -56,17 +57,17 @@ public:
   explicit InternalHeaders(const InternalHeaders& aOther)
     : mGuard(aOther.mGuard)
   {
     ErrorResult result;
     Fill(aOther, result);
     MOZ_ASSERT(!result.Failed());
   }
 
-  explicit InternalHeaders(const nsTArray<Entry>&& aHeaders,
+  explicit InternalHeaders(const nsTArray<PHeadersEntry>& aHeaders,
                            HeadersGuardEnum aGuard = HeadersGuardEnum::None);
 
   void Append(const nsACString& aName, const nsACString& aValue,
               ErrorResult& aRv);
   void Delete(const nsACString& aName, ErrorResult& aRv);
   void Get(const nsACString& aName, nsCString& aValue, ErrorResult& aRv) const;
   void GetAll(const nsACString& aName, nsTArray<nsCString>& aResults,
               ErrorResult& aRv) const;
@@ -86,16 +87,19 @@ public:
 
   static already_AddRefed<InternalHeaders>
   BasicHeaders(InternalHeaders* aHeaders);
 
   static already_AddRefed<InternalHeaders>
   CORSHeaders(InternalHeaders* aHeaders);
 
   void
+  GetPHeaders(nsTArray<PHeadersEntry>& aPHeadersOut) const;
+
+  void
   GetEntries(nsTArray<InternalHeaders::Entry>& aEntries) const;
 
   void
   GetUnsafeHeaders(nsTArray<nsCString>& aNames) const;
 private:
   virtual ~InternalHeaders();
 
   static bool IsInvalidName(const nsACString& aName, ErrorResult& aRv);
new file mode 100644
--- /dev/null
+++ b/dom/fetch/PHeaders.ipdlh
@@ -0,0 +1,15 @@
+/* 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/. */
+
+namespace mozilla {
+namespace dom {
+
+struct PHeadersEntry
+{
+  nsCString name;
+  nsCString value;
+};
+
+} // namespace dom
+} // namespace mozilla
--- a/dom/fetch/moz.build
+++ b/dom/fetch/moz.build
@@ -2,16 +2,17 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS.mozilla.dom += [
     'Fetch.h',
     'FetchDriver.h',
+    'FetchIPCUtils.h',
     'Headers.h',
     'InternalHeaders.h',
     'InternalRequest.h',
     'InternalResponse.h',
     'Request.h',
     'Response.h',
 ]
 
@@ -21,16 +22,22 @@ UNIFIED_SOURCES += [
     'Headers.cpp',
     'InternalHeaders.cpp',
     'InternalRequest.cpp',
     'InternalResponse.cpp',
     'Request.cpp',
     'Response.cpp',
 ]
 
+IPDL_SOURCES += [
+    'PHeaders.ipdlh',
+]
+
+include('/ipc/chromium/chromium-config.mozbuild')
+
 LOCAL_INCLUDES += [
     '../workers',
     # For nsDataHandler.h
     '/netwerk/protocol/data',
 ]
 
 FAIL_ON_WARNINGS = True
 MSVC_ENABLE_PGO = True