Backed out 6 changesets (bug 1522579) for build bustages on a CLOSED TREE
authorAndreea Pavel <apavel@mozilla.com>
Mon, 25 Feb 2019 18:19:38 +0200
changeset 460916 2777f00531253613cabfa34b6a1e5d5a21ea4478
parent 460915 3c8320baa230205e3a8646051f13ce2c51d45a74
child 460917 b9a1181a0f15eeedf907456d939cb3b4e36bc8f4
push id35613
push usernerli@mozilla.com
push dateTue, 26 Feb 2019 03:52:35 +0000
treeherdermozilla-central@faec87a80ed1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1522579
milestone67.0a1
backs out3c8320baa230205e3a8646051f13ce2c51d45a74
0a288a3d85cddb5e554b7d1e65477d38f590bf9c
ecfd27e7d150c7dacd0878e91fcf4fa6e292023b
eda40fca075833f04fe28fc6855fd6dc423452b5
5c7aafa32a0a46330588c98516964e637163e834
a3c5a2c164113980f9a0075f0b70278c3e2fe122
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 6 changesets (bug 1522579) for build bustages on a CLOSED TREE Backed out changeset 3c8320baa230 (bug 1522579) Backed out changeset 0a288a3d85cd (bug 1522579) Backed out changeset ecfd27e7d150 (bug 1522579) Backed out changeset eda40fca0758 (bug 1522579) Backed out changeset 5c7aafa32a0a (bug 1522579) Backed out changeset a3c5a2c16411 (bug 1522579)
dom/base/TabGroup.cpp
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/base/nsFocusManager.cpp
dom/base/nsFrameLoader.cpp
dom/base/nsFrameMessageManager.cpp
dom/base/nsFrameMessageManager.h
dom/events/EventStateManager.cpp
dom/file/TemporaryFileBlobImpl.cpp
dom/file/ipc/IPCBlobInputStream.cpp
dom/file/ipc/IPCBlobInputStreamParent.cpp
dom/file/ipc/IPCBlobInputStreamParent.h
dom/file/ipc/IPCBlobUtils.cpp
dom/file/ipc/IPCBlobUtils.h
dom/file/ipc/PIPCBlobInputStream.ipdl
dom/indexedDB/FileSnapshot.cpp
dom/ipc/ContentBridgeChild.cpp
dom/ipc/ContentBridgeChild.h
dom/ipc/ContentBridgeParent.cpp
dom/ipc/ContentBridgeParent.h
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/ContentProcessManager.cpp
dom/ipc/ContentProcessManager.h
dom/ipc/FilePickerParent.cpp
dom/ipc/JSWindowActorChild.cpp
dom/ipc/JSWindowActorParent.cpp
dom/ipc/PBrowser.ipdl
dom/ipc/PContent.ipdl
dom/ipc/PContentBridge.ipdl
dom/ipc/ProcessPriorityManager.cpp
dom/ipc/RemoteFrameParent.cpp
dom/ipc/StructuredCloneData.cpp
dom/ipc/StructuredCloneData.h
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
dom/ipc/moz.build
dom/ipc/nsIContentChild.cpp
dom/ipc/nsIContentChild.h
dom/ipc/nsIContentParent.cpp
dom/ipc/nsIContentParent.h
dom/presentation/PresentationSessionInfo.h
ipc/chromium/src/chrome/common/ipc_message_utils.h
ipc/glue/BackgroundImpl.cpp
ipc/glue/FileDescriptorSetChild.h
ipc/glue/FileDescriptorSetParent.h
ipc/glue/IPCStreamChild.cpp
ipc/glue/IPCStreamParent.cpp
ipc/glue/IPCStreamSource.h
ipc/glue/IPCStreamUtils.cpp
ipc/glue/IPCStreamUtils.h
ipc/glue/InputStreamUtils.cpp
ipc/glue/InputStreamUtils.h
ipc/glue/PChildToParentStream.ipdl
ipc/glue/PFileDescriptorSet.ipdl
ipc/glue/PParentToChildStream.ipdl
ipc/glue/nsIIPCSerializableInputStream.h
ipc/ipdl/sync-messages.ini
js/ipc/PJavaScript.ipdl
layout/ipc/RenderFrame.cpp
netwerk/base/PartiallySeekableInputStream.cpp
netwerk/base/nsBufferedStreams.cpp
netwerk/base/nsFileStreams.cpp
netwerk/base/nsMIMEInputStream.cpp
netwerk/protocol/http/HttpChannelParentListener.cpp
security/manager/ssl/PSMContentListener.h
testing/web-platform/meta/encrypted-media/__dir__.ini
testing/web-platform/meta/websockets/binary/__dir__.ini
testing/web-platform/meta/websockets/constructor/__dir__.ini
toolkit/components/extensions/webrequest/ChannelWrapper.cpp
toolkit/components/extensions/webrequest/ChannelWrapper.h
toolkit/components/extensions/webrequest/WebRequestService.cpp
toolkit/components/extensions/webrequest/WebRequestService.h
xpcom/io/InputStreamLengthWrapper.cpp
xpcom/io/NonBlockingAsyncInputStream.cpp
xpcom/io/SlicedInputStream.cpp
xpcom/io/nsMultiplexInputStream.cpp
xpcom/io/nsStorageStream.cpp
xpcom/io/nsStringStream.cpp
xpcom/tests/gtest/TestNonBlockingAsyncInputStream.cpp
--- a/dom/base/TabGroup.cpp
+++ b/dom/base/TabGroup.cpp
@@ -1,17 +1,17 @@
 /* -*- 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/TabGroup.h"
 
-#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/nsIContentChild.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/TimeoutManager.h"
 #include "mozilla/AbstractThread.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/ThrottledEventQueue.h"
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -39,17 +39,16 @@
 #include "mozilla/BackgroundHangMonitor.h"
 #include "mozilla/Base64.h"
 #include "mozilla/BasePrincipal.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/Components.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/dom/BlobURLProtocolHandler.h"
-#include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/CustomElementRegistry.h"
 #include "mozilla/dom/Document.h"
 #include "mozilla/dom/MessageBroadcaster.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/DOMExceptionBinding.h"
 #include "mozilla/dom/DOMTypes.h"
@@ -7247,17 +7246,17 @@ void nsContentUtils::SetKeyboardIndicato
                           (void*)&stateInfo);
 }
 
 nsresult nsContentUtils::IPCTransferableToTransferable(
     const IPCDataTransfer& aDataTransfer, const bool& aIsPrivateData,
     nsIPrincipal* aRequestingPrincipal,
     const nsContentPolicyType& aContentPolicyType,
     nsITransferable* aTransferable,
-    mozilla::dom::ContentParent* aContentParent,
+    mozilla::dom::nsIContentParent* aContentParent,
     mozilla::dom::TabChild* aTabChild) {
   nsresult rv;
 
   const nsTArray<IPCDataTransferItem>& items = aDataTransfer.items();
   for (const auto& item : items) {
     aTransferable->AddDataFlavor(item.flavor().get());
 
     if (item.data().type() == IPCDataTransferData::TnsString) {
@@ -7308,18 +7307,18 @@ nsresult nsContentUtils::IPCTransferable
   aTransferable->SetIsPrivateData(aIsPrivateData);
   aTransferable->SetRequestingPrincipal(aRequestingPrincipal);
   aTransferable->SetContentPolicyType(aContentPolicyType);
   return NS_OK;
 }
 
 void nsContentUtils::TransferablesToIPCTransferables(
     nsIArray* aTransferables, nsTArray<IPCDataTransfer>& aIPC,
-    bool aInSyncMessage, mozilla::dom::ContentChild* aChild,
-    mozilla::dom::ContentParent* aParent) {
+    bool aInSyncMessage, mozilla::dom::nsIContentChild* aChild,
+    mozilla::dom::nsIContentParent* aParent) {
   aIPC.Clear();
   if (aTransferables) {
     uint32_t transferableCount = 0;
     aTransferables->GetLength(&transferableCount);
     for (uint32_t i = 0; i < transferableCount; ++i) {
       IPCDataTransfer* dt = aIPC.AppendElement();
       nsCOMPtr<nsITransferable> transferable =
           do_QueryElementAt(aTransferables, i);
@@ -7441,18 +7440,18 @@ nsresult nsContentUtils::DataTransferIte
 bool nsContentUtils::IsFlavorImage(const nsACString& aFlavor) {
   return aFlavor.EqualsLiteral(kNativeImageMime) ||
          aFlavor.EqualsLiteral(kJPEGImageMime) ||
          aFlavor.EqualsLiteral(kJPGImageMime) ||
          aFlavor.EqualsLiteral(kPNGImageMime) ||
          aFlavor.EqualsLiteral(kGIFImageMime);
 }
 
-static Shmem ConvertToShmem(mozilla::dom::ContentChild* aChild,
-                            mozilla::dom::ContentParent* aParent,
+static Shmem ConvertToShmem(mozilla::dom::nsIContentChild* aChild,
+                            mozilla::dom::nsIContentParent* aParent,
                             const nsACString& aInput) {
   MOZ_ASSERT((aChild && !aParent) || (!aChild && aParent));
 
   IShmemAllocator* allocator = aChild ? static_cast<IShmemAllocator*>(aChild)
                                       : static_cast<IShmemAllocator*>(aParent);
 
   Shmem result;
   if (!allocator->AllocShmem(aInput.Length(), SharedMemory::TYPE_BASIC,
@@ -7462,18 +7461,18 @@ static Shmem ConvertToShmem(mozilla::dom
 
   memcpy(result.get<char>(), aInput.BeginReading(), aInput.Length());
 
   return result;
 }
 
 void nsContentUtils::TransferableToIPCTransferable(
     nsITransferable* aTransferable, IPCDataTransfer* aIPCDataTransfer,
-    bool aInSyncMessage, mozilla::dom::ContentChild* aChild,
-    mozilla::dom::ContentParent* aParent) {
+    bool aInSyncMessage, mozilla::dom::nsIContentChild* aChild,
+    mozilla::dom::nsIContentParent* aParent) {
   MOZ_ASSERT((aChild && !aParent) || (!aChild && aParent));
 
   if (aTransferable) {
     nsTArray<nsCString> flavorList;
     aTransferable->FlavorsTransferableCanExport(flavorList);
 
     for (uint32_t j = 0; j < flavorList.Length(); ++j) {
       nsCString& flavorStr = flavorList[j];
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -139,18 +139,18 @@ class Event;
 class EventTarget;
 class HTMLInputElement;
 class IPCDataTransfer;
 class IPCDataTransferItem;
 struct LifecycleCallbackArgs;
 struct LifecycleAdoptedCallbackArgs;
 class MessageBroadcaster;
 class NodeInfo;
-class ContentChild;
-class ContentParent;
+class nsIContentChild;
+class nsIContentParent;
 class TabChild;
 class Selection;
 class TabParent;
 }  // namespace dom
 
 namespace ipc {
 class Shmem;
 class IShmemAllocator;
@@ -2828,29 +2828,29 @@ class nsContentUtils {
    */
   static bool IsFlavorImage(const nsACString& aFlavor);
 
   static nsresult IPCTransferableToTransferable(
       const mozilla::dom::IPCDataTransfer& aDataTransfer,
       const bool& aIsPrivateData, nsIPrincipal* aRequestingPrincipal,
       const nsContentPolicyType& aContentPolicyType,
       nsITransferable* aTransferable,
-      mozilla::dom::ContentParent* aContentParent,
+      mozilla::dom::nsIContentParent* aContentParent,
       mozilla::dom::TabChild* aTabChild);
 
   static void TransferablesToIPCTransferables(
       nsIArray* aTransferables, nsTArray<mozilla::dom::IPCDataTransfer>& aIPC,
-      bool aInSyncMessage, mozilla::dom::ContentChild* aChild,
-      mozilla::dom::ContentParent* aParent);
+      bool aInSyncMessage, mozilla::dom::nsIContentChild* aChild,
+      mozilla::dom::nsIContentParent* aParent);
 
   static void TransferableToIPCTransferable(
       nsITransferable* aTransferable,
       mozilla::dom::IPCDataTransfer* aIPCDataTransfer, bool aInSyncMessage,
-      mozilla::dom::ContentChild* aChild,
-      mozilla::dom::ContentParent* aParent);
+      mozilla::dom::nsIContentChild* aChild,
+      mozilla::dom::nsIContentParent* aParent);
 
   /*
    * Get the pixel data from the given source surface and return it as a buffer.
    * The length and stride will be assigned from the surface.
    */
   static mozilla::UniquePtr<char[]> GetSurfaceData(
       mozilla::NotNull<mozilla::gfx::DataSourceSurface*> aSurface,
       size_t* aLength, int32_t* aStride);
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -8,17 +8,17 @@
 
 #include "nsFocusManager.h"
 
 #include "ChildIterator.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsGkAtoms.h"
 #include "nsGlobalWindow.h"
 #include "nsContentUtils.h"
-#include "ContentParent.h"
+#include "nsIContentParent.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIHTMLDocument.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIFormControl.h"
 #include "nsLayoutUtils.h"
 #include "nsIPresShell.h"
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -2391,18 +2391,19 @@ static Tuple<ContentParent*, TabParent*>
 
   RefPtr<nsFrameLoader> otherLoader;
   browser->GetSameProcessAsFrameLoader(getter_AddRefs(otherLoader));
   if (!otherLoader) {
     return ReturnTuple(nullptr, nullptr);
   }
 
   TabParent* tabParent = TabParent::GetFrom(otherLoader);
-  if (tabParent && tabParent->Manager()) {
-    return MakeTuple(tabParent->Manager(), tabParent);
+  if (tabParent && tabParent->Manager() &&
+      tabParent->Manager()->IsContentParent()) {
+    return MakeTuple(tabParent->Manager()->AsContentParent(), tabParent);
   }
 
   return ReturnTuple(nullptr, nullptr);
 }
 
 bool nsFrameLoader::TryRemoteBrowser() {
   NS_ASSERTION(!mRemoteBrowser && !mRemoteFrameChild,
                "TryRemoteBrowser called with a remote browser already?");
@@ -2436,18 +2437,19 @@ bool nsFrameLoader::TryRemoteBrowser() {
   if (!parentDocShell) {
     return false;
   }
 
   TabParent* openingTab = TabParent::GetFrom(parentDocShell->GetOpener());
   RefPtr<ContentParent> openerContentParent;
   RefPtr<TabParent> sameTabGroupAs;
 
-  if (openingTab && openingTab->Manager()) {
-    openerContentParent = openingTab->Manager();
+  if (openingTab && openingTab->Manager() &&
+      openingTab->Manager()->IsContentParent()) {
+    openerContentParent = openingTab->Manager()->AsContentParent();
   }
 
   // <iframe mozbrowser> gets to skip these checks.
   // iframes for JS plugins also get to skip these checks. We control the URL
   // that gets loaded, but the load is triggered from the document containing
   // the plugin.
   // out of process iframes also get to skip this check.
   if (!OwnerIsMozBrowserFrame() && !XRE_IsContentProcess()) {
@@ -2723,17 +2725,17 @@ class nsAsyncMessageToChild : public nsS
 nsresult nsFrameLoader::DoSendAsyncMessage(JSContext* aCx,
                                            const nsAString& aMessage,
                                            StructuredCloneData& aData,
                                            JS::Handle<JSObject*> aCpows,
                                            nsIPrincipal* aPrincipal) {
   TabParent* tabParent = mRemoteBrowser;
   if (tabParent) {
     ClonedMessageData data;
-    ContentParent* cp = tabParent->Manager();
+    nsIContentParent* cp = tabParent->Manager();
     if (!BuildClonedMessageDataForParent(cp, aData, data)) {
       MOZ_CRASH();
       return NS_ERROR_DOM_DATA_CLONE_ERR;
     }
     InfallibleTArray<mozilla::jsipc::CpowEntry> cpows;
     jsipc::CPOWManager* mgr = cp->GetCPOWManager();
     if (aCpows && (!mgr || !mgr->Wrap(aCx, aCpows, &cpows))) {
       return NS_ERROR_UNEXPECTED;
@@ -2962,17 +2964,17 @@ void nsFrameLoader::RequestUpdatePositio
 
 void nsFrameLoader::Print(uint64_t aOuterWindowID,
                           nsIPrintSettings* aPrintSettings,
                           nsIWebProgressListener* aProgressListener,
                           ErrorResult& aRv) {
 #if defined(NS_PRINTING)
   if (mRemoteBrowser) {
     RefPtr<embedding::PrintingParent> printingParent =
-        mRemoteBrowser->Manager()->GetPrintingParent();
+        mRemoteBrowser->Manager()->AsContentParent()->GetPrintingParent();
 
     embedding::PrintData printData;
     nsresult rv = printingParent->SerializeAndEnsureRemotePrintJob(
         aPrintSettings, aProgressListener, nullptr, &printData);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       aRv.Throw(rv);
       return;
     }
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -163,23 +163,23 @@ void MessageManagerCallback::DoGetRemote
   if (!parent) {
     return;
   }
 
   parent->GetRemoteType(aRemoteType, aError);
 }
 
 bool MessageManagerCallback::BuildClonedMessageDataForParent(
-    ContentParent* aParent, StructuredCloneData& aData,
+    nsIContentParent* aParent, StructuredCloneData& aData,
     ClonedMessageData& aClonedData) {
   return aData.BuildClonedMessageDataForParent(aParent, aClonedData);
 }
 
 bool MessageManagerCallback::BuildClonedMessageDataForChild(
-    ContentChild* aChild, StructuredCloneData& aData,
+    nsIContentChild* aChild, StructuredCloneData& aData,
     ClonedMessageData& aClonedData) {
   return aData.BuildClonedMessageDataForChild(aChild, aClonedData);
 }
 
 void mozilla::dom::ipc::UnpackClonedMessageDataForParent(
     const ClonedMessageData& aClonedData, StructuredCloneData& aData) {
   aData.BorrowFromClonedMessageDataForParent(aClonedData);
 }
--- a/dom/base/nsFrameMessageManager.h
+++ b/dom/base/nsFrameMessageManager.h
@@ -39,18 +39,18 @@ class nsFrameLoader;
 namespace mozilla {
 
 namespace ipc {
 class FileDescriptor;
 }
 
 namespace dom {
 
-class ContentParent;
-class ContentChild;
+class nsIContentParent;
+class nsIContentChild;
 class ChildProcessMessageManager;
 class ChromeMessageBroadcaster;
 class ClonedMessageData;
 class MessageBroadcaster;
 class MessageListener;
 class MessageListenerManager;
 class MessageManagerReporter;
 template <typename T>
@@ -105,20 +105,20 @@ class MessageManagerCallback {
       const {
     return nullptr;
   }
 
   virtual void DoGetRemoteType(nsAString& aRemoteType,
                                ErrorResult& aError) const;
 
  protected:
-  bool BuildClonedMessageDataForParent(ContentParent* aParent,
+  bool BuildClonedMessageDataForParent(nsIContentParent* aParent,
                                        StructuredCloneData& aData,
                                        ClonedMessageData& aClonedData);
-  bool BuildClonedMessageDataForChild(ContentChild* aChild,
+  bool BuildClonedMessageDataForChild(nsIContentChild* aChild,
                                       StructuredCloneData& aData,
                                       ClonedMessageData& aClonedData);
 };
 
 void UnpackClonedMessageDataForParent(const ClonedMessageData& aClonedData,
                                       StructuredCloneData& aData);
 
 void UnpackClonedMessageDataForChild(const ClonedMessageData& aClonedData,
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -1240,17 +1240,20 @@ void EventStateManager::DispatchCrossPro
       // Let the child process synthesize a mouse event if needed, and
       // ensure we don't synthesize one in this process.
       *aStatus = nsEventStatus_eConsumeNoDefault;
       remote->SendRealTouchEvent(*aEvent->AsTouchEvent());
       return;
     }
     case eDragEventClass: {
       RefPtr<TabParent> tabParent = remote;
-      tabParent->Manager()->MaybeInvokeDragSession(tabParent);
+      if (tabParent->Manager()->IsContentParent()) {
+        tabParent->Manager()->AsContentParent()->MaybeInvokeDragSession(
+            tabParent);
+      }
 
       nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
       uint32_t dropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
       uint32_t action = nsIDragService::DRAGDROP_ACTION_NONE;
       nsCOMPtr<nsIPrincipal> principal;
       if (dragSession) {
         dragSession->DragEventDispatchedToChildProcess();
         dragSession->GetDragAction(&action);
@@ -5502,20 +5505,24 @@ nsresult EventStateManager::DoContentCom
     aEvent->mIsEnabled = canDoIt;
     if (canDoIt && !aEvent->mOnlyEnabledCheck) {
       switch (aEvent->mMessage) {
         case eContentCommandPasteTransferable: {
           nsFocusManager* fm = nsFocusManager::GetFocusManager();
           nsIContent* focusedContent = fm ? fm->GetFocusedElement() : nullptr;
           RefPtr<TabParent> remote = TabParent::GetFrom(focusedContent);
           if (remote) {
+            NS_ENSURE_TRUE(remote->Manager()->IsContentParent(),
+                           NS_ERROR_FAILURE);
+
             nsCOMPtr<nsITransferable> transferable = aEvent->mTransferable;
             IPCDataTransfer ipcDataTransfer;
+            ContentParent* cp = remote->Manager()->AsContentParent();
             nsContentUtils::TransferableToIPCTransferable(
-                transferable, &ipcDataTransfer, false, nullptr, remote->Manager());
+                transferable, &ipcDataTransfer, false, nullptr, cp);
             bool isPrivateData = transferable->GetIsPrivateData();
             nsCOMPtr<nsIPrincipal> requestingPrincipal =
                 transferable->GetRequestingPrincipal();
             nsContentPolicyType contentPolicyType =
                 transferable->GetContentPolicyType();
             remote->SendPasteTransferable(ipcDataTransfer, isPrivateData,
                                           IPC::Principal(requestingPrincipal),
                                           contentPolicyType);
--- a/dom/file/TemporaryFileBlobImpl.cpp
+++ b/dom/file/TemporaryFileBlobImpl.cpp
@@ -48,31 +48,31 @@ class TemporaryFileInputStream final : p
 
     stream.forget(aInputStream);
     return NS_OK;
   }
 
   void Serialize(InputStreamParams& aParams,
                  FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
                  uint32_t aMaxSize, uint32_t* aSizeUsed,
-                 ContentChild* aManager) override {
+                 nsIContentChild* aManager) override {
     MOZ_CRASH("This inputStream cannot be serialized.");
   }
 
   void Serialize(InputStreamParams& aParams,
                  FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
                  uint32_t aMaxSize, uint32_t* aSizeUsed,
                  PBackgroundChild* aManager) override {
     MOZ_CRASH("This inputStream cannot be serialized.");
   }
 
   void Serialize(InputStreamParams& aParams,
                  FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
                  uint32_t aMaxSize, uint32_t* aSizeUsed,
-                 ContentParent* aManager) override {
+                 nsIContentParent* aManager) override {
     MOZ_CRASH("This inputStream cannot be serialized.");
   }
 
   void Serialize(InputStreamParams& aParams,
                  FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
                  uint32_t aMaxSize, uint32_t* aSizeUsed,
                  PBackgroundParent* aManager) override {
     MOZ_CRASH("This inputStream cannot be serialized.");
--- a/dom/file/ipc/IPCBlobInputStream.cpp
+++ b/dom/file/ipc/IPCBlobInputStream.cpp
@@ -562,17 +562,17 @@ IPCBlobInputStream::OnInputStreamReady(n
 }
 
 // nsIIPCSerializableInputStream
 
 void IPCBlobInputStream::Serialize(mozilla::ipc::InputStreamParams& aParams,
                                    FileDescriptorArray& aFileDescriptors,
                                    bool aDelayedStart, uint32_t aMaxSize,
                                    uint32_t* aSizeUsed,
-                                   ContentChild* aManager) {
+                                   nsIContentChild* aManager) {
   MOZ_ASSERT(aSizeUsed);
   *aSizeUsed = 0;
 
   SerializeInternal(aParams);
 }
 
 void IPCBlobInputStream::Serialize(mozilla::ipc::InputStreamParams& aParams,
                                    FileDescriptorArray& aFileDescriptors,
@@ -584,17 +584,17 @@ void IPCBlobInputStream::Serialize(mozil
 
   SerializeInternal(aParams);
 }
 
 void IPCBlobInputStream::Serialize(mozilla::ipc::InputStreamParams& aParams,
                                    FileDescriptorArray& aFileDescriptors,
                                    bool aDelayedStart, uint32_t aMaxSize,
                                    uint32_t* aSizeUsed,
-                                   ContentParent* aManager) {
+                                   nsIContentParent* aManager) {
   MOZ_ASSERT(aSizeUsed);
   *aSizeUsed = 0;
 
   SerializeInternal(aParams);
 }
 
 void IPCBlobInputStream::Serialize(mozilla::ipc::InputStreamParams& aParams,
                                    FileDescriptorArray& aFileDescriptors,
--- a/dom/file/ipc/IPCBlobInputStreamParent.cpp
+++ b/dom/file/ipc/IPCBlobInputStreamParent.cpp
@@ -43,17 +43,17 @@ IPCBlobInputStreamParent::Create(const n
 
   actor->mCallback = IPCBlobInputStreamStorage::Get()->TakeCallback(aID);
 
   return actor.forget();
 }
 
 IPCBlobInputStreamParent::IPCBlobInputStreamParent(const nsID& aID,
                                                    uint64_t aSize,
-                                                   ContentParent* aManager)
+                                                   nsIContentParent* aManager)
     : mID(aID),
       mSize(aSize),
       mContentManager(aManager),
       mPBackgroundManager(nullptr),
       mMigrating(false) {}
 
 IPCBlobInputStreamParent::IPCBlobInputStreamParent(const nsID& aID,
                                                    uint64_t aSize,
--- a/dom/file/ipc/IPCBlobInputStreamParent.h
+++ b/dom/file/ipc/IPCBlobInputStreamParent.h
@@ -56,29 +56,29 @@ class IPCBlobInputStreamParent final
   mozilla::ipc::IPCResult RecvClose();
 
   mozilla::ipc::IPCResult Recv__delete__() override;
 
   bool HasValidStream() const;
 
  private:
   IPCBlobInputStreamParent(const nsID& aID, uint64_t aSize,
-                           ContentParent* aManager);
+                           nsIContentParent* aManager);
 
   IPCBlobInputStreamParent(const nsID& aID, uint64_t aSize,
                            mozilla::ipc::PBackgroundParent* aManager);
 
   ~IPCBlobInputStreamParent() = default;
 
   const nsID mID;
   const uint64_t mSize;
 
   // Only 1 of these 2 is set. Raw pointer because these 2 managers are keeping
   // the parent actor alive. The pointers will be nullified in ActorDestroyed.
-  ContentParent* mContentManager;
+  nsIContentParent* mContentManager;
   mozilla::ipc::PBackgroundParent* mPBackgroundManager;
 
   RefPtr<IPCBlobInputStreamParentCallback> mCallback;
 
   bool mMigrating;
 };
 
 }  // namespace dom
--- a/dom/file/ipc/IPCBlobUtils.cpp
+++ b/dom/file/ipc/IPCBlobUtils.cpp
@@ -129,49 +129,49 @@ nsresult SerializeInputStreamChild(nsIIn
   }
 
   aIPCBlob.inputStream() = ipcStream.TakeValue();
   return NS_OK;
 }
 
 nsresult SerializeInputStream(nsIInputStream* aInputStream, uint64_t aSize,
                               uint64_t aChildID, IPCBlob& aIPCBlob,
-                              ContentParent* aManager) {
+                              nsIContentParent* aManager) {
   return SerializeInputStreamParent(aInputStream, aSize, aChildID, aIPCBlob,
                                     aManager);
 }
 
 nsresult SerializeInputStream(nsIInputStream* aInputStream, uint64_t aSize,
                               uint64_t aChildID, IPCBlob& aIPCBlob,
                               PBackgroundParent* aManager) {
   return SerializeInputStreamParent(aInputStream, aSize, aChildID, aIPCBlob,
                                     aManager);
 }
 
 nsresult SerializeInputStream(nsIInputStream* aInputStream, uint64_t aSize,
                               uint64_t aChildID, IPCBlob& aIPCBlob,
-                              ContentChild* aManager) {
+                              nsIContentChild* aManager) {
   return SerializeInputStreamChild(aInputStream, aIPCBlob, aManager);
 }
 
 nsresult SerializeInputStream(nsIInputStream* aInputStream, uint64_t aSize,
                               uint64_t aChildID, IPCBlob& aIPCBlob,
                               PBackgroundChild* aManager) {
   return SerializeInputStreamChild(aInputStream, aIPCBlob, aManager);
 }
 
-uint64_t ChildIDFromManager(ContentParent* aManager) {
+uint64_t ChildIDFromManager(nsIContentParent* aManager) {
   return aManager->ChildID();
 }
 
 uint64_t ChildIDFromManager(PBackgroundParent* aManager) {
   return BackgroundParent::GetChildID(aManager);
 }
 
-uint64_t ChildIDFromManager(ContentChild* aManager) { return 0; }
+uint64_t ChildIDFromManager(nsIContentChild* aManager) { return 0; }
 
 uint64_t ChildIDFromManager(PBackgroundChild* aManager) { return 0; }
 
 template <typename M>
 nsresult SerializeInternal(BlobImpl* aBlobImpl, M* aManager,
                            IPCBlob& aIPCBlob) {
   MOZ_ASSERT(aBlobImpl);
 
@@ -227,27 +227,27 @@ nsresult SerializeInternal(BlobImpl* aBl
                             ChildIDFromManager(aManager), aIPCBlob, aManager);
   if (NS_WARN_IF(rv.Failed())) {
     return rv.StealNSResult();
   }
 
   return NS_OK;
 }
 
-nsresult Serialize(BlobImpl* aBlobImpl, ContentChild* aManager,
+nsresult Serialize(BlobImpl* aBlobImpl, nsIContentChild* aManager,
                    IPCBlob& aIPCBlob) {
   return SerializeInternal(aBlobImpl, aManager, aIPCBlob);
 }
 
 nsresult Serialize(BlobImpl* aBlobImpl, PBackgroundChild* aManager,
                    IPCBlob& aIPCBlob) {
   return SerializeInternal(aBlobImpl, aManager, aIPCBlob);
 }
 
-nsresult Serialize(BlobImpl* aBlobImpl, ContentParent* aManager,
+nsresult Serialize(BlobImpl* aBlobImpl, nsIContentParent* aManager,
                    IPCBlob& aIPCBlob) {
   return SerializeInternal(aBlobImpl, aManager, aIPCBlob);
 }
 
 nsresult Serialize(BlobImpl* aBlobImpl, PBackgroundParent* aManager,
                    IPCBlob& aIPCBlob) {
   return SerializeInternal(aBlobImpl, aManager, aIPCBlob);
 }
--- a/dom/file/ipc/IPCBlobUtils.h
+++ b/dom/file/ipc/IPCBlobUtils.h
@@ -217,32 +217,32 @@ namespace ipc {
 class IProtocol;
 class PBackgroundChild;
 class PBackgroundParent;
 }  // namespace ipc
 
 namespace dom {
 
 class IPCBlob;
-class ContentChild;
-class ContentParent;
+class nsIContentChild;
+class nsIContentParent;
 
 namespace IPCBlobUtils {
 
 already_AddRefed<BlobImpl> Deserialize(const IPCBlob& aIPCBlob);
 
 // These 4 methods serialize aBlobImpl into aIPCBlob using the right manager.
 
-nsresult Serialize(BlobImpl* aBlobImpl, ContentChild* aManager,
+nsresult Serialize(BlobImpl* aBlobImpl, nsIContentChild* aManager,
                    IPCBlob& aIPCBlob);
 
 nsresult Serialize(BlobImpl* aBlobImpl,
                    mozilla::ipc::PBackgroundChild* aManager, IPCBlob& aIPCBlob);
 
-nsresult Serialize(BlobImpl* aBlobImpl, ContentParent* aManager,
+nsresult Serialize(BlobImpl* aBlobImpl, nsIContentParent* aManager,
                    IPCBlob& aIPCBlob);
 
 nsresult Serialize(BlobImpl* aBlobImpl,
                    mozilla::ipc::PBackgroundParent* aManager,
                    IPCBlob& aIPCBlob);
 
 // WARNING: If you pass any actor which does not have P{Content,Background} as
 // its toplevel protocol, this method will MOZ_CRASH.
--- a/dom/file/ipc/PIPCBlobInputStream.ipdl
+++ b/dom/file/ipc/PIPCBlobInputStream.ipdl
@@ -1,26 +1,27 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PBackground;
 include protocol PChildToParentStream;
 include protocol PContent;
+include protocol PContentBridge;
 include protocol PFileDescriptorSet;
 include protocol PParentToChildStream;
 
 include IPCStream;
 
 namespace mozilla {
 namespace ipc {
 
 protocol PIPCBlobInputStream
 {
-  manager PBackground or PContent;
+  manager PBackground or PContent or PContentBridge;
 
 parent:
   async StreamNeeded();
 
   async LengthNeeded();
 
   // When this is called, the parent releases the inputStream and sends a
   // __delete__.
--- a/dom/indexedDB/FileSnapshot.cpp
+++ b/dom/indexedDB/FileSnapshot.cpp
@@ -268,33 +268,33 @@ StreamWrapper::ReadSegments(nsWriteSegme
 NS_IMETHODIMP
 StreamWrapper::IsNonBlocking(bool* _retval) {
   return mInputStream->IsNonBlocking(_retval);
 }
 
 void StreamWrapper::Serialize(InputStreamParams& aParams,
                               FileDescriptorArray& aFileDescriptors,
                               bool aDelayedStart, uint32_t aMaxSize,
-                              uint32_t* aSizeUsed, ContentChild* aManager) {
+                              uint32_t* aSizeUsed, nsIContentChild* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void StreamWrapper::Serialize(InputStreamParams& aParams,
                               FileDescriptorArray& aFileDescriptors,
                               bool aDelayedStart, uint32_t aMaxSize,
                               uint32_t* aSizeUsed, PBackgroundChild* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void StreamWrapper::Serialize(InputStreamParams& aParams,
                               FileDescriptorArray& aFileDescriptors,
                               bool aDelayedStart, uint32_t aMaxSize,
-                              uint32_t* aSizeUsed, ContentParent* aManager) {
+                              uint32_t* aSizeUsed, nsIContentParent* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void StreamWrapper::Serialize(InputStreamParams& aParams,
                               FileDescriptorArray& aFileDescriptors,
                               bool aDelayedStart, uint32_t aMaxSize,
                               uint32_t* aSizeUsed,
new file mode 100644
--- /dev/null
+++ b/dom/ipc/ContentBridgeChild.cpp
@@ -0,0 +1,182 @@
+/* -*- 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/ContentBridgeChild.h"
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/File.h"
+#include "mozilla/dom/TabChild.h"
+#include "mozilla/dom/TabGroup.h"
+#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
+#include "mozilla/ipc/InputStreamUtils.h"
+#include "base/task.h"
+
+using namespace mozilla::ipc;
+using namespace mozilla::jsipc;
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_ISUPPORTS(ContentBridgeChild, nsIContentChild)
+
+ContentBridgeChild::ContentBridgeChild() {}
+
+ContentBridgeChild::~ContentBridgeChild() {}
+
+void ContentBridgeChild::ActorDestroy(ActorDestroyReason aWhy) {
+  MessageLoop::current()->PostTask(
+      NewRunnableMethod("dom::ContentBridgeChild::DeferredDestroy", this,
+                        &ContentBridgeChild::DeferredDestroy));
+}
+
+/*static*/ void ContentBridgeChild::Create(
+    Endpoint<PContentBridgeChild>&& aEndpoint) {
+  RefPtr<ContentBridgeChild> bridge = new ContentBridgeChild();
+  bridge->mSelfRef = bridge;
+
+  DebugOnly<bool> ok = aEndpoint.Bind(bridge);
+  MOZ_ASSERT(ok);
+}
+
+void ContentBridgeChild::DeferredDestroy() {
+  mSelfRef = nullptr;
+  // |this| was just destroyed, hands off
+}
+
+mozilla::ipc::IPCResult ContentBridgeChild::RecvAsyncMessage(
+    const nsString& aMsg, InfallibleTArray<jsipc::CpowEntry>&& aCpows,
+    const IPC::Principal& aPrincipal, const ClonedMessageData& aData) {
+  return nsIContentChild::RecvAsyncMessage(aMsg, std::move(aCpows), aPrincipal,
+                                           aData);
+}
+
+bool ContentBridgeChild::SendPBrowserConstructor(
+    PBrowserChild* aActor, const TabId& aTabId, const TabId& aSameTabGroupAs,
+    const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+    const ContentParentId& aCpID, const bool& aIsForBrowser) {
+  return PContentBridgeChild::SendPBrowserConstructor(
+      aActor, aTabId, aSameTabGroupAs, aContext, aChromeFlags, aCpID,
+      aIsForBrowser);
+}
+
+PFileDescriptorSetChild* ContentBridgeChild::SendPFileDescriptorSetConstructor(
+    const FileDescriptor& aFD) {
+  return PContentBridgeChild::SendPFileDescriptorSetConstructor(aFD);
+}
+
+PChildToParentStreamChild*
+ContentBridgeChild::SendPChildToParentStreamConstructor(
+    PChildToParentStreamChild* aActor) {
+  return PContentBridgeChild::SendPChildToParentStreamConstructor(aActor);
+}
+
+// This implementation is identical to ContentChild::GetCPOWManager but we can't
+// move it to nsIContentChild because it calls ManagedPJavaScriptChild() which
+// only exists in PContentChild and PContentBridgeChild.
+jsipc::CPOWManager* ContentBridgeChild::GetCPOWManager() {
+  if (PJavaScriptChild* c =
+          LoneManagedOrNullAsserts(ManagedPJavaScriptChild())) {
+    return CPOWManagerFor(c);
+  }
+  return CPOWManagerFor(SendPJavaScriptConstructor());
+}
+
+mozilla::jsipc::PJavaScriptChild* ContentBridgeChild::AllocPJavaScriptChild() {
+  return nsIContentChild::AllocPJavaScriptChild();
+}
+
+bool ContentBridgeChild::DeallocPJavaScriptChild(PJavaScriptChild* child) {
+  return nsIContentChild::DeallocPJavaScriptChild(child);
+}
+
+PBrowserChild* ContentBridgeChild::AllocPBrowserChild(
+    const TabId& aTabId, const TabId& aSameTabGroupAs,
+    const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+    const ContentParentId& aCpID, const bool& aIsForBrowser) {
+  return nsIContentChild::AllocPBrowserChild(
+      aTabId, aSameTabGroupAs, aContext, aChromeFlags, aCpID, aIsForBrowser);
+}
+
+bool ContentBridgeChild::DeallocPBrowserChild(PBrowserChild* aChild) {
+  return nsIContentChild::DeallocPBrowserChild(aChild);
+}
+
+mozilla::ipc::IPCResult ContentBridgeChild::RecvPBrowserConstructor(
+    PBrowserChild* aActor, const TabId& aTabId, const TabId& aSameTabGroupAs,
+    const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+    const ContentParentId& aCpID, const bool& aIsForBrowser) {
+  return nsIContentChild::RecvPBrowserConstructor(
+      aActor, aTabId, aSameTabGroupAs, aContext, aChromeFlags, aCpID,
+      aIsForBrowser);
+}
+
+PIPCBlobInputStreamChild* ContentBridgeChild::AllocPIPCBlobInputStreamChild(
+    const nsID& aID, const uint64_t& aSize) {
+  return nsIContentChild::AllocPIPCBlobInputStreamChild(aID, aSize);
+}
+
+bool ContentBridgeChild::DeallocPIPCBlobInputStreamChild(
+    PIPCBlobInputStreamChild* aActor) {
+  return nsIContentChild::DeallocPIPCBlobInputStreamChild(aActor);
+}
+
+PChildToParentStreamChild*
+ContentBridgeChild::AllocPChildToParentStreamChild() {
+  return nsIContentChild::AllocPChildToParentStreamChild();
+}
+
+bool ContentBridgeChild::DeallocPChildToParentStreamChild(
+    PChildToParentStreamChild* aActor) {
+  return nsIContentChild::DeallocPChildToParentStreamChild(aActor);
+}
+
+PParentToChildStreamChild*
+ContentBridgeChild::AllocPParentToChildStreamChild() {
+  return nsIContentChild::AllocPParentToChildStreamChild();
+}
+
+bool ContentBridgeChild::DeallocPParentToChildStreamChild(
+    PParentToChildStreamChild* aActor) {
+  return nsIContentChild::DeallocPParentToChildStreamChild(aActor);
+}
+
+PFileDescriptorSetChild* ContentBridgeChild::AllocPFileDescriptorSetChild(
+    const FileDescriptor& aFD) {
+  return nsIContentChild::AllocPFileDescriptorSetChild(aFD);
+}
+
+bool ContentBridgeChild::DeallocPFileDescriptorSetChild(
+    PFileDescriptorSetChild* aActor) {
+  return nsIContentChild::DeallocPFileDescriptorSetChild(aActor);
+}
+
+mozilla::ipc::IPCResult ContentBridgeChild::RecvActivate(PBrowserChild* aTab) {
+  TabChild* tab = static_cast<TabChild*>(aTab);
+  return tab->RecvActivate();
+}
+
+mozilla::ipc::IPCResult ContentBridgeChild::RecvDeactivate(
+    PBrowserChild* aTab) {
+  TabChild* tab = static_cast<TabChild*>(aTab);
+  return tab->RecvDeactivate();
+}
+
+already_AddRefed<nsIEventTarget> ContentBridgeChild::GetConstructedEventTarget(
+    const Message& aMsg) {
+  // Currently we only set targets for PBrowser.
+  if (aMsg.type() != PContentBridge::Msg_PBrowserConstructor__ID) {
+    return nullptr;
+  }
+
+  return nsIContentChild::GetConstructedEventTarget(aMsg);
+}
+
+already_AddRefed<nsIEventTarget> ContentBridgeChild::GetEventTargetFor(
+    TabChild* aTabChild) {
+  return IToplevelProtocol::GetActorEventTarget(aTabChild);
+}
+
+}  // namespace dom
+}  // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/ipc/ContentBridgeChild.h
@@ -0,0 +1,114 @@
+/* -*- 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_ContentBridgeChild_h
+#define mozilla_dom_ContentBridgeChild_h
+
+#include "mozilla/dom/PContentBridgeChild.h"
+#include "mozilla/dom/nsIContentChild.h"
+
+namespace mozilla {
+namespace dom {
+
+class ContentBridgeChild final : public PContentBridgeChild,
+                                 public nsIContentChild {
+  friend class PContentBridgeChild;
+
+ public:
+  explicit ContentBridgeChild();
+
+  NS_DECL_ISUPPORTS
+
+  static void Create(Endpoint<PContentBridgeChild>&& aEndpoint);
+
+  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+  void DeferredDestroy();
+
+  virtual mozilla::ipc::IPCResult RecvAsyncMessage(
+      const nsString& aMsg, InfallibleTArray<jsipc::CpowEntry>&& aCpows,
+      const IPC::Principal& aPrincipal,
+      const ClonedMessageData& aData) override;
+
+  jsipc::CPOWManager* GetCPOWManager() override;
+
+  virtual bool SendPBrowserConstructor(
+      PBrowserChild* aActor, const TabId& aTabId, const TabId& aSameTabGroupAs,
+      const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+      const ContentParentId& aCpID, const bool& aIsForBrowser) override;
+
+  virtual mozilla::ipc::PFileDescriptorSetChild*
+  SendPFileDescriptorSetConstructor(
+      const mozilla::ipc::FileDescriptor&) override;
+
+  virtual mozilla::ipc::PChildToParentStreamChild*
+  SendPChildToParentStreamConstructor(
+      mozilla::ipc::PChildToParentStreamChild*) override;
+
+  mozilla::ipc::IPCResult RecvActivate(PBrowserChild* aTab);
+
+  mozilla::ipc::IPCResult RecvDeactivate(PBrowserChild* aTab);
+
+  virtual already_AddRefed<nsIEventTarget> GetEventTargetFor(
+      TabChild* aTabChild) override;
+
+  FORWARD_SHMEM_ALLOCATOR_TO(PContentBridgeChild)
+
+ protected:
+  virtual ~ContentBridgeChild();
+
+  virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
+                                            const TabId& aSameTabGroupAs,
+                                            const IPCTabContext& aContext,
+                                            const uint32_t& aChromeFlags,
+                                            const ContentParentId& aCpID,
+                                            const bool& aIsForBrowser) override;
+  virtual bool DeallocPBrowserChild(PBrowserChild*) override;
+  virtual mozilla::ipc::IPCResult RecvPBrowserConstructor(
+      PBrowserChild* aCctor, const TabId& aTabId, const TabId& aSameTabGroupAs,
+      const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+      const ContentParentId& aCpID, const bool& aIsForBrowser) override;
+
+  virtual mozilla::jsipc::PJavaScriptChild* AllocPJavaScriptChild() override;
+  virtual bool DeallocPJavaScriptChild(
+      mozilla::jsipc::PJavaScriptChild*) override;
+
+  virtual PIPCBlobInputStreamChild* AllocPIPCBlobInputStreamChild(
+      const nsID& aID, const uint64_t& aSize) override;
+
+  virtual bool DeallocPIPCBlobInputStreamChild(
+      PIPCBlobInputStreamChild*) override;
+
+  virtual mozilla::ipc::PChildToParentStreamChild*
+  AllocPChildToParentStreamChild() override;
+
+  virtual bool DeallocPChildToParentStreamChild(
+      mozilla::ipc::PChildToParentStreamChild* aActor) override;
+
+  virtual PParentToChildStreamChild* AllocPParentToChildStreamChild() override;
+
+  virtual bool DeallocPParentToChildStreamChild(
+      PParentToChildStreamChild* aActor) override;
+
+  virtual PFileDescriptorSetChild* AllocPFileDescriptorSetChild(
+      const mozilla::ipc::FileDescriptor& aFD) override;
+
+  virtual bool DeallocPFileDescriptorSetChild(
+      mozilla::ipc::PFileDescriptorSetChild* aActor) override;
+
+  DISALLOW_EVIL_CONSTRUCTORS(ContentBridgeChild);
+
+ private:
+  virtual already_AddRefed<nsIEventTarget> GetConstructedEventTarget(
+      const Message& aMsg) override;
+
+ protected:  // members
+  RefPtr<ContentBridgeChild> mSelfRef;
+};
+
+}  // namespace dom
+}  // namespace mozilla
+
+#endif  // mozilla_dom_ContentBridgeChild_h
new file mode 100644
--- /dev/null
+++ b/dom/ipc/ContentBridgeParent.cpp
@@ -0,0 +1,204 @@
+/* -*- 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/ContentBridgeParent.h"
+#include "mozilla/dom/ProcessMessageManager.h"
+#include "mozilla/dom/TabParent.h"
+#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
+#include "nsXULAppAPI.h"
+#include "nsIObserverService.h"
+#include "base/task.h"
+
+using namespace mozilla::ipc;
+using namespace mozilla::jsipc;
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_ISUPPORTS(ContentBridgeParent, nsIContentParent, nsIObserver)
+
+ContentBridgeParent::ContentBridgeParent()
+    : mIsForBrowser(false), mIsForJSPlugin(false) {}
+
+ContentBridgeParent::~ContentBridgeParent() {}
+
+void ContentBridgeParent::ActorDestroy(ActorDestroyReason aWhy) {
+  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+  if (os) {
+    os->RemoveObserver(this, "content-child-shutdown");
+  }
+  MessageLoop::current()->PostTask(
+      NewRunnableMethod("dom::ContentBridgeParent::DeferredDestroy", this,
+                        &ContentBridgeParent::DeferredDestroy));
+}
+
+/*static*/ ContentBridgeParent* ContentBridgeParent::Create(
+    Endpoint<PContentBridgeParent>&& aEndpoint) {
+  RefPtr<ContentBridgeParent> bridge = new ContentBridgeParent();
+  bridge->mSelfRef = bridge;
+
+  DebugOnly<bool> ok = aEndpoint.Bind(bridge);
+  MOZ_ASSERT(ok);
+
+  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+  if (os) {
+    os->AddObserver(bridge, "content-child-shutdown", false);
+  }
+
+  // Initialize the message manager (and load delayed scripts) now that we
+  // have established communications with the child.
+  bridge->mMessageManager->InitWithCallback(bridge);
+
+  return bridge.get();
+}
+
+void ContentBridgeParent::DeferredDestroy() {
+  mSelfRef = nullptr;
+  // |this| was just destroyed, hands off
+}
+
+mozilla::ipc::IPCResult ContentBridgeParent::RecvSyncMessage(
+    const nsString& aMsg, const ClonedMessageData& aData,
+    InfallibleTArray<jsipc::CpowEntry>&& aCpows,
+    const IPC::Principal& aPrincipal, nsTArray<StructuredCloneData>* aRetvals) {
+  return nsIContentParent::RecvSyncMessage(aMsg, aData, std::move(aCpows),
+                                           aPrincipal, aRetvals);
+}
+
+mozilla::ipc::IPCResult ContentBridgeParent::RecvAsyncMessage(
+    const nsString& aMsg, InfallibleTArray<jsipc::CpowEntry>&& aCpows,
+    const IPC::Principal& aPrincipal, const ClonedMessageData& aData) {
+  return nsIContentParent::RecvAsyncMessage(aMsg, std::move(aCpows), aPrincipal,
+                                            aData);
+}
+
+PBrowserParent* ContentBridgeParent::SendPBrowserConstructor(
+    PBrowserParent* aActor, const TabId& aTabId, const TabId& aSameTabGroupAs,
+    const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+    const ContentParentId& aCpID, const bool& aIsForBrowser) {
+  return PContentBridgeParent::SendPBrowserConstructor(
+      aActor, aTabId, aSameTabGroupAs, aContext, aChromeFlags, aCpID,
+      aIsForBrowser);
+}
+
+PParentToChildStreamParent*
+ContentBridgeParent::SendPParentToChildStreamConstructor(
+    PParentToChildStreamParent* aActor) {
+  return PContentBridgeParent::SendPParentToChildStreamConstructor(aActor);
+}
+
+PIPCBlobInputStreamParent*
+ContentBridgeParent::SendPIPCBlobInputStreamConstructor(
+    PIPCBlobInputStreamParent* aActor, const nsID& aID, const uint64_t& aSize) {
+  return PContentBridgeParent::SendPIPCBlobInputStreamConstructor(aActor, aID,
+                                                                  aSize);
+}
+
+PIPCBlobInputStreamParent* ContentBridgeParent::AllocPIPCBlobInputStreamParent(
+    const nsID& aID, const uint64_t& aSize) {
+  return nsIContentParent::AllocPIPCBlobInputStreamParent(aID, aSize);
+}
+
+bool ContentBridgeParent::DeallocPIPCBlobInputStreamParent(
+    PIPCBlobInputStreamParent* aActor) {
+  return nsIContentParent::DeallocPIPCBlobInputStreamParent(aActor);
+}
+
+mozilla::jsipc::PJavaScriptParent*
+ContentBridgeParent::AllocPJavaScriptParent() {
+  return nsIContentParent::AllocPJavaScriptParent();
+}
+
+bool ContentBridgeParent::DeallocPJavaScriptParent(PJavaScriptParent* parent) {
+  return nsIContentParent::DeallocPJavaScriptParent(parent);
+}
+
+PBrowserParent* ContentBridgeParent::AllocPBrowserParent(
+    const TabId& aTabId, const TabId& aSameTabGroupAs,
+    const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+    const ContentParentId& aCpID, const bool& aIsForBrowser) {
+  return nsIContentParent::AllocPBrowserParent(
+      aTabId, aSameTabGroupAs, aContext, aChromeFlags, aCpID, aIsForBrowser);
+}
+
+bool ContentBridgeParent::DeallocPBrowserParent(PBrowserParent* aParent) {
+  return nsIContentParent::DeallocPBrowserParent(aParent);
+}
+
+mozilla::ipc::IPCResult ContentBridgeParent::RecvPBrowserConstructor(
+    PBrowserParent* actor, const TabId& tabId, const TabId& sameTabGroupAs,
+    const IPCTabContext& context, const uint32_t& chromeFlags,
+    const ContentParentId& cpId, const bool& isForBrowser) {
+  return nsIContentParent::RecvPBrowserConstructor(
+      actor, tabId, sameTabGroupAs, context, chromeFlags, cpId, isForBrowser);
+}
+
+void ContentBridgeParent::NotifyTabDestroyed() {
+  int32_t numLiveTabs = ManagedPBrowserParent().Count();
+  if (numLiveTabs == 1) {
+    MessageLoop::current()->PostTask(NewRunnableMethod(
+        "dom::ContentBridgeParent::Close", this, &ContentBridgeParent::Close));
+  }
+}
+
+// This implementation is identical to ContentParent::GetCPOWManager but we
+// can't move it to nsIContentParent because it calls ManagedPJavaScriptParent()
+// which only exists in PContentParent and PContentBridgeParent.
+jsipc::CPOWManager* ContentBridgeParent::GetCPOWManager() {
+  if (PJavaScriptParent* p =
+          LoneManagedOrNullAsserts(ManagedPJavaScriptParent())) {
+    return CPOWManagerFor(p);
+  }
+  return nullptr;
+}
+
+NS_IMETHODIMP
+ContentBridgeParent::Observe(nsISupports* aSubject, const char* aTopic,
+                             const char16_t* aData) {
+  if (!strcmp(aTopic, "content-child-shutdown")) {
+    Close();
+  }
+  return NS_OK;
+}
+
+PFileDescriptorSetParent*
+ContentBridgeParent::SendPFileDescriptorSetConstructor(
+    const FileDescriptor& aFD) {
+  return PContentBridgeParent::SendPFileDescriptorSetConstructor(aFD);
+}
+
+PFileDescriptorSetParent* ContentBridgeParent::AllocPFileDescriptorSetParent(
+    const FileDescriptor& aFD) {
+  return nsIContentParent::AllocPFileDescriptorSetParent(aFD);
+}
+
+bool ContentBridgeParent::DeallocPFileDescriptorSetParent(
+    PFileDescriptorSetParent* aActor) {
+  return nsIContentParent::DeallocPFileDescriptorSetParent(aActor);
+}
+
+PChildToParentStreamParent*
+ContentBridgeParent::AllocPChildToParentStreamParent() {
+  return nsIContentParent::AllocPChildToParentStreamParent();
+}
+
+bool ContentBridgeParent::DeallocPChildToParentStreamParent(
+    PChildToParentStreamParent* aActor) {
+  return nsIContentParent::DeallocPChildToParentStreamParent(aActor);
+}
+
+PParentToChildStreamParent*
+ContentBridgeParent::AllocPParentToChildStreamParent() {
+  return nsIContentParent::AllocPParentToChildStreamParent();
+}
+
+bool ContentBridgeParent::DeallocPParentToChildStreamParent(
+    PParentToChildStreamParent* aActor) {
+  return nsIContentParent::DeallocPParentToChildStreamParent(aActor);
+}
+
+}  // namespace dom
+}  // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/ipc/ContentBridgeParent.h
@@ -0,0 +1,155 @@
+/* -*- 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_ContentBridgeParent_h
+#define mozilla_dom_ContentBridgeParent_h
+
+#include "mozilla/dom/PContentBridgeParent.h"
+#include "mozilla/dom/nsIContentParent.h"
+#include "mozilla/dom/ipc/IdType.h"
+#include "nsIObserver.h"
+
+namespace mozilla {
+namespace dom {
+
+class ContentBridgeParent : public PContentBridgeParent,
+                            public nsIContentParent,
+                            public nsIObserver {
+  friend class PContentBridgeParent;
+
+ public:
+  explicit ContentBridgeParent();
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+
+  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+  void DeferredDestroy();
+  virtual bool IsContentBridgeParent() const override { return true; }
+  void NotifyTabDestroyed();
+
+  static ContentBridgeParent* Create(
+      Endpoint<PContentBridgeParent>&& aEndpoint);
+
+  virtual PBrowserParent* SendPBrowserConstructor(
+      PBrowserParent* aActor, const TabId& aTabId, const TabId& aSameTabGroupAs,
+      const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+      const ContentParentId& aCpID, const bool& aIsForBrowser) override;
+
+  virtual PFileDescriptorSetParent* SendPFileDescriptorSetConstructor(
+      const FileDescriptor&) override;
+
+  FORWARD_SHMEM_ALLOCATOR_TO(PContentBridgeParent)
+
+  jsipc::CPOWManager* GetCPOWManager() override;
+
+  virtual ContentParentId ChildID() const override { return mChildID; }
+  virtual bool IsForBrowser() const override { return mIsForBrowser; }
+  virtual int32_t Pid() const override {
+    // XXX: do we need this for ContentBridgeParent?
+    return -1;
+  }
+  virtual bool IsForJSPlugin() const override { return mIsForJSPlugin; }
+
+  virtual mozilla::ipc::PParentToChildStreamParent*
+  SendPParentToChildStreamConstructor(
+      mozilla::ipc::PParentToChildStreamParent*) override;
+
+  virtual bool SendActivate(PBrowserParent* aTab) override {
+    return PContentBridgeParent::SendActivate(aTab);
+  }
+
+  virtual bool SendDeactivate(PBrowserParent* aTab) override {
+    return PContentBridgeParent::SendDeactivate(aTab);
+  }
+
+ protected:
+  virtual ~ContentBridgeParent();
+
+  void SetChildID(ContentParentId aId) { mChildID = aId; }
+
+  void SetIsForBrowser(bool aIsForBrowser) { mIsForBrowser = aIsForBrowser; }
+  void SetIsForJSPlugin(bool aIsForJSPlugin) {
+    mIsForJSPlugin = aIsForJSPlugin;
+  }
+
+  void Close() {
+    // Trick NewRunnableMethod
+    PContentBridgeParent::Close();
+  }
+
+ protected:
+  virtual mozilla::ipc::IPCResult RecvSyncMessage(
+      const nsString& aMsg, const ClonedMessageData& aData,
+      InfallibleTArray<jsipc::CpowEntry>&& aCpows,
+      const IPC::Principal& aPrincipal,
+      nsTArray<StructuredCloneData>* aRetvals) override;
+
+  virtual mozilla::ipc::IPCResult RecvAsyncMessage(
+      const nsString& aMsg, InfallibleTArray<jsipc::CpowEntry>&& aCpows,
+      const IPC::Principal& aPrincipal,
+      const ClonedMessageData& aData) override;
+
+  virtual jsipc::PJavaScriptParent* AllocPJavaScriptParent() override;
+
+  virtual bool DeallocPJavaScriptParent(jsipc::PJavaScriptParent*) override;
+
+  virtual PBrowserParent* AllocPBrowserParent(
+      const TabId& aTabId, const TabId& aSameTabGroupAs,
+      const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+      const ContentParentId& aCpID, const bool& aIsForBrowser) override;
+
+  virtual bool DeallocPBrowserParent(PBrowserParent*) override;
+
+  virtual mozilla::ipc::IPCResult RecvPBrowserConstructor(
+      PBrowserParent* actor, const TabId& tabId, const TabId& sameTabGroupAs,
+      const IPCTabContext& context, const uint32_t& chromeFlags,
+      const ContentParentId& cpId, const bool& isForBrowser) override;
+
+  virtual PIPCBlobInputStreamParent* SendPIPCBlobInputStreamConstructor(
+      PIPCBlobInputStreamParent* aActor, const nsID& aID,
+      const uint64_t& aSize) override;
+
+  virtual PIPCBlobInputStreamParent* AllocPIPCBlobInputStreamParent(
+      const nsID& aID, const uint64_t& aSize) override;
+
+  virtual bool DeallocPIPCBlobInputStreamParent(
+      PIPCBlobInputStreamParent*) override;
+
+  virtual PChildToParentStreamParent* AllocPChildToParentStreamParent()
+      override;
+
+  virtual bool DeallocPChildToParentStreamParent(
+      PChildToParentStreamParent* aActor) override;
+
+  virtual mozilla::ipc::PParentToChildStreamParent*
+  AllocPParentToChildStreamParent() override;
+
+  virtual bool DeallocPParentToChildStreamParent(
+      mozilla::ipc::PParentToChildStreamParent* aActor) override;
+
+  virtual PFileDescriptorSetParent* AllocPFileDescriptorSetParent(
+      const mozilla::ipc::FileDescriptor&) override;
+
+  virtual bool DeallocPFileDescriptorSetParent(
+      PFileDescriptorSetParent*) override;
+
+  DISALLOW_EVIL_CONSTRUCTORS(ContentBridgeParent);
+
+ protected:  // members
+  RefPtr<ContentBridgeParent> mSelfRef;
+  ContentParentId mChildID;
+  bool mIsForBrowser;
+  bool mIsForJSPlugin;
+
+ private:
+  friend class ContentParent;
+};
+
+}  // namespace dom
+}  // namespace mozilla
+
+#endif  // mozilla_dom_ContentBridgeParent_h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -26,16 +26,18 @@
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/TelemetryIPC.h"
 #include "mozilla/VideoDecoderManagerChild.h"
 #include "mozilla/devtools/HeapSnapshotTempFileHelperChild.h"
 #include "mozilla/docshell/OfflineCacheUpdateChild.h"
 #include "mozilla/dom/ClientManager.h"
 #include "mozilla/dom/ClientOpenWindowOpActors.h"
 #include "mozilla/dom/ChildProcessMessageManager.h"
+#include "mozilla/dom/ContentBridgeChild.h"
+#include "mozilla/dom/ContentBridgeParent.h"
 #include "mozilla/dom/ContentProcessMessageManager.h"
 #include "mozilla/dom/DOMPrefs.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/ExternalHelperAppChild.h"
 #include "mozilla/dom/FileCreatorHelper.h"
 #include "mozilla/dom/GetFilesHelper.h"
@@ -45,32 +47,31 @@
 #include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/dom/PLoginReputationChild.h"
 #include "mozilla/dom/PSessionStorageObserverChild.h"
 #include "mozilla/dom/PostMessageEvent.h"
 #include "mozilla/dom/PushNotifier.h"
 #include "mozilla/dom/RemoteWorkerService.h"
 #include "mozilla/dom/ServiceWorkerManager.h"
 #include "mozilla/dom/TabGroup.h"
+#include "mozilla/dom/nsIContentChild.h"
 #include "mozilla/dom/URLClassifierChild.h"
 #include "mozilla/dom/WorkerDebugger.h"
 #include "mozilla/dom/WorkerDebuggerManager.h"
-#include "mozilla/dom/ipc/IPCBlobInputStreamChild.h"
 #include "mozilla/dom/ipc/SharedMap.h"
 #include "mozilla/gfx/gfxVars.h"
 #include "mozilla/gfx/Logging.h"
 #include "mozilla/psm/PSMContentListener.h"
 #include "mozilla/hal_sandbox/PHalChild.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/FileDescriptorSetChild.h"
 #include "mozilla/ipc/FileDescriptorUtils.h"
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "mozilla/ipc/ProcessChild.h"
 #include "mozilla/ipc/PChildToParentStreamChild.h"
-#include "mozilla/ipc/PParentToChildStreamChild.h"
 #include "mozilla/intl/LocaleService.h"
 #include "mozilla/ipc/TestShellChild.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/jsipc/PJavaScript.h"
 #include "mozilla/layers/APZChild.h"
 #include "mozilla/layers/CompositorManagerChild.h"
 #include "mozilla/layers/ContentProcessController.h"
 #include "mozilla/layers/ImageBridgeChild.h"
@@ -222,19 +223,16 @@
 #    include "mozilla/a11y/AccessibleWrap.h"
 #  endif
 #endif
 
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/PPresentationChild.h"
 #include "mozilla/dom/PresentationIPCService.h"
 #include "mozilla/ipc/InputStreamUtils.h"
-#include "mozilla/ipc/IPCStreamAlloc.h"
-#include "mozilla/ipc/IPCStreamDestination.h"
-#include "mozilla/ipc/IPCStreamSource.h"
 
 #ifdef MOZ_WEBSPEECH
 #  include "mozilla/dom/PSpeechSynthesisChild.h"
 #endif
 
 #include "ClearOnShutdown.h"
 #include "ProcessUtils.h"
 #include "URIUtils.h"
@@ -577,18 +575,19 @@ ContentChild::~ContentChild() {
 #endif
 }
 
 #ifdef _MSC_VER
 #  pragma warning(pop)
 #endif
 
 NS_INTERFACE_MAP_BEGIN(ContentChild)
+  NS_INTERFACE_MAP_ENTRY(nsIContentChild)
   NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentChild)
 NS_INTERFACE_MAP_END
 
 mozilla::ipc::IPCResult ContentChild::RecvSetXPCOMProcessAttributes(
     const XPCOMInitData& aXPCOMInit, const StructuredCloneData& aInitialData,
     nsTArray<LookAndFeelInt>&& aLookAndFeelIntCache,
     nsTArray<SystemFontListEntry>&& aFontList) {
   if (!sShutdownCanary) {
     return IPC_OK();
@@ -1312,16 +1311,22 @@ mozilla::ipc::IPCResult ContentChild::Re
 
 bool ContentChild::DeallocPCycleCollectWithLogsChild(
     PCycleCollectWithLogsChild* aActor) {
   RefPtr<CycleCollectWithLogsChild> actor =
       dont_AddRef(static_cast<CycleCollectWithLogsChild*>(aActor));
   return true;
 }
 
+mozilla::ipc::IPCResult ContentChild::RecvInitContentBridgeChild(
+    Endpoint<PContentBridgeChild>&& aEndpoint) {
+  ContentBridgeChild::Create(std::move(aEndpoint));
+  return IPC_OK();
+}
+
 mozilla::ipc::IPCResult ContentChild::RecvInitGMPService(
     Endpoint<PGMPServiceChild>&& aGMPService) {
   if (!GMPServiceChild::Create(std::move(aGMPService))) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
@@ -1682,49 +1687,31 @@ static void FirstIdle(void) {
   if (!recordreplay::IsRecordingOrReplaying()) {
     ContentChild::GetSingleton()->SendFirstIdle();
   }
 }
 
 mozilla::jsipc::PJavaScriptChild* ContentChild::AllocPJavaScriptChild() {
   MOZ_ASSERT(ManagedPJavaScriptChild().IsEmpty());
 
-  return NewJavaScriptChild();
+  return nsIContentChild::AllocPJavaScriptChild();
 }
 
 bool ContentChild::DeallocPJavaScriptChild(PJavaScriptChild* aChild) {
-  ReleaseJavaScriptChild(aChild);
-  return true;
+  return nsIContentChild::DeallocPJavaScriptChild(aChild);
 }
 
 PBrowserChild* ContentChild::AllocPBrowserChild(const TabId& aTabId,
                                                 const TabId& aSameTabGroupAs,
                                                 const IPCTabContext& aContext,
                                                 const uint32_t& aChromeFlags,
                                                 const ContentParentId& aCpID,
                                                 const bool& aIsForBrowser) {
-  // We'll happily accept any kind of IPCTabContext here; we don't need to
-  // check that it's of a certain type for security purposes, because we
-  // believe whatever the parent process tells us.
-
-  MaybeInvalidTabContext tc(aContext);
-  if (!tc.IsValid()) {
-    NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
-                             "the parent process. (%s)  Crashing...",
-                             tc.GetInvalidReason())
-                 .get());
-    MOZ_CRASH("Invalid TabContext received from the parent process.");
-  }
-
-  RefPtr<TabChild> child =
-      TabChild::Create(static_cast<ContentChild*>(this), aTabId,
-                       aSameTabGroupAs, tc.GetTabContext(), aChromeFlags);
-
-  // The ref here is released in DeallocPBrowserChild.
-  return child.forget().take();
+  return nsIContentChild::AllocPBrowserChild(
+      aTabId, aSameTabGroupAs, aContext, aChromeFlags, aCpID, aIsForBrowser);
 }
 
 bool ContentChild::SendPBrowserConstructor(
     PBrowserChild* aActor, const TabId& aTabId, const TabId& aSameTabGroupAs,
     const IPCTabContext& aContext, const uint32_t& aChromeFlags,
     const ContentParentId& aCpID, const bool& aIsForBrowser) {
   if (IsShuttingDown()) {
     return false;
@@ -1750,30 +1737,19 @@ mozilla::ipc::IPCResult ContentChild::Re
     gFirstIdleTask = firstIdleTask;
     if (NS_FAILED(NS_DispatchToCurrentThreadQueue(firstIdleTask.forget(),
                                                   EventQueuePriority::Idle))) {
       gFirstIdleTask = nullptr;
       hasRunOnce = false;
     }
   }
 
-  auto tabChild = static_cast<TabChild*>(aActor);
-
-  if (NS_WARN_IF(NS_FAILED(tabChild->Init(/* aOpener */ nullptr)))) {
-    return IPC_FAIL(tabChild, "TabChild::Init failed");
-  }
-
-  nsCOMPtr<nsIObserverService> os = services::GetObserverService();
-  if (os) {
-    os->NotifyObservers(static_cast<nsITabChild*>(tabChild),
-                        "tab-child-created", nullptr);
-  }
-  // Notify parent that we are ready to handle input events.
-  tabChild->SendRemoteIsReadyToHandleInputEvents();
-  return IPC_OK();
+  return nsIContentChild::RecvPBrowserConstructor(
+      aActor, aTabId, aSameTabGroupAs, aContext, aChromeFlags, aCpID,
+      aIsForBrowser);
 }
 
 void ContentChild::GetAvailableDictionaries(
     InfallibleTArray<nsString>& aDictionaries) {
   aDictionaries = mAvailableDictionaries;
 }
 
 PFileDescriptorSetChild* ContentChild::SendPFileDescriptorSetConstructor(
@@ -1782,46 +1758,36 @@ PFileDescriptorSetChild* ContentChild::S
     return nullptr;
   }
 
   return PContentChild::SendPFileDescriptorSetConstructor(aFD);
 }
 
 PFileDescriptorSetChild* ContentChild::AllocPFileDescriptorSetChild(
     const FileDescriptor& aFD) {
-  return new FileDescriptorSetChild(aFD);
+  return nsIContentChild::AllocPFileDescriptorSetChild(aFD);
 }
 
 bool ContentChild::DeallocPFileDescriptorSetChild(
     PFileDescriptorSetChild* aActor) {
-  delete static_cast<FileDescriptorSetChild*>(aActor);
-  return true;
+  return nsIContentChild::DeallocPFileDescriptorSetChild(aActor);
 }
 
 bool ContentChild::DeallocPBrowserChild(PBrowserChild* aIframe) {
-  TabChild* child = static_cast<TabChild*>(aIframe);
-  NS_RELEASE(child);
-  return true;
+  return nsIContentChild::DeallocPBrowserChild(aIframe);
 }
 
 PIPCBlobInputStreamChild* ContentChild::AllocPIPCBlobInputStreamChild(
     const nsID& aID, const uint64_t& aSize) {
-  // IPCBlobInputStreamChild is refcounted. Here it's created and in
-  // DeallocPIPCBlobInputStreamChild is released.
-
-  RefPtr<IPCBlobInputStreamChild> actor =
-      new IPCBlobInputStreamChild(aID, aSize);
-  return actor.forget().take();
+  return nsIContentChild::AllocPIPCBlobInputStreamChild(aID, aSize);
 }
 
 bool ContentChild::DeallocPIPCBlobInputStreamChild(
     PIPCBlobInputStreamChild* aActor) {
-  RefPtr<IPCBlobInputStreamChild> actor =
-      dont_AddRef(static_cast<IPCBlobInputStreamChild*>(aActor));
-  return true;
+  return nsIContentChild::DeallocPIPCBlobInputStreamChild(aActor);
 }
 
 mozilla::PRemoteSpellcheckEngineChild*
 ContentChild::AllocPRemoteSpellcheckEngineChild() {
   MOZ_CRASH(
       "Default Constructor for PRemoteSpellcheckEngineChild should never be "
       "called");
   return nullptr;
@@ -1976,33 +1942,31 @@ PChildToParentStreamChild* ContentChild:
   if (IsShuttingDown()) {
     return nullptr;
   }
 
   return PContentChild::SendPChildToParentStreamConstructor(aActor);
 }
 
 PChildToParentStreamChild* ContentChild::AllocPChildToParentStreamChild() {
-  MOZ_CRASH("PChildToParentStreamChild actors should be manually constructed!");
+  return nsIContentChild::AllocPChildToParentStreamChild();
 }
 
 bool ContentChild::DeallocPChildToParentStreamChild(
     PChildToParentStreamChild* aActor) {
-  delete aActor;
-  return true;
+  return nsIContentChild::DeallocPChildToParentStreamChild(aActor);
 }
 
 PParentToChildStreamChild* ContentChild::AllocPParentToChildStreamChild() {
-  return mozilla::ipc::AllocPParentToChildStreamChild();
+  return nsIContentChild::AllocPParentToChildStreamChild();
 }
 
 bool ContentChild::DeallocPParentToChildStreamChild(
     PParentToChildStreamChild* aActor) {
-  delete aActor;
-  return true;
+  return nsIContentChild::DeallocPParentToChildStreamChild(aActor);
 }
 
 PPSMContentDownloaderChild* ContentChild::AllocPPSMContentDownloaderChild(
     const uint32_t& aCertType) {
   // NB: We don't need aCertType in the child actor.
   RefPtr<PSMContentDownloaderChild> child = new PSMContentDownloaderChild();
   return child.forget().take();
 }
@@ -2829,17 +2793,18 @@ void ContentChild::StartForceKillTimer()
 /* static */ void ContentChild::ForceKillTimerCallback(nsITimer* aTimer,
                                                        void* aClosure) {
   ProcessChild::QuickExit();
 }
 
 mozilla::ipc::IPCResult ContentChild::RecvShutdown() {
   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   if (os) {
-    os->NotifyObservers(this, "content-child-will-shutdown", nullptr);
+    os->NotifyObservers(static_cast<nsIContentChild*>(this),
+                        "content-child-will-shutdown", nullptr);
   }
 
   ShutdownInternal();
   return IPC_OK();
 }
 
 void ContentChild::ShutdownInternal() {
   // If we receive the shutdown message from within a nested event loop, we want
@@ -2876,17 +2841,18 @@ void ContentChild::ShutdownInternal() {
 
   if (mPolicy) {
     mPolicy->Deactivate();
     mPolicy = nullptr;
   }
 
   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   if (os) {
-    os->NotifyObservers(this, "content-child-shutdown", nullptr);
+    os->NotifyObservers(static_cast<nsIContentChild*>(this),
+                        "content-child-shutdown", nullptr);
   }
 
 #if defined(XP_WIN)
   mozilla::widget::StopAudioSession();
 #endif
 
   GetIPCChannel()->SetAbortOnError(false);
 
@@ -3319,48 +3285,17 @@ bool ContentChild::DeallocPSessionStorag
 // actors created by the ContentParent.
 already_AddRefed<nsIEventTarget> ContentChild::GetConstructedEventTarget(
     const Message& aMsg) {
   // Currently we only set targets for PBrowser.
   if (aMsg.type() != PContent::Msg_PBrowserConstructor__ID) {
     return nullptr;
   }
 
-  ActorHandle handle;
-  TabId tabId, sameTabGroupAs;
-  PickleIterator iter(aMsg);
-  if (!IPC::ReadParam(&aMsg, &iter, &handle)) {
-    return nullptr;
-  }
-  aMsg.IgnoreSentinel(&iter);
-  if (!IPC::ReadParam(&aMsg, &iter, &tabId)) {
-    return nullptr;
-  }
-  aMsg.IgnoreSentinel(&iter);
-  if (!IPC::ReadParam(&aMsg, &iter, &sameTabGroupAs)) {
-    return nullptr;
-  }
-
-  // If sameTabGroupAs is non-zero, then the new tab will be in the same
-  // TabGroup as a previously created tab. Rather than try to find the
-  // previously created tab (whose constructor message may not even have been
-  // processed yet, in theory) and look up its event target, we just use the
-  // default event target. This means that runnables for this tab will not be
-  // labeled. However, this path is only taken for print preview and view
-  // source, which are not performance-sensitive.
-  if (sameTabGroupAs) {
-    return nullptr;
-  }
-
-  // If the request for a new TabChild is coming from the parent process, then
-  // there is no opener. Therefore, we create a fresh TabGroup.
-  RefPtr<TabGroup> tabGroup = new TabGroup();
-  nsCOMPtr<nsIEventTarget> target =
-      tabGroup->EventTargetFor(TaskCategory::Other);
-  return target.forget();
+  return nsIContentChild::GetConstructedEventTarget(aMsg);
 }
 
 void ContentChild::FileCreationRequest(nsID& aUUID, FileCreatorHelper* aHelper,
                                        const nsAString& aFullPath,
                                        const nsAString& aType,
                                        const nsAString& aName,
                                        const Optional<int64_t>& aLastModified,
                                        bool aExistenceCheck,
@@ -3911,9 +3846,9 @@ nsresult GetRepoDir(nsIFile** aRepoDir) 
 }
 
 nsresult GetObjDir(nsIFile** aObjDir) {
   MOZ_ASSERT(IsDevelopmentBuild());
   return GetDirFromBundlePlist(NS_LITERAL_STRING(MAC_DEV_OBJ_KEY), aObjDir);
 }
 #endif /* XP_MACOSX */
 
-}  // namespace mozilla
\ No newline at end of file
+}  // namespace mozilla
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -4,28 +4,25 @@
  * 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_ContentChild_h
 #define mozilla_dom_ContentChild_h
 
 #include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/dom/ContentBridgeParent.h"
+#include "mozilla/dom/nsIContentChild.h"
 #include "mozilla/dom/PBrowserOrId.h"
 #include "mozilla/dom/PContentChild.h"
-#include "mozilla/dom/CPOWManagerGetter.h"
 #include "mozilla/StaticPtr.h"
-#include "mozilla/ipc/Shmem.h"
-#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "nsAutoPtr.h"
 #include "nsHashKeys.h"
 #include "nsIObserver.h"
 #include "nsTHashtable.h"
-#include "nsStringFwd.h"
-#include "nsTArrayForwardDeclare.h"
 #include "nsRefPtrHashtable.h"
 
 #include "nsIWindowProvider.h"
 
 #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
 #  include "nsIFile.h"
 #endif
 
@@ -76,18 +73,17 @@ class AlertObserver;
 class ConsoleListener;
 class ClonedMessageData;
 class TabChild;
 class GetFilesHelperChild;
 class FileCreatorHelper;
 
 class ContentChild final : public PContentChild,
                            public nsIWindowProvider,
-                           public CPOWManagerGetter,
-                           public mozilla::ipc::IShmemAllocator {
+                           public nsIContentChild {
   typedef mozilla::dom::ClonedMessageData ClonedMessageData;
   typedef mozilla::ipc::FileDescriptor FileDescriptor;
   typedef mozilla::ipc::OptionalURIParams OptionalURIParams;
   typedef mozilla::ipc::PFileDescriptorSetChild PFileDescriptorSetChild;
   typedef mozilla::ipc::URIParams URIParams;
 
   friend class PContentChild;
 
@@ -155,16 +151,19 @@ class ContentChild final : public PConte
   bool IsShuttingDown() const;
 
   ipc::SharedMap* SharedData() { return mSharedData; };
 
   static void AppendProcessId(nsACString& aName);
 
   static void UpdateCookieStatus(nsIChannel* aChannel);
 
+  mozilla::ipc::IPCResult RecvInitContentBridgeChild(
+      Endpoint<PContentBridgeChild>&& aEndpoint);
+
   mozilla::ipc::IPCResult RecvInitGMPService(
       Endpoint<PGMPServiceChild>&& aGMPService);
 
   mozilla::ipc::IPCResult RecvInitProfiler(
       Endpoint<PProfilerChild>&& aEndpoint);
 
   mozilla::ipc::IPCResult RecvGMPsChanged(
       nsTArray<GMPCapabilityData>&& capabilities);
@@ -190,29 +189,30 @@ class ContentChild final : public PConte
 
   virtual mozilla::ipc::IPCResult RecvAudioDefaultDeviceChange();
 
   mozilla::ipc::IPCResult RecvReinitRenderingForDeviceReset();
 
   virtual mozilla::ipc::IPCResult RecvSetProcessSandbox(
       const MaybeFileDesc& aBroker);
 
-  PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
-                                    const TabId& aSameTabGroupAs,
-                                    const IPCTabContext& aContext,
-                                    const uint32_t& aChromeFlags,
-                                    const ContentParentId& aCpID,
-                                    const bool& aIsForBrowser);
+  virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
+                                            const TabId& aSameTabGroupAs,
+                                            const IPCTabContext& aContext,
+                                            const uint32_t& aChromeFlags,
+                                            const ContentParentId& aCpID,
+                                            const bool& aIsForBrowser) override;
 
-  bool DeallocPBrowserChild(PBrowserChild*);
+  virtual bool DeallocPBrowserChild(PBrowserChild*) override;
 
-  PIPCBlobInputStreamChild* AllocPIPCBlobInputStreamChild(
-      const nsID& aID, const uint64_t& aSize);
+  virtual PIPCBlobInputStreamChild* AllocPIPCBlobInputStreamChild(
+      const nsID& aID, const uint64_t& aSize) override;
 
-  bool DeallocPIPCBlobInputStreamChild(PIPCBlobInputStreamChild* aActor);
+  virtual bool DeallocPIPCBlobInputStreamChild(
+      PIPCBlobInputStreamChild* aActor) override;
 
   PHalChild* AllocPHalChild();
   bool DeallocPHalChild(PHalChild*);
 
   PHeapSnapshotTempFileHelperChild* AllocPHeapSnapshotTempFileHelperChild();
 
   bool DeallocPHeapSnapshotTempFileHelperChild(
       PHeapSnapshotTempFileHelperChild*);
@@ -258,24 +258,26 @@ class ContentChild final : public PConte
   PNeckoChild* AllocPNeckoChild();
 
   bool DeallocPNeckoChild(PNeckoChild*);
 
   PPrintingChild* AllocPPrintingChild();
 
   bool DeallocPPrintingChild(PPrintingChild*);
 
-  PChildToParentStreamChild* SendPChildToParentStreamConstructor(
-      PChildToParentStreamChild*);
+  virtual PChildToParentStreamChild* SendPChildToParentStreamConstructor(
+      PChildToParentStreamChild*) override;
 
-  PChildToParentStreamChild* AllocPChildToParentStreamChild();
-  bool DeallocPChildToParentStreamChild(PChildToParentStreamChild*);
+  virtual PChildToParentStreamChild* AllocPChildToParentStreamChild() override;
+  virtual bool DeallocPChildToParentStreamChild(
+      PChildToParentStreamChild*) override;
 
-  PParentToChildStreamChild* AllocPParentToChildStreamChild();
-  bool DeallocPParentToChildStreamChild(PParentToChildStreamChild*);
+  virtual PParentToChildStreamChild* AllocPParentToChildStreamChild() override;
+  virtual bool DeallocPParentToChildStreamChild(
+      PParentToChildStreamChild*) override;
 
   PPSMContentDownloaderChild* AllocPPSMContentDownloaderChild(
       const uint32_t& aCertType);
 
   bool DeallocPPSMContentDownloaderChild(
       PPSMContentDownloaderChild* aDownloader);
 
   PExternalHelperAppChild* AllocPExternalHelperAppChild(
@@ -319,19 +321,20 @@ class ContentChild final : public PConte
       InfallibleTArray<OverrideMapping>&& overrides, const nsCString& locale,
       const bool& reset);
   mozilla::ipc::IPCResult RecvRegisterChromeItem(
       const ChromeRegistryItem& item);
 
   mozilla::ipc::IPCResult RecvClearImageCache(const bool& privateLoader,
                                               const bool& chrome);
 
-  mozilla::jsipc::PJavaScriptChild* AllocPJavaScriptChild();
+  virtual mozilla::jsipc::PJavaScriptChild* AllocPJavaScriptChild() override;
 
-  bool DeallocPJavaScriptChild(mozilla::jsipc::PJavaScriptChild*);
+  virtual bool DeallocPJavaScriptChild(
+      mozilla::jsipc::PJavaScriptChild*) override;
 
   PRemoteSpellcheckEngineChild* AllocPRemoteSpellcheckEngineChild();
 
   bool DeallocPRemoteSpellcheckEngineChild(PRemoteSpellcheckEngineChild*);
 
   mozilla::ipc::IPCResult RecvSetOffline(const bool& offline);
 
   mozilla::ipc::IPCResult RecvSetConnectivity(const bool& connectivity);
@@ -358,20 +361,20 @@ class ContentChild final : public PConte
 
   mozilla::ipc::IPCResult RecvDataStorageClear(const nsString& aFilename);
 
   mozilla::ipc::IPCResult RecvNotifyAlertsObserver(const nsCString& aType,
                                                    const nsString& aData);
 
   virtual mozilla::ipc::IPCResult RecvLoadProcessScript(const nsString& aURL);
 
-  mozilla::ipc::IPCResult RecvAsyncMessage(const nsString& aMsg,
-                                           InfallibleTArray<CpowEntry>&& aCpows,
-                                           const IPC::Principal& aPrincipal,
-                                           const ClonedMessageData& aData);
+  virtual mozilla::ipc::IPCResult RecvAsyncMessage(
+      const nsString& aMsg, InfallibleTArray<CpowEntry>&& aCpows,
+      const IPC::Principal& aPrincipal,
+      const ClonedMessageData& aData) override;
 
   mozilla::ipc::IPCResult RecvRegisterStringBundles(
       nsTArray<StringBundleDescriptor>&& stringBundles);
 
   mozilla::ipc::IPCResult RecvUpdateSharedData(
       const FileDescriptor& aMapFile, const uint32_t& aMapSize,
       nsTArray<IPCBlob>&& aBlobs, nsTArray<nsCString>&& aChangedKeys);
 
@@ -500,29 +503,29 @@ class ContentChild final : public PConte
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
   uint32_t GetChromeMainThreadId() const { return mMainChromeTid; }
 
   uint32_t GetMsaaID() const { return mMsaaID; }
 #endif
 
   bool IsForBrowser() const { return mIsForBrowser; }
 
-  PFileDescriptorSetChild* SendPFileDescriptorSetConstructor(
-      const FileDescriptor&);
+  virtual PFileDescriptorSetChild* SendPFileDescriptorSetConstructor(
+      const FileDescriptor&) override;
 
-  PFileDescriptorSetChild* AllocPFileDescriptorSetChild(const FileDescriptor&);
-
-  bool DeallocPFileDescriptorSetChild(PFileDescriptorSetChild*);
+  virtual PFileDescriptorSetChild* AllocPFileDescriptorSetChild(
+      const FileDescriptor&) override;
 
-  bool SendPBrowserConstructor(PBrowserChild* actor, const TabId& aTabId,
-                               const TabId& aSameTabGroupAs,
-                               const IPCTabContext& context,
-                               const uint32_t& chromeFlags,
-                               const ContentParentId& aCpID,
-                               const bool& aIsForBrowser);
+  virtual bool DeallocPFileDescriptorSetChild(
+      PFileDescriptorSetChild*) override;
+
+  virtual bool SendPBrowserConstructor(
+      PBrowserChild* actor, const TabId& aTabId, const TabId& aSameTabGroupAs,
+      const IPCTabContext& context, const uint32_t& chromeFlags,
+      const ContentParentId& aCpID, const bool& aIsForBrowser) override;
 
   virtual mozilla::ipc::IPCResult RecvPBrowserConstructor(
       PBrowserChild* aCctor, const TabId& aTabId, const TabId& aSameTabGroupAs,
       const IPCTabContext& aContext, const uint32_t& aChromeFlags,
       const ContentParentId& aCpID, const bool& aIsForBrowser) override;
 
   FORWARD_SHMEM_ALLOCATOR_TO(PContentChild)
 
@@ -656,17 +659,18 @@ class ContentChild final : public PConte
                            const nsAString& aName,
                            const Optional<int64_t>& aLastModified,
                            bool aExistenceCheck, bool aIsFromNsIFile);
 
   typedef std::function<void(PRFileDesc*)> AnonymousTemporaryFileCallback;
   nsresult AsyncOpenAnonymousTemporaryFile(
       const AnonymousTemporaryFileCallback& aCallback);
 
-  already_AddRefed<nsIEventTarget> GetEventTargetFor(TabChild* aTabChild);
+  virtual already_AddRefed<nsIEventTarget> GetEventTargetFor(
+      TabChild* aTabChild) override;
 
   mozilla::ipc::IPCResult RecvSetPluginList(
       const uint32_t& aPluginEpoch, nsTArray<PluginTag>&& aPluginTags,
       nsTArray<FakePluginTag>&& aFakePluginTags);
 
   PClientOpenWindowOpChild* AllocPClientOpenWindowOpChild(
       const ClientOpenWindowArgs& aArgs);
 
@@ -817,9 +821,9 @@ class ContentChild final : public PConte
   DISALLOW_EVIL_CONSTRUCTORS(ContentChild);
 };
 
 uint64_t NextWindowID();
 
 }  // namespace dom
 }  // namespace mozilla
 
-#endif  // mozilla_dom_ContentChild_h
\ No newline at end of file
+#endif  // mozilla_dom_ContentChild_h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -38,60 +38,55 @@
 #include "mozilla/DataStorage.h"
 #include "mozilla/devtools/HeapSnapshotTempFileHelperParent.h"
 #include "mozilla/docshell/OfflineCacheUpdateParent.h"
 #include "mozilla/dom/BrowsingContext.h"
 #include "mozilla/dom/BrowsingContextGroup.h"
 #include "mozilla/dom/CanonicalBrowsingContext.h"
 #include "mozilla/dom/ClientManager.h"
 #include "mozilla/dom/ClientOpenWindowOpActors.h"
-#include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/FileCreatorHelper.h"
 #include "mozilla/dom/FileSystemSecurity.h"
 #include "mozilla/dom/IPCBlobUtils.h"
 #include "mozilla/dom/ExternalHelperAppParent.h"
 #include "mozilla/dom/GetFilesHelper.h"
 #include "mozilla/dom/GeolocationBinding.h"
 #include "mozilla/dom/JSWindowActorService.h"
 #include "mozilla/dom/LocalStorageCommon.h"
 #include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/dom/Notification.h"
+#include "mozilla/dom/PContentBridgeParent.h"
 #include "mozilla/dom/PContentPermissionRequestParent.h"
 #include "mozilla/dom/PCycleCollectWithLogsParent.h"
 #include "mozilla/dom/PositionError.h"
 #include "mozilla/dom/ServiceWorkerRegistrar.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/Permissions.h"
 #include "mozilla/dom/PresentationParent.h"
 #include "mozilla/dom/PPresentationParent.h"
 #include "mozilla/dom/PushNotifier.h"
 #include "mozilla/dom/quota/QuotaManagerService.h"
 #include "mozilla/dom/ServiceWorkerUtils.h"
 #include "mozilla/dom/URLClassifierParent.h"
-#include "mozilla/dom/ipc/IPCBlobInputStreamParent.h"
 #include "mozilla/dom/ipc/SharedMap.h"
 #include "mozilla/embedding/printingui/PrintingParent.h"
 #include "mozilla/extensions/StreamFilterParent.h"
 #include "mozilla/gfx/gfxVars.h"
 #include "mozilla/gfx/GPUProcessManager.h"
 #include "mozilla/hal_sandbox/PHalParent.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ipc/CrashReporterHost.h"
-#include "mozilla/ipc/FileDescriptorSetParent.h"
 #include "mozilla/ipc/FileDescriptorUtils.h"
 #include "mozilla/ipc/PChildToParentStreamParent.h"
 #include "mozilla/ipc/TestShellParent.h"
 #include "mozilla/ipc/IPCStreamUtils.h"
-#include "mozilla/ipc/IPCStreamAlloc.h"
-#include "mozilla/ipc/IPCStreamDestination.h"
-#include "mozilla/ipc/IPCStreamSource.h"
 #include "mozilla/intl/LocaleService.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/layers/PAPZParent.h"
 #include "mozilla/layers/CompositorThread.h"
 #include "mozilla/layers/ImageBridgeParent.h"
 #include "mozilla/layers/LayerTreeOwnerTracker.h"
 #include "mozilla/loader/ScriptCacheActors.h"
 #include "mozilla/LoginReputationIPC.h"
@@ -214,17 +209,16 @@
 #include "nsPluginTags.h"
 #include "nsIBlocklistService.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
 #include "nsICaptivePortalService.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsIBidiKeyboard.h"
 #include "nsLayoutStylesheetCache.h"
-#include "MMPrinter.h"
 
 #include "mozilla/Sprintf.h"
 
 #ifdef MOZ_WEBRTC
 #  include "signaling/src/peerconnection/WebrtcGlobalParent.h"
 #endif
 
 #if defined(XP_MACOSX)
@@ -290,25 +284,16 @@
 
 #ifdef MOZ_CODE_COVERAGE
 #  include "mozilla/CodeCoverageHandler.h"
 #endif
 
 // For VP9Benchmark::sBenchmarkFpsPref
 #include "Benchmark.h"
 
-// XXX need another bug to move this to a common header.
-#ifdef DISABLE_ASSERTS_FOR_FUZZING
-#  define ASSERT_UNLESS_FUZZING(...) \
-    do {                             \
-    } while (0)
-#else
-#  define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false, __VA_ARGS__)
-#endif
-
 static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
 
 using base::KillProcess;
 
 using namespace CrashReporter;
 using namespace mozilla::dom::power;
 using namespace mozilla::media;
 using namespace mozilla::embedding;
@@ -446,17 +431,17 @@ ContentParentsMemoryReporter::CollectRep
       }
       numQueuedMessages = channel->Unsound_NumQueuedMessages();
     }
 
     nsPrintfCString path(
         "queued-ipc-messages/content-parent"
         "(%s, pid=%d, %s, 0x%p, refcnt=%" PRIuPTR ")",
         NS_ConvertUTF16toUTF8(friendlyName).get(), cp->Pid(), channelStr,
-        static_cast<nsIObserver*>(cp), refcnt);
+        static_cast<nsIContentParent*>(cp), refcnt);
 
     NS_NAMED_LITERAL_CSTRING(
         desc,
         "The number of unset IPC messages held in this ContentParent's "
         "channel.  A large value here might indicate that we're leaking "
         "messages.  Similarly, a ContentParent object for a process that's no "
         "longer running could indicate that we're leaking ContentParents.");
 
@@ -960,16 +945,105 @@ extern const wchar_t* kPluginWidgetConte
   ContentParent* cp = reinterpret_cast<ContentParent*>(
       ::GetPropW(hwnd, kPluginWidgetContentParentProperty));
   if (cp && !cp->IsDestroyed()) {
     Unused << cp->SendUpdateWindow((uintptr_t)hwnd);
   }
 }
 #endif  // defined(XP_WIN)
 
+mozilla::ipc::IPCResult ContentParent::RecvCreateChildProcess(
+    const IPCTabContext& aContext, const hal::ProcessPriority& aPriority,
+    const TabId& aOpenerTabId, const TabId& aTabId, ContentParentId* aCpId,
+    bool* aIsForBrowser) {
+#if 0
+  if (!CanOpenBrowser(aContext)) {
+      return false;
+  }
+#endif
+  RefPtr<ContentParent> cp;
+  MaybeInvalidTabContext tc(aContext);
+  if (!tc.IsValid()) {
+    NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
+                             "the child process. (%s)",
+                             tc.GetInvalidReason())
+                 .get());
+    return IPC_FAIL_NO_REASON(this);
+  }
+
+  if (tc.GetTabContext().IsJSPlugin()) {
+    cp =
+        GetNewOrUsedJSPluginProcess(tc.GetTabContext().JSPluginId(), aPriority);
+  } else {
+    cp = GetNewOrUsedBrowserProcess(
+        nullptr, NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE), aPriority, this);
+  }
+
+  if (!cp) {
+    *aCpId = 0;
+    *aIsForBrowser = false;
+    return IPC_OK();
+  }
+
+  *aCpId = cp->ChildID();
+  *aIsForBrowser = cp->IsForBrowser();
+
+  ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
+  if (cp->IsForJSPlugin()) {
+    // We group all the iframes for a specific JS plugin into one process,
+    // regardless of origin. As a consequence that process can't be a child of
+    // the content process that contains the document with the element loading
+    // the plugin. All content processes need to be able to communicate with the
+    // process for the JS plugin.
+    cpm->RegisterRemoteFrame(aTabId, ChildID(), aOpenerTabId, aContext,
+                             cp->ChildID());
+    return IPC_OK();
+  }
+
+  // cp was already added to the ContentProcessManager, this just sets the
+  // parent ID.
+  cpm->AddContentProcess(cp, this->ChildID());
+
+  if (cpm->AddGrandchildProcess(this->ChildID(), cp->ChildID()) &&
+      cpm->RegisterRemoteFrame(aTabId, ChildID(), aOpenerTabId, aContext,
+                               cp->ChildID())) {
+    return IPC_OK();
+  }
+
+  return IPC_FAIL_NO_REASON(this);
+}
+
+mozilla::ipc::IPCResult ContentParent::RecvBridgeToChildProcess(
+    const ContentParentId& aCpId, Endpoint<PContentBridgeParent>* aEndpoint) {
+  ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
+  ContentParent* cp = cpm->GetContentProcessById(aCpId);
+
+  if (cp && cp->CanCommunicateWith(ChildID())) {
+    Endpoint<PContentBridgeParent> parent;
+    Endpoint<PContentBridgeChild> child;
+
+    if (NS_FAILED(PContentBridge::CreateEndpoints(OtherPid(), cp->OtherPid(),
+                                                  &parent, &child))) {
+      return IPC_FAIL(this, "CreateEndpoints failed");
+    }
+
+    *aEndpoint = std::move(parent);
+
+    if (!cp->SendInitContentBridgeChild(std::move(child))) {
+      return IPC_FAIL(this, "SendInitContentBridgeChild failed");
+    }
+
+    return IPC_OK();
+  }
+
+  // You can't bridge to a process you didn't open!
+  KillHard("BridgeToChildProcess");
+  return IPC_FAIL_NO_REASON(this);
+}
+
 static nsIDocShell* GetOpenerDocShellHelper(Element* aFrameElement) {
   // Propagate the private-browsing status of the element's parent
   // docshell to the remote docshell, via the chrome flags.
   MOZ_ASSERT(aFrameElement);
   nsPIDOMWindowOuter* win = aFrameElement->OwnerDoc()->GetWindow();
   if (!win) {
     NS_WARNING("Remote frame has no window");
     return nullptr;
@@ -1096,53 +1170,58 @@ mozilla::ipc::IPCResult ContentParent::R
       MOZ_ASSERT(!parent->GetOwnerElement(),
                  "Shouldn't have an owner elemnt before");
       parent->SetOwnerElement(aFrameElement);
       return parent;
     }
   }
 
   ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement);
+  bool isInContentProcess = !XRE_IsParentProcess();
   TabId tabId(nsContentUtils::GenerateTabId());
 
   nsIDocShell* docShell = GetOpenerDocShellHelper(aFrameElement);
   TabId openerTabId;
   if (docShell) {
     openerTabId = TabParent::GetTabIdFrom(docShell);
   }
 
   bool isPreloadBrowser = false;
   nsAutoString isPreloadBrowserStr;
   if (aFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::preloadedState,
                              isPreloadBrowserStr)) {
     isPreloadBrowser = isPreloadBrowserStr.EqualsLiteral("preloaded");
   }
 
-  RefPtr<ContentParent> constructorSender;
-  MOZ_RELEASE_ASSERT(XRE_IsParentProcess(), "Cannot allocate TabParent in content process");
-  if (aOpenerContentParent) {
-    constructorSender = aOpenerContentParent;
+  RefPtr<nsIContentParent> constructorSender;
+  if (isInContentProcess) {
+    MOZ_ASSERT(aContext.IsMozBrowserElement() || aContext.IsJSPlugin());
+    constructorSender = CreateContentBridgeParent(aContext, initialPriority,
+                                                  openerTabId, tabId);
   } else {
-    if (aContext.IsJSPlugin()) {
-      constructorSender =
-          GetNewOrUsedJSPluginProcess(aContext.JSPluginId(), initialPriority);
+    if (aOpenerContentParent) {
+      constructorSender = aOpenerContentParent;
     } else {
-      constructorSender = GetNewOrUsedBrowserProcess(
-          aFrameElement, remoteType, initialPriority, nullptr,
-          isPreloadBrowser);
-    }
-    if (!constructorSender) {
-      return nullptr;
+      if (aContext.IsJSPlugin()) {
+        constructorSender =
+            GetNewOrUsedJSPluginProcess(aContext.JSPluginId(), initialPriority);
+      } else {
+        constructorSender = GetNewOrUsedBrowserProcess(
+            aFrameElement, remoteType, initialPriority, nullptr,
+            isPreloadBrowser);
+      }
+      if (!constructorSender) {
+        return nullptr;
+      }
     }
-  }
-  ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
-  cpm->RegisterRemoteFrame(tabId, ContentParentId(0), openerTabId,
-                            aContext.AsIPCTabContext(),
-                            constructorSender->ChildID());
-
+    ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
+    cpm->RegisterRemoteFrame(tabId, ContentParentId(0), openerTabId,
+                             aContext.AsIPCTabContext(),
+                             constructorSender->ChildID());
+  }
   if (constructorSender) {
     nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
     docShell->GetTreeOwner(getter_AddRefs(treeOwner));
     if (!treeOwner) {
       return nullptr;
     }
 
     nsCOMPtr<nsIWebBrowserChrome> wbc = do_GetInterface(treeOwner);
@@ -1183,16 +1262,44 @@ mozilla::ipc::IPCResult ContentParent::R
       RefPtr<TabParent> constructedTabParent = TabParent::GetFrom(browser);
       constructedTabParent->SetOwnerElement(aFrameElement);
       return constructedTabParent;
     }
   }
   return nullptr;
 }
 
+/*static*/ ContentBridgeParent* ContentParent::CreateContentBridgeParent(
+    const TabContext& aContext, const hal::ProcessPriority& aPriority,
+    const TabId& aOpenerTabId, const TabId& aTabId) {
+  MOZ_ASSERT(aTabId);
+
+  ContentChild* child = ContentChild::GetSingleton();
+  ContentParentId cpId;
+  bool isForBrowser;
+  if (!child->SendCreateChildProcess(aContext.AsIPCTabContext(), aPriority,
+                                     aOpenerTabId, aTabId, &cpId,
+                                     &isForBrowser)) {
+    return nullptr;
+  }
+  if (cpId == 0) {
+    return nullptr;
+  }
+  Endpoint<PContentBridgeParent> endpoint;
+  if (!child->SendBridgeToChildProcess(cpId, &endpoint)) {
+    return nullptr;
+  }
+  ContentBridgeParent* parent =
+      ContentBridgeParent::Create(std::move(endpoint));
+  parent->SetChildID(cpId);
+  parent->SetIsForBrowser(isForBrowser);
+  parent->SetIsForJSPlugin(aContext.IsJSPlugin());
+  return parent;
+}
+
 void ContentParent::GetAll(nsTArray<ContentParent*>& aArray) {
   aArray.Clear();
 
   for (auto* cp : AllProcesses(eLive)) {
     aArray.AppendElement(cp);
   }
 }
 
@@ -2219,17 +2326,18 @@ ContentParent::LaunchSubprocessAsync(hal
   return retval;
 }
 
 ContentParent::ContentParent(ContentParent* aOpener,
                              const nsAString& aRemoteType,
                              RecordReplayState aRecordReplayState,
                              const nsAString& aRecordingFile,
                              int32_t aJSPluginID)
-    : mSelfRef(nullptr),
+    : nsIContentParent(),
+      mSelfRef(nullptr),
       mSubprocess(nullptr),
       mLaunchTS(TimeStamp::Now()),
       mLaunchYieldTS(mLaunchTS),
       mActivateTS(mLaunchTS),
       mOpener(aOpener),
       mRemoteType(aRemoteType),
       mChildID(gContentChildID++),
       mGeolocationWatchID(-1),
@@ -2249,18 +2357,16 @@ ContentParent::ContentParent(ContentPare
       mIsInputPriorityEventEnabled(false),
       mHangMonitorActor(nullptr) {
   // Insert ourselves into the global linked list of ContentParent objects.
   if (!sContentParents) {
     sContentParents = new LinkedList<ContentParent>();
   }
   sContentParents->insertBack(this);
 
-  mMessageManager = nsFrameMessageManager::NewProcessMessageManager(true);
-
   // From this point on, NS_WARNING, NS_ASSERTION, etc. should print out the
   // PID along with the warning.
   nsDebugImpl::SetMultiprocessMode("Parent");
 
 #if defined(XP_WIN)
   if (XRE_IsParentProcess()) {
     audio::AudioNotificationSender::Init();
   }
@@ -2906,17 +3012,17 @@ mozilla::ipc::IPCResult ContentParent::R
 // We want ContentParent to show up in CC logs for debugging purposes, but we
 // don't actually cycle collect it.
 NS_IMPL_CYCLE_COLLECTION_0(ContentParent)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(ContentParent)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(ContentParent)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ContentParent)
-  NS_INTERFACE_MAP_ENTRY_CONCRETE(ContentParent)
+  NS_INTERFACE_MAP_ENTRY(nsIContentParent)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
   NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionCallback)
   NS_INTERFACE_MAP_ENTRY(nsIDOMGeoPositionErrorCallback)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
 NS_INTERFACE_MAP_END
 
 NS_IMETHODIMP
@@ -3137,178 +3243,51 @@ mozilla::ipc::IPCResult ContentParent::R
     return IPC_FAIL(this, "BackgroundParent::Alloc failed");
   }
 
   return IPC_OK();
 }
 
 mozilla::jsipc::PJavaScriptParent* ContentParent::AllocPJavaScriptParent() {
   MOZ_ASSERT(ManagedPJavaScriptParent().IsEmpty());
-  return NewJavaScriptParent();
+  return nsIContentParent::AllocPJavaScriptParent();
 }
 
 bool ContentParent::DeallocPJavaScriptParent(PJavaScriptParent* parent) {
-  ReleaseJavaScriptParent(parent);
-  return true;
-}
-
-bool ContentParent::CanOpenBrowser(const IPCTabContext& aContext) {
-  // (PopupIPCTabContext lets the child process prove that it has access to
-  // the app it's trying to open.)
-  // On e10s we also allow UnsafeTabContext to allow service workers to open
-  // windows. This is enforced in MaybeInvalidTabContext.
-  if (aContext.type() != IPCTabContext::TPopupIPCTabContext &&
-      aContext.type() != IPCTabContext::TUnsafeIPCTabContext) {
-    ASSERT_UNLESS_FUZZING(
-        "Unexpected IPCTabContext type.  Aborting AllocPBrowserParent.");
-    return false;
-  }
-
-  if (aContext.type() == IPCTabContext::TPopupIPCTabContext) {
-    const PopupIPCTabContext& popupContext = aContext.get_PopupIPCTabContext();
-    if (popupContext.opener().type() != PBrowserOrId::TPBrowserParent) {
-      ASSERT_UNLESS_FUZZING(
-          "Unexpected PopupIPCTabContext type.  Aborting AllocPBrowserParent.");
-      return false;
-    }
-
-    auto opener =
-        TabParent::GetFrom(popupContext.opener().get_PBrowserParent());
-    if (!opener) {
-      ASSERT_UNLESS_FUZZING(
-          "Got null opener from child; aborting AllocPBrowserParent.");
-      return false;
-    }
-
-    // Popup windows of isMozBrowserElement frames must be isMozBrowserElement
-    // if the parent isMozBrowserElement.  Allocating a !isMozBrowserElement
-    // frame with same app ID would allow the content to access data it's not
-    // supposed to.
-    if (!popupContext.isMozBrowserElement() && opener->IsMozBrowserElement()) {
-      ASSERT_UNLESS_FUZZING(
-          "Child trying to escalate privileges!  Aborting "
-          "AllocPBrowserParent.");
-      return false;
-    }
-  }
-
-  MaybeInvalidTabContext tc(aContext);
-  if (!tc.IsValid()) {
-    NS_ERROR(nsPrintfCString("Child passed us an invalid TabContext.  (%s)  "
-                             "Aborting AllocPBrowserParent.",
-                             tc.GetInvalidReason())
-                 .get());
-    return false;
-  }
-
-  return true;
+  return nsIContentParent::DeallocPJavaScriptParent(parent);
 }
 
 PBrowserParent* ContentParent::AllocPBrowserParent(
     const TabId& aTabId, const TabId& aSameTabGroupAs,
     const IPCTabContext& aContext, const uint32_t& aChromeFlags,
     const ContentParentId& aCpId, const bool& aIsForBrowser) {
-  MOZ_ASSERT(!aSameTabGroupAs);
-
-  Unused << aCpId;
-  Unused << aIsForBrowser;
-
-  if (!CanOpenBrowser(aContext)) {
-    return nullptr;
-  }
-
-  uint32_t chromeFlags = aChromeFlags;
-  TabId openerTabId(0);
-  ContentParentId openerCpId(0);
-  if (aContext.type() == IPCTabContext::TPopupIPCTabContext) {
-    // CanOpenBrowser has ensured that the IPCTabContext is of
-    // type PopupIPCTabContext, and that the opener TabParent is
-    // reachable.
-    const PopupIPCTabContext& popupContext = aContext.get_PopupIPCTabContext();
-    auto opener =
-        TabParent::GetFrom(popupContext.opener().get_PBrowserParent());
-    openerTabId = opener->GetTabId();
-    openerCpId = opener->Manager()->ChildID();
-
-    // We must ensure that the private browsing and remoteness flags
-    // match those of the opener.
-    nsCOMPtr<nsILoadContext> loadContext = opener->GetLoadContext();
-    if (!loadContext) {
-      return nullptr;
-    }
-
-    bool isPrivate;
-    loadContext->GetUsePrivateBrowsing(&isPrivate);
-    if (isPrivate) {
-      chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
-    }
-  }
-
-  if (openerTabId > 0 ||
-      aContext.type() == IPCTabContext::TUnsafeIPCTabContext) {
-    MOZ_ASSERT(XRE_IsParentProcess());
-    if (!XRE_IsParentProcess()) {
-      return nullptr;
-    }
-
-    // The creation of PBrowser was triggered from content process through
-    // either window.open() or service worker's openWindow().
-    // We need to register remote frame with the child generated tab id.
-    ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
-    if (!cpm->RegisterRemoteFrame(aTabId, openerCpId, openerTabId, aContext,
-                                  aCpId)) {
-      return nullptr;
-    }
-  }
-
-  // And because we're allocating a remote browser, of course the
-  // window is remote.
-  chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
-
-  MaybeInvalidTabContext tc(aContext);
-  MOZ_ASSERT(tc.IsValid());
-  TabParent* parent = new TabParent(static_cast<ContentParent*>(this), aTabId,
-                                    tc.GetTabContext(), chromeFlags);
-
-  // We release this ref in DeallocPBrowserParent()
-  NS_ADDREF(parent);
-  return parent;
+  return nsIContentParent::AllocPBrowserParent(
+      aTabId, aSameTabGroupAs, aContext, aChromeFlags, aCpId, aIsForBrowser);
 }
 
 bool ContentParent::DeallocPBrowserParent(PBrowserParent* frame) {
-  TabParent* parent = TabParent::GetFrom(frame);
-  NS_RELEASE(parent);
-  return true;
+  return nsIContentParent::DeallocPBrowserParent(frame);
 }
 
 mozilla::ipc::IPCResult ContentParent::RecvPBrowserConstructor(
     PBrowserParent* actor, const TabId& tabId, const TabId& sameTabGroupAs,
     const IPCTabContext& context, const uint32_t& chromeFlags,
     const ContentParentId& cpId, const bool& isForBrowser) {
-  TabParent* parent = TabParent::GetFrom(actor);
-  // When enabling input event prioritization, input events may preempt other
-  // normal priority IPC messages. To prevent the input events preempt
-  // PBrowserConstructor, we use an IPC 'RemoteIsReadyToHandleInputEvents' to
-  // notify parent that TabChild is created. In this case, PBrowser is initiated
-  // from content so that we can set TabParent as ready to handle input events.
-  parent->SetReadyToHandleInputEvents();
-  return IPC_OK();
+  return nsIContentParent::RecvPBrowserConstructor(
+      actor, tabId, sameTabGroupAs, context, chromeFlags, cpId, isForBrowser);
 }
 
 PIPCBlobInputStreamParent* ContentParent::AllocPIPCBlobInputStreamParent(
     const nsID& aID, const uint64_t& aSize) {
-  MOZ_CRASH("PIPCBlobInputStreamParent actors should be manually constructed!");
-  return nullptr;
+  return nsIContentParent::AllocPIPCBlobInputStreamParent(aID, aSize);
 }
 
 bool ContentParent::DeallocPIPCBlobInputStreamParent(
     PIPCBlobInputStreamParent* aActor) {
-  RefPtr<IPCBlobInputStreamParent> actor =
-      dont_AddRef(static_cast<IPCBlobInputStreamParent*>(aActor));
-  return true;
+  return nsIContentParent::DeallocPIPCBlobInputStreamParent(aActor);
 }
 
 mozilla::PRemoteSpellcheckEngineParent*
 ContentParent::AllocPRemoteSpellcheckEngineParent() {
   mozilla::RemoteSpellcheckEngineParent* parent =
       new mozilla::RemoteSpellcheckEngineParent();
   return parent;
 }
@@ -3576,33 +3555,36 @@ mozilla::ipc::IPCResult ContentParent::R
                                                    &endpoint);
 
   aResolver(std::move(endpoint));
 
   return IPC_OK();
 }
 
 PChildToParentStreamParent* ContentParent::AllocPChildToParentStreamParent() {
-  return mozilla::ipc::AllocPChildToParentStreamParent();
+  return nsIContentParent::AllocPChildToParentStreamParent();
 }
 
 bool ContentParent::DeallocPChildToParentStreamParent(
     PChildToParentStreamParent* aActor) {
-  delete aActor;
-  return true;
+  return nsIContentParent::DeallocPChildToParentStreamParent(aActor);
+}
+
+PParentToChildStreamParent* ContentParent::SendPParentToChildStreamConstructor(
+    PParentToChildStreamParent* aActor) {
+  return PContentParent::SendPParentToChildStreamConstructor(aActor);
 }
 
 PParentToChildStreamParent* ContentParent::AllocPParentToChildStreamParent() {
-  MOZ_CRASH("PParentToChildStreamParent actors should be manually constructed!");
+  return nsIContentParent::AllocPParentToChildStreamParent();
 }
 
 bool ContentParent::DeallocPParentToChildStreamParent(
     PParentToChildStreamParent* aActor) {
-  delete aActor;
-  return true;
+  return nsIContentParent::DeallocPParentToChildStreamParent(aActor);
 }
 
 PPSMContentDownloaderParent* ContentParent::AllocPPSMContentDownloaderParent(
     const uint32_t& aCertType) {
   RefPtr<PSMContentDownloaderParent> downloader =
       new PSMContentDownloaderParent(aCertType);
   return downloader.forget().take();
 }
@@ -3887,69 +3869,33 @@ mozilla::ipc::IPCResult ContentParent::R
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult ContentParent::RecvSyncMessage(
     const nsString& aMsg, const ClonedMessageData& aData,
     InfallibleTArray<CpowEntry>&& aCpows, const IPC::Principal& aPrincipal,
     nsTArray<StructuredCloneData>* aRetvals) {
-  AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("ContentParent::RecvSyncMessage",
-                                             OTHER, aMsg);
-  MMPrinter::Print("ContentParent::RecvSyncMessage", aMsg, aData);
-
-  CrossProcessCpowHolder cpows(this, aCpows);
-  RefPtr<nsFrameMessageManager> ppm = mMessageManager;
-  if (ppm) {
-    ipc::StructuredCloneData data;
-    ipc::UnpackClonedMessageDataForParent(aData, data);
-
-    ppm->ReceiveMessage(ppm, nullptr, aMsg, true, &data, &cpows, aPrincipal,
-                        aRetvals, IgnoreErrors());
-  }
-  return IPC_OK();
+  return nsIContentParent::RecvSyncMessage(aMsg, aData, std::move(aCpows),
+                                           aPrincipal, aRetvals);
 }
 
 mozilla::ipc::IPCResult ContentParent::RecvRpcMessage(
     const nsString& aMsg, const ClonedMessageData& aData,
     InfallibleTArray<CpowEntry>&& aCpows, const IPC::Principal& aPrincipal,
     nsTArray<StructuredCloneData>* aRetvals) {
-  AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("ContentParent::RecvRpcMessage",
-                                             OTHER, aMsg);
-  MMPrinter::Print("ContentParent::RecvRpcMessage", aMsg, aData);
-
-  CrossProcessCpowHolder cpows(this, aCpows);
-  RefPtr<nsFrameMessageManager> ppm = mMessageManager;
-  if (ppm) {
-    ipc::StructuredCloneData data;
-    ipc::UnpackClonedMessageDataForParent(aData, data);
-
-    ppm->ReceiveMessage(ppm, nullptr, aMsg, true, &data, &cpows, aPrincipal,
-                        aRetvals, IgnoreErrors());
-  }
-  return IPC_OK();
+  return nsIContentParent::RecvRpcMessage(aMsg, aData, std::move(aCpows),
+                                          aPrincipal, aRetvals);
 }
 
 mozilla::ipc::IPCResult ContentParent::RecvAsyncMessage(
     const nsString& aMsg, InfallibleTArray<CpowEntry>&& aCpows,
     const IPC::Principal& aPrincipal, const ClonedMessageData& aData) {
-  AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("ContentParent::RecvAsyncMessage",
-                                             OTHER, aMsg);
-  MMPrinter::Print("ContentParent::RecvAsyncMessage", aMsg, aData);
-
-  CrossProcessCpowHolder cpows(this, aCpows);
-  RefPtr<nsFrameMessageManager> ppm = mMessageManager;
-  if (ppm) {
-    ipc::StructuredCloneData data;
-    ipc::UnpackClonedMessageDataForParent(aData, data);
-
-    ppm->ReceiveMessage(ppm, nullptr, aMsg, false, &data, &cpows, aPrincipal,
-                        nullptr, IgnoreErrors());
-  }
-  return IPC_OK();
+  return nsIContentParent::RecvAsyncMessage(aMsg, std::move(aCpows), aPrincipal,
+                                            aData);
 }
 
 static int32_t AddGeolocationListener(
     nsIDOMGeoPositionCallback* watcher,
     nsIDOMGeoPositionErrorCallback* errorCallBack, bool highAccuracy) {
   RefPtr<Geolocation> geo = Geolocation::NonWindowSingleton();
 
   UniquePtr<PositionOptions> options = MakeUnique<PositionOptions>();
@@ -4150,16 +4096,30 @@ nsresult ContentParent::DoSendAsyncMessa
   }
   if (!SendAsyncMessage(nsString(aMessage), cpows, Principal(aPrincipal),
                         data)) {
     return NS_ERROR_UNEXPECTED;
   }
   return NS_OK;
 }
 
+PIPCBlobInputStreamParent* ContentParent::SendPIPCBlobInputStreamConstructor(
+    PIPCBlobInputStreamParent* aActor, const nsID& aID, const uint64_t& aSize) {
+  return PContentParent::SendPIPCBlobInputStreamConstructor(aActor, aID, aSize);
+}
+
+PBrowserParent* ContentParent::SendPBrowserConstructor(
+    PBrowserParent* aActor, const TabId& aTabId, const TabId& aSameTabGroupAs,
+    const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+    const ContentParentId& aCpId, const bool& aIsForBrowser) {
+  return PContentParent::SendPBrowserConstructor(
+      aActor, aTabId, aSameTabGroupAs, aContext, aChromeFlags, aCpId,
+      aIsForBrowser);
+}
+
 mozilla::ipc::IPCResult ContentParent::RecvKeywordToURI(
     const nsCString& aKeyword, nsString* aProviderName,
     RefPtr<nsIInputStream>* aPostData, OptionalURIParams* aURI) {
   *aPostData = nullptr;
   *aURI = void_t();
 
   nsCOMPtr<nsIURIFixup> fixup = components::URIFixup::Service();
   if (!fixup) {
@@ -4399,25 +4359,29 @@ mozilla::ipc::IPCResult ContentParent::R
     return IPC_OK();
   }
 
   formProcessor->ProvideContent(NS_LITERAL_STRING("SELECT"), *aContent,
                                 *aAttribute);
   return IPC_OK();
 }
 
+PFileDescriptorSetParent* ContentParent::SendPFileDescriptorSetConstructor(
+    const FileDescriptor& aFD) {
+  return PContentParent::SendPFileDescriptorSetConstructor(aFD);
+}
+
 PFileDescriptorSetParent* ContentParent::AllocPFileDescriptorSetParent(
     const FileDescriptor& aFD) {
-  return new FileDescriptorSetParent(aFD);
+  return nsIContentParent::AllocPFileDescriptorSetParent(aFD);
 }
 
 bool ContentParent::DeallocPFileDescriptorSetParent(
     PFileDescriptorSetParent* aActor) {
-  delete static_cast<FileDescriptorSetParent*>(aActor);
-  return true;
+  return nsIContentParent::DeallocPFileDescriptorSetParent(aActor);
 }
 
 bool ContentParent::IgnoreIPCPrincipal() {
   static bool sDidAddVarCache = false;
   static bool sIgnoreIPCPrincipal = false;
   if (!sDidAddVarCache) {
     sDidAddVarCache = true;
     Preferences::AddBoolVarCache(&sIgnoreIPCPrincipal,
@@ -5547,16 +5511,30 @@ mozilla::ipc::IPCResult ContentParent::R
 
   if (!SendFileCreationResponse(aID, FileCreationSuccessResult(ipcBlob))) {
     return IPC_FAIL_NO_REASON(this);
   }
 
   return IPC_OK();
 }
 
+bool ContentParent::CanCommunicateWith(ContentParentId aOtherProcess) {
+  // Normally a process can only communicate with its parent, but a JS plugin
+  // process can communicate with any process.
+  ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
+  ContentParentId parentId;
+  if (!cpm->GetParentProcessId(ChildID(), &parentId)) {
+    return false;
+  }
+  if (IsForJSPlugin()) {
+    return parentId == ContentParentId(0);
+  }
+  return parentId == aOtherProcess;
+}
+
 nsresult ContentParent::SaveRecording(nsIFile* aFile, bool* aRetval) {
   if (mRecordReplayState != eRecording) {
     *aRetval = false;
     return NS_OK;
   }
 
   PRFileDesc* prfd;
   nsresult rv = aFile->OpenNSPRFileDesc(
@@ -5885,9 +5863,9 @@ mozilla::ipc::IPCResult ContentParent::R
 NS_IMPL_ISUPPORTS(ParentIdleListener, nsIObserver)
 
 NS_IMETHODIMP
 ParentIdleListener::Observe(nsISupports*, const char* aTopic,
                             const char16_t* aData) {
   mozilla::Unused << mParent->SendNotifyIdleObserver(
       mObserver, nsDependentCString(aTopic), nsDependentString(aData));
   return NS_OK;
-}
\ No newline at end of file
+}
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -3,24 +3,21 @@
 /* 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_ContentParent_h
 #define mozilla_dom_ContentParent_h
 
 #include "mozilla/dom/PContentParent.h"
-#include "mozilla/dom/CPOWManagerGetter.h"
-#include "mozilla/dom/ipc/IdType.h"
+#include "mozilla/dom/nsIContentParent.h"
 #include "mozilla/gfx/gfxVarReceiver.h"
 #include "mozilla/gfx/GPUProcessListener.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/GeckoChildProcessHost.h"
-#include "mozilla/ipc/PParentToChildStreamParent.h"
-#include "mozilla/ipc/PChildToParentStreamParent.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/HalTypes.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/MemoryReportingProcess.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Variant.h"
@@ -87,69 +84,62 @@ class URIParams;
 class TestShellParent;
 #ifdef FUZZING
 class ProtocolFuzzerHelper;
 #endif
 }  // namespace ipc
 
 namespace jsipc {
 class PJavaScriptParent;
-class CpowEntry;
 }  // namespace jsipc
 
 namespace layers {
 struct TextureFactoryIdentifier;
 }  // namespace layers
 
 namespace dom {
 
 class BrowsingContextGroup;
 class Element;
 class TabParent;
 class ClonedMessageData;
 class MemoryReport;
 class TabContext;
+class ContentBridgeParent;
 class GetFilesHelper;
 class MemoryReportRequestHost;
 
-#define NS_CONTENTPARENT_IID                         \
-  {                                                  \
-    0xeeec9ebf, 0x8ecf, 0x4e38, {                    \
-      0x81, 0xda, 0xb7, 0x34, 0x13, 0x7e, 0xac, 0xf3 \
-    }                                                \
-  }
-
 class ContentParent final : public PContentParent,
+                            public nsIContentParent,
                             public nsIObserver,
                             public nsIDOMGeoPositionCallback,
                             public nsIDOMGeoPositionErrorCallback,
                             public nsIInterfaceRequestor,
                             public gfx::gfxVarReceiver,
                             public mozilla::LinkedListElement<ContentParent>,
                             public gfx::GPUProcessListener,
-                            public mozilla::MemoryReportingProcess,
-                            public mozilla::dom::ipc::MessageManagerCallback,
-                            public CPOWManagerGetter,
-                            public mozilla::ipc::IShmemAllocator {
+                            public mozilla::MemoryReportingProcess {
   typedef mozilla::ipc::GeckoChildProcessHost GeckoChildProcessHost;
   typedef mozilla::ipc::OptionalURIParams OptionalURIParams;
   typedef mozilla::ipc::PFileDescriptorSetParent PFileDescriptorSetParent;
   typedef mozilla::ipc::TestShellParent TestShellParent;
   typedef mozilla::ipc::URIParams URIParams;
   typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
   typedef mozilla::dom::ClonedMessageData ClonedMessageData;
   typedef mozilla::dom::BrowsingContextGroup BrowsingContextGroup;
 
   friend class mozilla::PreallocatedProcessManagerImpl;
   friend class PContentParent;
 #ifdef FUZZING
   friend class mozilla::ipc::ProtocolFuzzerHelper;
 #endif
 
  public:
+  virtual bool IsContentParent() const override { return true; }
+
   using LaunchError = GeckoChildProcessHost::LaunchError;
   using LaunchPromise =
       GeckoChildProcessHost::LaunchPromise<RefPtr<ContentParent>>;
 
   /**
    * Create a subprocess suitable for use later as a content process.
    */
   static RefPtr<LaunchPromise> PreallocateProcess();
@@ -285,16 +275,24 @@ class ContentParent final : public PCont
    *           this plugin window.
    */
   static void SendAsyncUpdate(nsIWidget* aWidget);
 #endif
 
   // Let managees query if it is safe to send messages.
   bool IsDestroyed() const { return !mIPCOpen; }
 
+  mozilla::ipc::IPCResult RecvCreateChildProcess(
+      const IPCTabContext& aContext, const hal::ProcessPriority& aPriority,
+      const TabId& aOpenerTabId, const TabId& aTabId, ContentParentId* aCpId,
+      bool* aIsForBrowser);
+
+  mozilla::ipc::IPCResult RecvBridgeToChildProcess(
+      const ContentParentId& aCpId, Endpoint<PContentBridgeParent>* aEndpoint);
+
   mozilla::ipc::IPCResult RecvOpenRecordReplayChannel(
       const uint32_t& channelId, FileDescriptor* connection);
   mozilla::ipc::IPCResult RecvCreateReplayingProcess(
       const uint32_t& aChannelId);
 
   mozilla::ipc::IPCResult RecvCreateGMPService();
 
   mozilla::ipc::IPCResult RecvLoadPlugin(
@@ -368,43 +366,39 @@ class ContentParent final : public PCont
   void UpdateCookieStatus(nsIChannel* aChannel);
 
   bool IsLaunching() const {
     return mLifecycleState == LifecycleState::LAUNCHING;
   }
   bool IsAlive() const override;
   bool IsDead() const { return mLifecycleState == LifecycleState::DEAD; }
 
-  bool IsForBrowser() const { return mIsForBrowser; }
-  bool IsForJSPlugin() const {
+  virtual bool IsForBrowser() const override { return mIsForBrowser; }
+  virtual bool IsForJSPlugin() const override {
     return mJSPluginID != nsFakePluginTag::NOT_JSPLUGIN;
   }
 
   GeckoChildProcessHost* Process() const { return mSubprocess; }
 
   ContentParent* Opener() const { return mOpener; }
   nsIContentProcessInfo* ScriptableHelper() const { return mScriptableHelper; }
 
-  mozilla::dom::ProcessMessageManager* GetMessageManager() const {
-    return mMessageManager;
-  }
-
   bool NeedsPermissionsUpdate(const nsACString& aPermissionKey) const;
 
   /**
    * Kill our subprocess and make sure it dies.  Should only be used
    * in emergency situations since it bypasses the normal shutdown
    * process.
    *
    * WARNING: aReason appears in telemetry, so any new value passed in requires
    * data review.
    */
   void KillHard(const char* aWhy);
 
-  ContentParentId ChildID() const { return mChildID; }
+  ContentParentId ChildID() const override { return mChildID; }
 
   /**
    * Get a user-friendly name for this ContentParent.  We make no guarantees
    * about this name: It might not be unique, apps can spoof special names,
    * etc.  So please don't use this name to make any decisions about the
    * ContentParent based on the value returned here.
    */
   void FriendlyName(nsAString& aName, bool aAnonymize = false);
@@ -431,32 +425,42 @@ class ContentParent final : public PCont
    */
   already_AddRefed<embedding::PrintingParent> GetPrintingParent();
 #endif
 
   mozilla::ipc::IPCResult RecvInitStreamFilter(
       const uint64_t& aChannelId, const nsString& aAddonId,
       InitStreamFilterResolver&& aResolver);
 
-  PChildToParentStreamParent* AllocPChildToParentStreamParent();
-  bool DeallocPChildToParentStreamParent(PChildToParentStreamParent* aActor);
+  virtual PChildToParentStreamParent* AllocPChildToParentStreamParent()
+      override;
+  virtual bool DeallocPChildToParentStreamParent(
+      PChildToParentStreamParent* aActor) override;
+
+  virtual PParentToChildStreamParent* SendPParentToChildStreamConstructor(
+      PParentToChildStreamParent*) override;
 
-  PParentToChildStreamParent* AllocPParentToChildStreamParent();
-  bool DeallocPParentToChildStreamParent(PParentToChildStreamParent* aActor);
+  virtual PFileDescriptorSetParent* SendPFileDescriptorSetConstructor(
+      const FileDescriptor&) override;
+
+  virtual PParentToChildStreamParent* AllocPParentToChildStreamParent()
+      override;
+  virtual bool DeallocPParentToChildStreamParent(
+      PParentToChildStreamParent* aActor) override;
 
   PHalParent* AllocPHalParent();
 
   virtual mozilla::ipc::IPCResult RecvPHalConstructor(
       PHalParent* aActor) override {
     return PContentParent::RecvPHalConstructor(aActor);
   }
 
   PHeapSnapshotTempFileHelperParent* AllocPHeapSnapshotTempFileHelperParent();
 
-  PJavaScriptParent* AllocPJavaScriptParent();
+  virtual PJavaScriptParent* AllocPJavaScriptParent() override;
 
   virtual mozilla::ipc::IPCResult RecvPJavaScriptConstructor(
       PJavaScriptParent* aActor) override {
     return PContentParent::RecvPJavaScriptConstructor(aActor);
   }
 
   PRemoteSpellcheckEngineParent* AllocPRemoteSpellcheckEngineParent();
 
@@ -573,16 +577,24 @@ class ContentParent final : public PCont
   PSessionStorageObserverParent* AllocPSessionStorageObserverParent();
 
   virtual mozilla::ipc::IPCResult RecvPSessionStorageObserverConstructor(
       PSessionStorageObserverParent* aActor) override;
 
   bool DeallocPSessionStorageObserverParent(
       PSessionStorageObserverParent* aActor);
 
+  virtual bool SendActivate(PBrowserParent* aTab) override {
+    return PContentParent::SendActivate(aTab);
+  }
+
+  virtual bool SendDeactivate(PBrowserParent* aTab) override {
+    return PContentParent::SendDeactivate(aTab);
+  }
+
   bool DeallocPURLClassifierLocalParent(PURLClassifierLocalParent* aActor);
 
   bool DeallocPURLClassifierParent(PURLClassifierParent* aActor);
 
   // Use the PHangMonitor channel to ask the child to repaint a tab.
   void PaintTabWhileInterruptingJS(TabParent* aTabParent, bool aForceRepaint,
                                    const layers::LayersObserverEpoch& aEpoch);
 
@@ -625,18 +637,16 @@ class ContentParent final : public PCont
   mozilla::ipc::IPCResult RecvWindowBlur(BrowsingContext* aContext);
   mozilla::ipc::IPCResult RecvWindowPostMessage(
       BrowsingContext* aContext, const ClonedMessageData& aMessage,
       const PostMessageData& aData);
 
   mozilla::ipc::IPCResult RecvSetUserGestureActivation(
       BrowsingContext* aContext, bool aNewValue);
 
-  FORWARD_SHMEM_ALLOCATOR_TO(PContentParent)
-
  protected:
   void OnChannelConnected(int32_t pid) override;
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
   bool ShouldContinueFromReplyTimeout() override;
 
   void OnVarChanged(const GfxVarUpdate& aVar) override;
@@ -653,35 +663,49 @@ class ContentParent final : public PCont
    */
   static nsClassHashtable<nsStringHashKey, nsTArray<ContentParent*>>*
       sBrowserContentParents;
   static nsTArray<ContentParent*>* sPrivateContent;
   static nsDataHashtable<nsUint32HashKey, ContentParent*>*
       sJSPluginContentParents;
   static StaticAutoPtr<LinkedList<ContentParent>> sContentParents;
 
+  static ContentBridgeParent* CreateContentBridgeParent(
+      const TabContext& aContext, const hal::ProcessPriority& aPriority,
+      const TabId& aOpenerTabId, const TabId& aTabId);
+
 #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
   // Cached Mac sandbox params used when launching content processes.
   static StaticAutoPtr<std::vector<std::string>> sMacSandboxParams;
 #endif
 
+  // Hide the raw constructor methods since we don't want client code
+  // using them.
+  virtual PBrowserParent* SendPBrowserConstructor(
+      PBrowserParent* actor, const TabId& aTabId, const TabId& aSameTabGroupsAs,
+      const IPCTabContext& context, const uint32_t& chromeFlags,
+      const ContentParentId& aCpId, const bool& aIsForBrowser) override;
+  using PContentParent::SendPTestShellConstructor;
+
   // Set aLoadUri to true to load aURIToLoad and to false to only create the
   // window. aURIToLoad should always be provided, if available, to ensure
   // compatibility with GeckoView.
   mozilla::ipc::IPCResult CommonCreateWindow(
       PBrowserParent* aThisTab, bool aSetOpener, const uint32_t& aChromeFlags,
       const bool& aCalledFromJS, const bool& aPositionSpecified,
       const bool& aSizeSpecified, nsIURI* aURIToLoad,
       const nsCString& aFeatures, const nsCString& aBaseURI,
       const float& aFullZoom, uint64_t aNextTabParentId, const nsString& aName,
       nsresult& aResult, nsCOMPtr<nsITabParent>& aNewTabParent,
       bool* aWindowIsNew, int32_t& aOpenLocation,
       nsIPrincipal* aTriggeringPrincipal, uint32_t aReferrerPolicy,
       bool aLoadUri, nsIContentSecurityPolicy* aCsp);
 
+  FORWARD_SHMEM_ALLOCATOR_TO(PContentParent)
+
   enum RecordReplayState { eNotRecordingOrReplaying, eRecording, eReplaying };
 
   explicit ContentParent(int32_t aPluginID)
       : ContentParent(nullptr, EmptyString(), eNotRecordingOrReplaying,
                       EmptyString(), aPluginID) {}
   ContentParent(ContentParent* aOpener, const nsAString& aRemoteType,
                 RecordReplayState aRecordReplayState = eNotRecordingOrReplaying,
                 const nsAString& aRecordingFile = EmptyString())
@@ -791,55 +815,57 @@ class ContentParent final : public PCont
   // content process.
   //
   // See nsIPermissionManager::GetPermissionsForKey for more information on
   // these keys.
   void EnsurePermissionsByKey(const nsCString& aKey);
 
   static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure);
 
-  bool CanOpenBrowser(const IPCTabContext& aContext);
-
   /**
    * Get or create the corresponding content parent array to
    * |aContentProcessType|.
    */
   static nsTArray<ContentParent*>& GetOrCreatePool(
       const nsAString& aContentProcessType);
 
   mozilla::ipc::IPCResult RecvInitBackground(
       Endpoint<mozilla::ipc::PBackgroundParent>&& aEndpoint);
 
   mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport);
   mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration);
   mozilla::ipc::IPCResult RecvAddPerformanceMetrics(
       const nsID& aID, nsTArray<PerformanceInfo>&& aMetrics);
 
-  bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*);
+  virtual bool DeallocPJavaScriptParent(
+      mozilla::jsipc::PJavaScriptParent*) override;
 
   bool DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParent*);
 
-  PBrowserParent* AllocPBrowserParent(const TabId& aTabId,
-                                      const TabId& aSameTabGroupAs,
-                                      const IPCTabContext& aContext,
-                                      const uint32_t& aChromeFlags,
-                                      const ContentParentId& aCpId,
-                                      const bool& aIsForBrowser);
+  virtual PBrowserParent* AllocPBrowserParent(
+      const TabId& aTabId, const TabId& aSameTabGroupAs,
+      const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+      const ContentParentId& aCpId, const bool& aIsForBrowser) override;
 
-  bool DeallocPBrowserParent(PBrowserParent* frame);
+  virtual bool DeallocPBrowserParent(PBrowserParent* frame) override;
 
   virtual mozilla::ipc::IPCResult RecvPBrowserConstructor(
       PBrowserParent* actor, const TabId& tabId, const TabId& sameTabGroupAs,
       const IPCTabContext& context, const uint32_t& chromeFlags,
       const ContentParentId& cpId, const bool& isForBrowser) override;
 
-  PIPCBlobInputStreamParent* AllocPIPCBlobInputStreamParent(
-      const nsID& aID, const uint64_t& aSize);
+  virtual PIPCBlobInputStreamParent* SendPIPCBlobInputStreamConstructor(
+      PIPCBlobInputStreamParent* aActor, const nsID& aID,
+      const uint64_t& aSize) override;
 
-  bool DeallocPIPCBlobInputStreamParent(PIPCBlobInputStreamParent* aActor);
+  virtual PIPCBlobInputStreamParent* AllocPIPCBlobInputStreamParent(
+      const nsID& aID, const uint64_t& aSize) override;
+
+  virtual bool DeallocPIPCBlobInputStreamParent(
+      PIPCBlobInputStreamParent* aActor) override;
 
   mozilla::ipc::IPCResult RecvIsSecureURI(
       const uint32_t& aType, const URIParams& aURI, const uint32_t& aFlags,
       const OriginAttributes& aOriginAttributes, bool* aIsSecureURI);
 
   mozilla::ipc::IPCResult RecvAccumulateMixedContentHSTS(
       const URIParams& aURI, const bool& aActive,
       const OriginAttributes& aOriginAttributes);
@@ -969,27 +995,27 @@ class ContentParent final : public PCont
   mozilla::ipc::IPCResult RecvLoadURIExternal(const URIParams& uri,
                                               PBrowserParent* windowContext);
   mozilla::ipc::IPCResult RecvExtProtocolChannelConnectParent(
       const uint32_t& registrarId);
 
   mozilla::ipc::IPCResult RecvSyncMessage(
       const nsString& aMsg, const ClonedMessageData& aData,
       InfallibleTArray<CpowEntry>&& aCpows, const IPC::Principal& aPrincipal,
-      nsTArray<StructuredCloneData>* aRetvals);
+      nsTArray<StructuredCloneData>* aRetvals) override;
 
   mozilla::ipc::IPCResult RecvRpcMessage(
       const nsString& aMsg, const ClonedMessageData& aData,
       InfallibleTArray<CpowEntry>&& aCpows, const IPC::Principal& aPrincipal,
-      nsTArray<StructuredCloneData>* aRetvals);
+      nsTArray<StructuredCloneData>* aRetvals) override;
 
-  mozilla::ipc::IPCResult RecvAsyncMessage(const nsString& aMsg,
-                                           InfallibleTArray<CpowEntry>&& aCpows,
-                                           const IPC::Principal& aPrincipal,
-                                           const ClonedMessageData& aData);
+  mozilla::ipc::IPCResult RecvAsyncMessage(
+      const nsString& aMsg, InfallibleTArray<CpowEntry>&& aCpows,
+      const IPC::Principal& aPrincipal,
+      const ClonedMessageData& aData) override;
 
   mozilla::ipc::IPCResult RecvAddGeolocationListener(
       const IPC::Principal& aPrincipal, const bool& aHighAccuracy);
   mozilla::ipc::IPCResult RecvRemoveGeolocationListener();
 
   mozilla::ipc::IPCResult RecvSetGeolocationHigherAccuracy(const bool& aEnable);
 
   mozilla::ipc::IPCResult RecvConsoleMessage(const nsString& aMessage);
@@ -1065,20 +1091,21 @@ class ContentParent final : public PCont
                                                  const nsString& challenge,
                                                  const nsString& keytype,
                                                  const nsString& keyparams,
                                                  nsString* newValue);
 
   mozilla::ipc::IPCResult RecvKeygenProvideContent(
       nsString* aAttribute, nsTArray<nsString>* aContent);
 
-  PFileDescriptorSetParent* AllocPFileDescriptorSetParent(
-      const mozilla::ipc::FileDescriptor&);
+  virtual PFileDescriptorSetParent* AllocPFileDescriptorSetParent(
+      const mozilla::ipc::FileDescriptor&) override;
 
-  bool DeallocPFileDescriptorSetParent(PFileDescriptorSetParent*);
+  virtual bool DeallocPFileDescriptorSetParent(
+      PFileDescriptorSetParent*) override;
 
   PWebrtcGlobalParent* AllocPWebrtcGlobalParent();
   bool DeallocPWebrtcGlobalParent(PWebrtcGlobalParent* aActor);
 
   mozilla::ipc::IPCResult RecvUpdateDropEffect(const uint32_t& aDragAction,
                                                const uint32_t& aDropEffect);
 
   mozilla::ipc::IPCResult RecvShutdownProfile(const nsCString& aProfile);
@@ -1157,16 +1184,18 @@ class ContentParent final : public PCont
   void SendGetFilesResponseAndForget(const nsID& aID,
                                      const GetFilesResponseResult& aResult);
 
   bool SendRequestMemoryReport(const uint32_t& aGeneration,
                                const bool& aAnonymize,
                                const bool& aMinimizeMemoryUsage,
                                const MaybeFileDesc& aDMDFile) override;
 
+  bool CanCommunicateWith(ContentParentId aOtherProcess);
+
   nsresult SaveRecording(nsIFile* aFile, bool* aRetval);
 
   bool IsRecordingOrReplaying() const {
     return mRecordReplayState != eNotRecordingOrReplaying;
   }
 
   void OnBrowsingContextGroupSubscribe(BrowsingContextGroup* aGroup);
   void OnBrowsingContextGroupUnsubscribe(BrowsingContextGroup* aGroup);
@@ -1292,18 +1321,16 @@ class ContentParent final : public PCont
 
   UniquePtr<mozilla::ipc::CrashReporterHost> mCrashReporter;
 
   // Collects any pref changes that occur during process launch (after
   // the initial map is passed in command-line arguments) to be sent
   // when the process can receive IPC messages.
   nsTArray<Pref> mQueuedPrefs;
 
-  RefPtr<mozilla::dom::ProcessMessageManager> mMessageManager;
-
   static uint64_t sNextTabParentId;
   static nsDataHashtable<nsUint64HashKey, TabParent*> sNextTabParents;
 
 #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
   // When set to true, indicates that content processes should
   // initialize their sandbox during startup instead of waiting
   // for the SetProcessSandbox IPDL message.
   static bool sEarlySandboxInit;
--- a/dom/ipc/ContentProcessManager.cpp
+++ b/dom/ipc/ContentProcessManager.cpp
@@ -63,16 +63,29 @@ void ContentProcessManager::RemoveConten
   for (auto iter = mContentParentMap.begin(); iter != mContentParentMap.end();
        ++iter) {
     if (!iter->second.mChildrenCpId.empty()) {
       iter->second.mChildrenCpId.erase(aChildCpId);
     }
   }
 }
 
+bool ContentProcessManager::AddGrandchildProcess(
+    const ContentParentId& aParentCpId, const ContentParentId& aChildCpId) {
+  MOZ_ASSERT(NS_IsMainThread());
+
+  auto iter = mContentParentMap.find(aParentCpId);
+  if (NS_WARN_IF(iter == mContentParentMap.end())) {
+    ASSERT_UNLESS_FUZZING("Parent process should be already in map!");
+    return false;
+  }
+  iter->second.mChildrenCpId.insert(aChildCpId);
+  return true;
+}
+
 bool ContentProcessManager::GetParentProcessId(
     const ContentParentId& aChildCpId,
     /*out*/ ContentParentId* aParentCpId) {
   MOZ_ASSERT(NS_IsMainThread());
 
   auto iter = mContentParentMap.find(aChildCpId);
   if (NS_WARN_IF(iter == mContentParentMap.end())) {
     ASSERT_UNLESS_FUZZING();
--- a/dom/ipc/ContentProcessManager.h
+++ b/dom/ipc/ContentProcessManager.h
@@ -43,16 +43,22 @@ class ContentProcessManager final {
   void AddContentProcess(
       ContentParent* aChildCp,
       const ContentParentId& aParentCpId = ContentParentId(0));
   /**
    * Remove the content process by id.
    */
   void RemoveContentProcess(const ContentParentId& aChildCpId);
   /**
+   * Add a grandchild content process into the map.
+   * aParentCpId must be already added in the map by AddContentProcess().
+   */
+  bool AddGrandchildProcess(const ContentParentId& aParentCpId,
+                            const ContentParentId& aChildCpId);
+  /**
    * Get the parent process's id by child process's id.
    * Used to check if a child really belongs to the parent.
    */
   bool GetParentProcessId(const ContentParentId& aChildCpId,
                           /*out*/ ContentParentId* aParentCpId);
   /**
    * Return the ContentParent pointer by id.
    */
--- a/dom/ipc/FilePickerParent.cpp
+++ b/dom/ipc/FilePickerParent.cpp
@@ -123,17 +123,17 @@ FilePickerParent::IORunnable::Run() {
 
   return NS_OK;
 }
 
 void FilePickerParent::IORunnable::Destroy() { mFilePickerParent = nullptr; }
 
 void FilePickerParent::SendFilesOrDirectories(
     const nsTArray<BlobImplOrString>& aData) {
-  ContentParent* parent = TabParent::GetFrom(Manager())->Manager();
+  nsIContentParent* parent = TabParent::GetFrom(Manager())->Manager();
 
   if (mMode == nsIFilePicker::modeGetFolder) {
     MOZ_ASSERT(aData.Length() <= 1);
     if (aData.IsEmpty()) {
       Unused << Send__delete__(this, void_t(), mResult);
       return;
     }
 
--- a/dom/ipc/JSWindowActorChild.cpp
+++ b/dom/ipc/JSWindowActorChild.cpp
@@ -90,17 +90,17 @@ void JSWindowActorChild::SendAsyncMessag
         NS_SUCCEEDED(rv),
         "JS Window Actor AsyncMessageToParent dispatch failed");
     return;
   }
 
   // If we're a cross-process, send the async message over the corresponding
   // actor.
   ClonedMessageData msgData;
-  ContentChild* cc = ContentChild::GetSingleton();
+  nsIContentChild* cc = ContentChild::GetSingleton();
   if (!data.BuildClonedMessageDataForChild(cc, msgData)) {
     aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
     return;
   }
 
   if (!mManager->SendAsyncMessage(mName, PromiseFlatString(aMessageName),
                                   msgData)) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
--- a/dom/ipc/JSWindowActorParent.cpp
+++ b/dom/ipc/JSWindowActorParent.cpp
@@ -89,17 +89,17 @@ void JSWindowActorParent::SendAsyncMessa
                          "JS Window Actor AsyncMessageToChild dispatch failed");
     return;
   }
 
   // If we're a cross-process, send the async message over the corresponding
   // actor.
   ClonedMessageData msgData;
   RefPtr<TabParent> tabParent = mManager->GetTabParent();
-  ContentParent* cp = tabParent->Manager();
+  nsIContentParent* cp = tabParent->Manager();
   if (!data.BuildClonedMessageDataForParent(cp, msgData)) {
     aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR);
     return;
   }
 
   if (!mManager->SendAsyncMessage(mName, PromiseFlatString(aMessageName),
                                   msgData)) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -2,16 +2,17 @@
 /* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
 
 /* 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 PColorPicker;
 include protocol PContent;
+include protocol PContentBridge;
 include protocol PDocAccessible;
 include protocol PFilePicker;
 include protocol PIndexedDBPermissionRequest;
 include protocol PPluginWidget;
 include protocol PRemotePrintJob;
 include protocol PChildToParentStream;
 include protocol PParentToChildStream;
 include protocol PFileDescriptorSet;
@@ -128,17 +129,17 @@ struct RequestData
 union OptionalShmem
 {
   void_t;
   Shmem;
 };
 
 nested(upto inside_cpow) sync protocol PBrowser
 {
-    manager PContent;
+    manager PContent or PContentBridge;
 
     manages PColorPicker;
     manages PDocAccessible;
     manages PFilePicker;
     manages PIndexedDBPermissionRequest;
     manages PPluginWidget;
     manages PPaymentRequest;
     manages PWindowGlobal;
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -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/. */
 
 include protocol PBackground;
 include protocol PBrowser;
 include protocol PClientOpenWindowOp;
 include protocol PCompositorManager;
+include protocol PContentBridge;
 include protocol PContentPermissionRequest;
 include protocol PCycleCollectWithLogs;
 include protocol PPSMContentDownloader;
 include protocol PExternalHelperApp;
 include protocol PHandlerService;
 include protocol PFileDescriptorSet;
 include protocol PHal;
 include protocol PHeapSnapshotTempFileHelper;
@@ -58,16 +59,21 @@ include PContentPermission;
 include ServiceWorkerConfiguration;
 include GraphicsMessages;
 include MemoryReportTypes;
 include ClientIPCTypes;
 include HangTypes;
 include PrefsTypes;
 include NeckoChannelParams;
 
+// Workaround to prevent error if PContentChild.cpp & PContentBridgeParent.cpp
+// are put into different UnifiedProtocolsXX.cpp files.
+// XXX Remove this once bug 1069073 is fixed
+include "mozilla/dom/PContentBridgeParent.h";
+
 using refcounted class nsIDOMGeoPosition from "nsGeoPositionIPCSerialiser.h";
 using refcounted class nsIAlertNotification from "mozilla/AlertNotificationIPCSerializer.h";
 
 using struct ChromePackage from "mozilla/chrome/RegistryMessageUtils.h";
 using struct SubstitutionMapping from "mozilla/chrome/RegistryMessageUtils.h";
 using struct OverrideMapping from "mozilla/chrome/RegistryMessageUtils.h";
 using base::ProcessId from "base/process.h";
 using struct IPC::Permission from "mozilla/net/NeckoMessageUtils.h";
@@ -400,16 +406,17 @@ both:
     // to persist a subdocument.  For child->parent, arguments are
     // ignored and should be null/zero.
     async PWebBrowserPersistDocument(nullable PBrowser aBrowser,
                                      uint64_t aOuterWindowID);
 
 child:
     async InitGMPService(Endpoint<PGMPServiceChild> service);
     async InitProcessHangMonitor(Endpoint<PProcessHangMonitorChild> hangMonitor);
+    async InitContentBridgeChild(Endpoint<PContentBridgeChild> endpoint);
     async InitProfiler(Endpoint<PProfilerChild> aEndpoint);
 
     // Give the content process its endpoints to the compositor.
     async InitRendering(
       Endpoint<PCompositorManagerChild> compositor,
       Endpoint<PImageBridgeChild> imageBridge,
       Endpoint<PVRManagerChild> vr,
       Endpoint<PVideoDecoderManagerChild> video,
@@ -775,16 +782,24 @@ child:
                                OptionalLoadInfoArgs aLoadInfo,
                                uint64_t aChannelId,
                                nsIURI aOriginalURI,
                                uint64_t aIdentifier);
 
 parent:
     async InitBackground(Endpoint<PBackgroundParent> aEndpoint);
 
+    sync CreateChildProcess(IPCTabContext context,
+                            ProcessPriority priority,
+                            TabId openerTabId,
+                            TabId tabId)
+        returns (ContentParentId cpId, bool isForBrowser);
+    sync BridgeToChildProcess(ContentParentId cpId)
+        returns (Endpoint<PContentBridgeParent> endpoint);
+
     sync OpenRecordReplayChannel(uint32_t channelId)
         returns (FileDescriptor connection);
     async CreateReplayingProcess(uint32_t channelId);
 
     async CreateGMPService();
 
     async InitStreamFilter(uint64_t channelId, nsString addonId)
         returns (Endpoint<PStreamFilterChild> aEndpoint);
@@ -1289,9 +1304,9 @@ both:
     async WindowClose(BrowsingContext aContext, bool aTrustedCaller);
     async WindowFocus(BrowsingContext aContext);
     async WindowBlur(BrowsingContext aContext);
     async WindowPostMessage(BrowsingContext aContext, ClonedMessageData aMessage,
                             PostMessageData aData);
 };
 
 }
-}
\ No newline at end of file
+}
new file mode 100644
--- /dev/null
+++ b/dom/ipc/PContentBridge.ipdl
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=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 protocol PBrowser;
+include protocol PContent;
+include protocol PJavaScript;
+include protocol PFileDescriptorSet;
+include protocol PChildToParentStream;
+include protocol PParentToChildStream;
+include protocol PIPCBlobInputStream;
+
+include DOMTypes;
+include JavaScriptTypes;
+include ProtocolTypes;
+include PTabContext;
+
+using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
+using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
+using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h";
+using class mozilla::dom::MessagePort from "mozilla/dom/MessagePort.h";
+using class mozilla::dom::ipc::StructuredCloneData from "mozilla/dom/ipc/StructuredCloneData.h";
+
+namespace mozilla {
+namespace dom {
+
+/*
+ * PContentBridge allows us to represent a parent/child relationship between two
+ * child processes.  When a child process wants to open its own child, it asks
+ * the root process to create a new process and then bridge them.  The first
+ * child will allocate the PContentBridgeParent, and the newly opened child will
+ * allocate the PContentBridgeChild.  This protocol allows these processes to
+ * share PBrowsers and send messages to each other.
+ */
+nested(upto inside_cpow) sync protocol PContentBridge
+{
+    manages PBrowser;
+    manages PFileDescriptorSet;
+    manages PJavaScript;
+    manages PChildToParentStream;
+    manages PParentToChildStream;
+    manages PIPCBlobInputStream;
+
+child:
+    async PParentToChildStream();
+
+child:
+   /**
+     * Sending an activate message moves focus to the child.
+     */
+    async Activate(PBrowser aTab);
+
+    async Deactivate(PBrowser aTab);
+
+    async PIPCBlobInputStream(nsID aID, uint64_t aSize);
+
+parent:
+    sync SyncMessage(nsString aMessage, ClonedMessageData aData,
+                     CpowEntry[] aCpows, Principal aPrincipal)
+      returns (StructuredCloneData[] retval);
+
+    async PJavaScript();
+
+    async PChildToParentStream();
+
+both:
+    // Both the parent and the child can construct the PBrowser.
+    // See the comment in PContent::PBrowser().
+    async PBrowser(TabId tabId, TabId sameTabGroupAs,
+                   IPCTabContext context, uint32_t chromeFlags,
+                   ContentParentId cpId, bool isForBrowser);
+
+    async PFileDescriptorSet(FileDescriptor fd);
+
+    async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
+                       Principal aPrincipal, ClonedMessageData aData);
+};
+
+}
+}
--- a/dom/ipc/ProcessPriorityManager.cpp
+++ b/dom/ipc/ProcessPriorityManager.cpp
@@ -435,19 +435,19 @@ void ProcessPriorityManagerImpl::SetProc
     pppm->SetPriorityNow(aPriority);
   }
 }
 
 void ProcessPriorityManagerImpl::ObserveContentParentCreated(
     nsISupports* aContentParent) {
   // Do nothing; it's sufficient to get the PPPM.  But assign to nsRefPtr so we
   // don't leak the already_AddRefed object.
-  RefPtr<ContentParent> cp = do_QueryObject(aContentParent);
+  nsCOMPtr<nsIContentParent> cp = do_QueryInterface(aContentParent);
   RefPtr<ParticularProcessPriorityManager> pppm =
-      GetParticularProcessPriorityManager(cp);
+      GetParticularProcessPriorityManager(cp->AsContentParent());
 }
 
 void ProcessPriorityManagerImpl::ObserveContentParentDestroyed(
     nsISupports* aSubject) {
   nsCOMPtr<nsIPropertyBag2> props = do_QueryInterface(aSubject);
   NS_ENSURE_TRUE_VOID(props);
 
   uint64_t childID = CONTENT_PROCESS_ID_UNKNOWN;
@@ -472,18 +472,19 @@ void ProcessPriorityManagerImpl::NotifyP
   } else if (newPriority < PROCESS_PRIORITY_FOREGROUND_HIGH &&
              aOldPriority >= PROCESS_PRIORITY_FOREGROUND_HIGH) {
     mHighPriorityChildIDs.RemoveEntry(aParticularManager->ChildID());
   }
 }
 
 void ProcessPriorityManagerImpl::TabActivityChanged(TabParent* aTabParent,
                                                     bool aIsActive) {
+  ContentParent* cp = aTabParent->Manager()->AsContentParent();
   RefPtr<ParticularProcessPriorityManager> pppm =
-      GetParticularProcessPriorityManager(aTabParent->Manager());
+      GetParticularProcessPriorityManager(cp);
   if (!pppm) {
     return;
   }
 
   pppm->TabActivityChanged(aTabParent, aIsActive);
 }
 
 NS_IMPL_ISUPPORTS(ParticularProcessPriorityManager, nsIObserver,
--- a/dom/ipc/RemoteFrameParent.cpp
+++ b/dom/ipc/RemoteFrameParent.cpp
@@ -30,17 +30,17 @@ nsresult RemoteFrameParent::Init(const n
   attrs.SyncAttributesWithPrivateBrowsing(false);
   MutableTabContext tabContext;
   tabContext.SetTabContext(false, 0, UIStateChangeType_Set,
                            UIStateChangeType_Set, attrs, aPresentationURL);
 
   ProcessPriority initialPriority = PROCESS_PRIORITY_FOREGROUND;
 
   // Get our ConstructorSender object.
-  RefPtr<ContentParent> constructorSender =
+  RefPtr<nsIContentParent> constructorSender =
       ContentParent::GetNewOrUsedBrowserProcess(
           nullptr, aRemoteType, initialPriority, nullptr, false);
   if (NS_WARN_IF(!constructorSender)) {
     MOZ_ASSERT(false, "Unable to allocate content process!");
     return NS_ERROR_FAILURE;
   }
 
   ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
--- a/dom/ipc/StructuredCloneData.cpp
+++ b/dom/ipc/StructuredCloneData.cpp
@@ -190,22 +190,22 @@ bool BuildClonedMessageData(M* aManager,
       streams.AppendElement(stream->TakeValue());
     }
   }
 
   return true;
 }
 
 bool StructuredCloneData::BuildClonedMessageDataForParent(
-    ContentParent* aParent, ClonedMessageData& aClonedData) {
+    nsIContentParent* aParent, ClonedMessageData& aClonedData) {
   return BuildClonedMessageData(aParent, *this, aClonedData);
 }
 
 bool StructuredCloneData::BuildClonedMessageDataForChild(
-    ContentChild* aChild, ClonedMessageData& aClonedData) {
+    nsIContentChild* aChild, ClonedMessageData& aClonedData) {
   return BuildClonedMessageData(aChild, *this, aClonedData);
 }
 
 bool StructuredCloneData::BuildClonedMessageDataForBackgroundParent(
     PBackgroundParent* aParent, ClonedMessageData& aClonedData) {
   return BuildClonedMessageData(aParent, *this, aClonedData);
 }
 
--- a/dom/ipc/StructuredCloneData.h
+++ b/dom/ipc/StructuredCloneData.h
@@ -24,18 +24,18 @@ namespace ipc {
 class AutoIPCStream;
 class PBackgroundChild;
 class PBackgroundParent;
 
 }  // namespace ipc
 
 namespace dom {
 
-class ContentChild;
-class ContentParent;
+class nsIContentChild;
+class nsIContentParent;
 
 namespace ipc {
 
 /**
  * Wraps the non-reference-counted JSStructuredCloneData class to have a
  * reference count so that multiple StructuredCloneData instances can reference
  * a single underlying serialized representation.
  *
@@ -176,19 +176,19 @@ class StructuredCloneData : public Struc
 
   void Write(JSContext* aCx, JS::Handle<JS::Value> aValue,
              JS::Handle<JS::Value> aTransfers, ErrorResult& aRv);
 
   // Actor-varying methods to convert the structured clone stored in this holder
   // by a previous call to Write() into ClonedMessageData IPC representation.
   // (Blobs are represented in IPC by IPCBlob actors, so we need the parent to
   // be able to create them.)
-  bool BuildClonedMessageDataForParent(ContentParent* aParent,
+  bool BuildClonedMessageDataForParent(nsIContentParent* aParent,
                                        ClonedMessageData& aClonedData);
-  bool BuildClonedMessageDataForChild(ContentChild* aChild,
+  bool BuildClonedMessageDataForChild(nsIContentChild* aChild,
                                       ClonedMessageData& aClonedData);
   bool BuildClonedMessageDataForBackgroundParent(
       mozilla::ipc::PBackgroundParent* aParent, ClonedMessageData& aClonedData);
   bool BuildClonedMessageDataForBackgroundChild(
       mozilla::ipc::PBackgroundChild* aChild, ClonedMessageData& aClonedData);
 
   // Actor-varying and memory-management-strategy-varying methods to initialize
   // this holder from a ClonedMessageData representation.
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -345,27 +345,27 @@ already_AddRefed<TabChild> TabChild::Fin
   if (iter == NestedTabChildMap().end()) {
     return nullptr;
   }
   RefPtr<TabChild> tabChild = iter->second;
   return tabChild.forget();
 }
 
 /*static*/ already_AddRefed<TabChild> TabChild::Create(
-    ContentChild* aManager, const TabId& aTabId,
+    nsIContentChild* aManager, const TabId& aTabId,
     const TabId& aSameTabGroupAs, const TabContext& aContext,
     uint32_t aChromeFlags) {
   RefPtr<TabChild> groupChild = FindTabChild(aSameTabGroupAs);
   dom::TabGroup* group = groupChild ? groupChild->TabGroup() : nullptr;
   RefPtr<TabChild> iframe =
       new TabChild(aManager, aTabId, group, aContext, aChromeFlags);
   return iframe.forget();
 }
 
-TabChild::TabChild(ContentChild* aManager, const TabId& aTabId,
+TabChild::TabChild(nsIContentChild* aManager, const TabId& aTabId,
                    dom::TabGroup* aTabGroup, const TabContext& aContext,
                    uint32_t aChromeFlags)
     : TabContext(aContext),
       mTabGroup(aTabGroup),
       mManager(aManager),
       mChromeFlags(aChromeFlags),
       mMaxTouchPoints(0),
       mLayersId{0},
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -226,23 +226,23 @@ class TabChild final : public TabChildBa
 
   // Return a list of all active TabChildren.
   static nsTArray<RefPtr<TabChild>> GetAll();
 
  public:
   /**
    * Create a new TabChild object.
    */
-  TabChild(ContentChild* aManager, const TabId& aTabId, TabGroup* aTabGroup,
+  TabChild(nsIContentChild* aManager, const TabId& aTabId, TabGroup* aTabGroup,
            const TabContext& aContext, uint32_t aChromeFlags);
 
   nsresult Init(mozIDOMWindowProxy* aParent);
 
   /** Return a TabChild with the given attributes. */
-  static already_AddRefed<TabChild> Create(ContentChild* aManager,
+  static already_AddRefed<TabChild> Create(nsIContentChild* aManager,
                                            const TabId& aTabId,
                                            const TabId& aSameTabGroupAs,
                                            const TabContext& aContext,
                                            uint32_t aChromeFlags);
 
   // Let managees query if it is safe to send messages.
   bool IsDestroyed() const { return mDestroyed; }
 
@@ -463,17 +463,17 @@ class TabChild final : public TabChildBa
    * Signal to this TabChild that it should be made visible:
    * activated widget, retained layer tree, etc.  (Respectively,
    * made not visible.)
    */
   void MakeVisible();
   void MakeHidden();
   bool IsVisible();
 
-  ContentChild* Manager() const { return mManager; }
+  nsIContentChild* Manager() const { return mManager; }
 
   static inline TabChild* GetFrom(nsIDocShell* aDocShell) {
     if (!aDocShell) {
       return nullptr;
     }
 
     nsCOMPtr<nsITabChild> tc = aDocShell->GetTabChild();
     return static_cast<TabChild*>(tc.get());
@@ -798,17 +798,17 @@ class TabChild final : public TabChildBa
   class DelayedDeleteRunnable;
 
   TextureFactoryIdentifier mTextureFactoryIdentifier;
   RefPtr<nsWebBrowser> mWebBrowser;
   nsCOMPtr<nsIWebNavigation> mWebNav;
   RefPtr<mozilla::dom::TabGroup> mTabGroup;
   RefPtr<PuppetWidget> mPuppetWidget;
   nsCOMPtr<nsIURI> mLastURI;
-  RefPtr<ContentChild> mManager;
+  RefPtr<nsIContentChild> mManager;
   uint32_t mChromeFlags;
   uint32_t mMaxTouchPoints;
   layers::LayersId mLayersId;
   int64_t mBeforeUnloadListeners;
   CSSRect mUnscaledOuterRect;
   Maybe<bool> mLayersConnected;
   bool mDidFakeShow;
   bool mNotified;
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -9,16 +9,17 @@
 #include "TabParent.h"
 
 #ifdef ACCESSIBILITY
 #  include "mozilla/a11y/DocAccessibleParent.h"
 #  include "nsAccessibilityService.h"
 #endif
 #include "mozilla/BrowserElementParent.h"
 #include "mozilla/dom/ChromeMessageSender.h"
+#include "mozilla/dom/ContentBridgeParent.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/DataTransferItemList.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/indexedDB/ActorsParent.h"
 #include "mozilla/dom/IPCBlobUtils.h"
 #include "mozilla/dom/PaymentRequestParent.h"
 #include "mozilla/dom/RemoteFrameParent.h"
@@ -138,17 +139,17 @@ using mozilla::Unused;
 namespace mozilla {
 namespace dom {
 
 TabParent::LayerToTabParentTable* TabParent::sLayerToTabParentTable = nullptr;
 
 NS_IMPL_ISUPPORTS(TabParent, nsITabParent, nsIAuthPromptProvider,
                   nsISupportsWeakReference)
 
-TabParent::TabParent(ContentParent* aManager, const TabId& aTabId,
+TabParent::TabParent(nsIContentParent* aManager, const TabId& aTabId,
                      const TabContext& aContext, uint32_t aChromeFlags)
     : TabContext(aContext),
       mFrameElement(nullptr),
       mContentCache(*this),
       mRect(0, 0, 0, 0),
       mDimensions(0, 0),
       mOrientation(0),
       mDPI(0),
@@ -380,33 +381,43 @@ void TabParent::Destroy() {
   if (mIsDestroyed) {
     return;
   }
 
   DestroyInternal();
 
   mIsDestroyed = true;
 
-  ContentParent::NotifyTabDestroying(this->GetTabId(), Manager()->ChildID());
+  if (XRE_IsParentProcess()) {
+    ContentParent::NotifyTabDestroying(this->GetTabId(),
+                                       Manager()->AsContentParent()->ChildID());
+  } else {
+    ContentParent::NotifyTabDestroying(this->GetTabId(), Manager()->ChildID());
+  }
 
   mMarkedDestroying = true;
 }
 
 mozilla::ipc::IPCResult TabParent::RecvEnsureLayersConnected(
     CompositorOptions* aCompositorOptions) {
   if (mRenderFrame.IsInitialized()) {
     mRenderFrame.EnsureLayersConnected(aCompositorOptions);
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult TabParent::Recv__delete__() {
-  MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
-  ContentParent::UnregisterRemoteFrame(mTabId, Manager()->ChildID(),
-                                       mMarkedDestroying);
+  if (XRE_IsParentProcess()) {
+    ContentParent::UnregisterRemoteFrame(
+        mTabId, Manager()->AsContentParent()->ChildID(), mMarkedDestroying);
+  } else {
+    Manager()->AsContentBridgeParent()->NotifyTabDestroyed();
+    ContentParent::UnregisterRemoteFrame(mTabId, Manager()->ChildID(),
+                                         mMarkedDestroying);
+  }
 
   return IPC_OK();
 }
 
 void TabParent::ActorDestroy(ActorDestroyReason why) {
   if (mRenderFrame.IsInitialized()) {
     // It's important to unmap layers after the remote browser has been
     // destroyed, otherwise it may still send messages to the compositor which
@@ -946,16 +957,21 @@ auto TabParent::AllocPIndexedDBPermissio
     const Principal& aPrincipal) -> PIndexedDBPermissionRequestParent* {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsCOMPtr<nsIPrincipal> principal(aPrincipal);
   if (!principal) {
     return nullptr;
   }
 
+  nsCOMPtr<nsIContentParent> manager = Manager();
+  if (!manager->IsContentParent()) {
+    MOZ_CRASH("Figure out security checks for bridged content!");
+  }
+
   if (NS_WARN_IF(!mFrameElement)) {
     return nullptr;
   }
 
   return mozilla::dom::indexedDB::AllocPIndexedDBPermissionRequestParent(
       mFrameElement, principal);
 }
 
@@ -1056,17 +1072,18 @@ void TabParent::SendRealMouseEvent(Widge
     }
     return;
   }
 
   ScrollableLayerGuid guid;
   uint64_t blockId;
   ApzAwareEventRoutingToChild(&guid, &blockId, nullptr);
 
-  bool isInputPriorityEventEnabled = Manager()->IsInputPriorityEventEnabled();
+  bool isInputPriorityEventEnabled =
+      Manager()->AsContentParent()->IsInputPriorityEventEnabled();
 
   if (mIsMouseEnterIntoWidgetEventSuppressed) {
     // In the case that the TabParent suppressed the eMouseEnterWidget event due
     // to its corresponding TabChild wasn't ready to handle it, we have to
     // resend it when the TabChild is ready.
     mIsMouseEnterIntoWidgetEventSuppressed = false;
     WidgetMouseEvent localEvent(aEvent);
     localEvent.mMessage = eMouseEnterIntoWidget;
@@ -1183,17 +1200,17 @@ bool TabParent::QueryDropLinksForVerific
 }
 
 void TabParent::SendRealDragEvent(WidgetDragEvent& aEvent, uint32_t aDragAction,
                                   uint32_t aDropEffect,
                                   const IPC::Principal& aPrincipal) {
   if (mIsDestroyed || !mIsReadyToHandleInputEvents) {
     return;
   }
-  MOZ_ASSERT(!Manager()->IsInputPriorityEventEnabled());
+  MOZ_ASSERT(!Manager()->AsContentParent()->IsInputPriorityEventEnabled());
   aEvent.mRefPoint += GetChildProcessOffset();
   if (aEvent.mMessage == eDrop) {
     if (!QueryDropLinksForVerification()) {
       return;
     }
   }
   DebugOnly<bool> ret = PBrowserParent::SendRealDragEvent(
       aEvent, aDragAction, aDropEffect, aPrincipal);
@@ -1206,17 +1223,17 @@ void TabParent::SendMouseWheelEvent(Widg
     return;
   }
 
   ScrollableLayerGuid guid;
   uint64_t blockId;
   ApzAwareEventRoutingToChild(&guid, &blockId, nullptr);
   aEvent.mRefPoint += GetChildProcessOffset();
   DebugOnly<bool> ret =
-      Manager()->IsInputPriorityEventEnabled()
+      Manager()->AsContentParent()->IsInputPriorityEventEnabled()
           ? PBrowserParent::SendMouseWheelEvent(aEvent, guid, blockId)
           : PBrowserParent::SendNormalPriorityMouseWheelEvent(aEvent, guid,
                                                               blockId);
 
   NS_WARNING_ASSERTION(ret, "PBrowserParent::SendMouseWheelEvent() failed");
   MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess());
 }
 
@@ -1468,17 +1485,17 @@ void TabParent::SendRealKeyEvent(WidgetK
   if (aEvent.mMessage == eKeyPress) {
     // XXX Should we do this only when input context indicates an editor having
     //     focus and the key event won't cause inputting text?
     aEvent.InitAllEditCommands();
   } else {
     aEvent.PreventNativeKeyBindings();
   }
   DebugOnly<bool> ret =
-      Manager()->IsInputPriorityEventEnabled()
+      Manager()->AsContentParent()->IsInputPriorityEventEnabled()
           ? PBrowserParent::SendRealKeyEvent(aEvent)
           : PBrowserParent::SendNormalPriorityRealKeyEvent(aEvent);
 
   NS_WARNING_ASSERTION(ret, "PBrowserParent::SendRealKeyEvent() failed");
   MOZ_ASSERT(!ret || aEvent.HasBeenPostedToRemoteProcess());
 }
 
 void TabParent::SendRealTouchEvent(WidgetTouchEvent& aEvent) {
@@ -1507,17 +1524,18 @@ void TabParent::SendRealTouchEvent(Widge
     return;
   }
 
   LayoutDeviceIntPoint offset = GetChildProcessOffset();
   for (uint32_t i = 0; i < aEvent.mTouches.Length(); i++) {
     aEvent.mTouches[i]->mRefPoint += offset;
   }
 
-  bool inputPriorityEventEnabled = Manager()->IsInputPriorityEventEnabled();
+  bool inputPriorityEventEnabled =
+      Manager()->AsContentParent()->IsInputPriorityEventEnabled();
 
   if (aEvent.mMessage == eTouchMove) {
     DebugOnly<bool> ret =
         inputPriorityEventEnabled
             ? PBrowserParent::SendRealTouchMoveEvent(aEvent, guid, blockId,
                                                      apzResponse)
             : PBrowserParent::SendNormalPriorityRealTouchMoveEvent(
                   aEvent, guid, blockId, apzResponse);
@@ -1560,17 +1578,17 @@ bool TabParent::SendHandleTap(TapType aT
           fm->SetFocus(element, nsIFocusManager::FLAG_BYMOUSE |
                                     nsIFocusManager::FLAG_BYTOUCH |
                                     nsIFocusManager::FLAG_NOSCROLL);
         }
       }
     }
   }
   LayoutDeviceIntPoint offset = GetChildProcessOffset();
-  return Manager()->IsInputPriorityEventEnabled()
+  return Manager()->AsContentParent()->IsInputPriorityEventEnabled()
              ? PBrowserParent::SendHandleTap(aType, aPoint + offset, aModifiers,
                                              aGuid, aInputBlockId)
              : PBrowserParent::SendNormalPriorityHandleTap(
                    aType, aPoint + offset, aModifiers, aGuid, aInputBlockId);
 }
 
 mozilla::ipc::IPCResult TabParent::RecvSyncMessage(
     const nsString& aMessage, const ClonedMessageData& aData,
@@ -2170,17 +2188,17 @@ bool TabParent::SendCompositionEvent(Wid
   if (mIsDestroyed) {
     return false;
   }
 
   if (!mContentCache.OnCompositionEvent(aEvent)) {
     return true;
   }
 
-  bool ret = Manager()->IsInputPriorityEventEnabled()
+  bool ret = Manager()->AsContentParent()->IsInputPriorityEventEnabled()
                  ? PBrowserParent::SendCompositionEvent(aEvent)
                  : PBrowserParent::SendNormalPriorityCompositionEvent(aEvent);
   if (NS_WARN_IF(!ret)) {
     return false;
   }
   MOZ_ASSERT(aEvent.HasBeenPostedToRemoteProcess());
   return true;
 }
@@ -2189,17 +2207,17 @@ bool TabParent::SendSelectionEvent(Widge
   if (mIsDestroyed) {
     return false;
   }
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
     return true;
   }
   mContentCache.OnSelectionEvent(aEvent);
-  bool ret = Manager()->IsInputPriorityEventEnabled()
+  bool ret = Manager()->AsContentParent()->IsInputPriorityEventEnabled()
                  ? PBrowserParent::SendSelectionEvent(aEvent)
                  : PBrowserParent::SendNormalPrioritySelectionEvent(aEvent);
   if (NS_WARN_IF(!ret)) {
     return false;
   }
   MOZ_ASSERT(aEvent.HasBeenPostedToRemoteProcess());
   aEvent.mSucceeded = true;
   return true;
@@ -2596,17 +2614,17 @@ TabParent::SetDocShellIsActive(bool isAc
           a11y::nsWinUtils::HideNativeWindow(window);
         }
       }
     }
   }
 #endif
 
   // Keep track of how many active recording/replaying tabs there are.
-  if (Manager()->IsRecordingOrReplaying()) {
+  if (Manager()->AsContentParent()->IsRecordingOrReplaying()) {
     SetIsActiveRecordReplayTab(isActive);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TabParent::GetDocShellIsActive(bool* aIsActive) {
@@ -2693,35 +2711,35 @@ void TabParent::SetRenderLayersInternal(
   // RenderLayers requests are ignored.
   mLayerTreeEpoch = mLayerTreeEpoch.Next();
 
   Unused << SendRenderLayers(aEnabled, aForceRepaint, mLayerTreeEpoch);
 
   // Ask the child to repaint using the PHangMonitor channel/thread (which may
   // be less congested).
   if (aEnabled) {
-    Manager()->PaintTabWhileInterruptingJS(this, aForceRepaint,
-                                           mLayerTreeEpoch);
+    ContentParent* cp = Manager()->AsContentParent();
+    cp->PaintTabWhileInterruptingJS(this, aForceRepaint, mLayerTreeEpoch);
   }
 }
 
 NS_IMETHODIMP
 TabParent::PreserveLayers(bool aPreserveLayers) {
   mPreserveLayers = aPreserveLayers;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TabParent::SaveRecording(const nsAString& aFilename, bool* aRetval) {
   nsCOMPtr<nsIFile> file;
   nsresult rv = NS_NewLocalFile(aFilename, false, getter_AddRefs(file));
   if (NS_FAILED(rv)) {
     return rv;
   }
-  return Manager()->SaveRecording(file, aRetval);
+  return Manager()->AsContentParent()->SaveRecording(file, aRetval);
 }
 
 NS_IMETHODIMP
 TabParent::GetContentBlockingLog(Promise** aPromise) {
   NS_ENSURE_ARG_POINTER(aPromise);
 
   *aPromise = nullptr;
   if (!mFrameElement) {
@@ -2801,17 +2819,23 @@ TabParent::GetHasPresented(bool* aResult
 }
 
 void TabParent::NavigateByKey(bool aForward, bool aForDocumentNavigation) {
   Unused << SendNavigateByKey(aForward, aForDocumentNavigation);
 }
 
 NS_IMETHODIMP
 TabParent::TransmitPermissionsForPrincipal(nsIPrincipal* aPrincipal) {
-  return Manager()->TransmitPermissionsForPrincipal(aPrincipal);
+  nsCOMPtr<nsIContentParent> manager = Manager();
+  if (!manager->IsContentParent()) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  return manager->AsContentParent()->TransmitPermissionsForPrincipal(
+      aPrincipal);
 }
 
 NS_IMETHODIMP
 TabParent::GetHasBeforeUnload(bool* aResult) {
   *aResult = mHasBeforeUnload;
   return NS_OK;
 }
 
@@ -3096,33 +3120,36 @@ mozilla::ipc::IPCResult TabParent::RecvA
 mozilla::ipc::IPCResult TabParent::RecvInvokeDragSession(
     nsTArray<IPCDataTransfer>&& aTransfers, const uint32_t& aAction,
     const OptionalShmem& aVisualDnDData, const uint32_t& aStride,
     const gfx::SurfaceFormat& aFormat, const LayoutDeviceIntRect& aDragRect,
     const IPC::Principal& aPrincipal) {
   mInitialDataTransferItems.Clear();
   nsIPresShell* shell = mFrameElement->OwnerDoc()->GetShell();
   if (!shell) {
-    Unused << Manager()->SendEndDragSession(true, true, LayoutDeviceIntPoint(),
-                                            0);
-    // Continue sending input events with input priority when stopping the dnd
-    // session.
-    Manager()->SetInputPriorityEventEnabled(true);
+    if (Manager()->IsContentParent()) {
+      Unused << Manager()->AsContentParent()->SendEndDragSession(
+          true, true, LayoutDeviceIntPoint(), 0);
+      // Continue sending input events with input priority when stopping the dnd
+      // session.
+      Manager()->AsContentParent()->SetInputPriorityEventEnabled(true);
+    }
     return IPC_OK();
   }
 
   EventStateManager* esm = shell->GetPresContext()->EventStateManager();
   for (uint32_t i = 0; i < aTransfers.Length(); ++i) {
     mInitialDataTransferItems.AppendElement(std::move(aTransfers[i].items()));
   }
-
-  nsCOMPtr<nsIDragService> dragService =
-      do_GetService("@mozilla.org/widget/dragservice;1");
-  if (dragService) {
-    dragService->MaybeAddChildProcess(Manager());
+  if (Manager()->IsContentParent()) {
+    nsCOMPtr<nsIDragService> dragService =
+        do_GetService("@mozilla.org/widget/dragservice;1");
+    if (dragService) {
+      dragService->MaybeAddChildProcess(Manager()->AsContentParent());
+    }
   }
 
   if (aVisualDnDData.type() == OptionalShmem::Tvoid_t ||
       !aVisualDnDData.get_Shmem().IsReadable() ||
       aVisualDnDData.get_Shmem().Size<char>() < aDragRect.height * aStride) {
     mDnDVisualization = nullptr;
   } else {
     mDnDVisualization = gfx::CreateDataSourceSurfaceFromData(
@@ -3208,20 +3235,26 @@ bool TabParent::TakeDragVisualization(
 bool TabParent::AsyncPanZoomEnabled() const {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   return widget && widget->AsyncPanZoomEnabled();
 }
 
 void TabParent::StartPersistence(uint64_t aOuterWindowID,
                                  nsIWebBrowserPersistDocumentReceiver* aRecv,
                                  ErrorResult& aRv) {
+  nsCOMPtr<nsIContentParent> manager = Manager();
+  if (!manager->IsContentParent()) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return;
+  }
   auto* actor = new WebBrowserPersistDocumentParent();
   actor->SetOnReady(aRecv);
-  bool ok = Manager()->SendPWebBrowserPersistDocumentConstructor(
-      actor, this, aOuterWindowID);
+  bool ok =
+      manager->AsContentParent()->SendPWebBrowserPersistDocumentConstructor(
+          actor, this, aOuterWindowID);
   if (!ok) {
     aRv.Throw(NS_ERROR_FAILURE);
   }
   // (The actor will be destroyed on constructor failure.)
 }
 
 NS_IMETHODIMP
 TabParent::StartApzAutoscroll(float aAnchorX, float aAnchorY,
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -64,17 +64,17 @@ namespace gfx {
 class SourceSurface;
 class DataSourceSurface;
 }  // namespace gfx
 
 namespace dom {
 
 class CanonicalBrowsingContext;
 class ClonedMessageData;
-class ContentParent;
+class nsIContentParent;
 class Element;
 class DataTransfer;
 
 namespace ipc {
 class StructuredCloneData;
 }  // namespace ipc
 
 class TabParent final : public PBrowserParent,
@@ -95,17 +95,17 @@ class TabParent final : public PBrowserP
   // Helper class for ContentParent::RecvCreateWindow.
   struct AutoUseNewTab;
 
   // nsITabParent
   NS_DECL_NSITABPARENT
   // nsIDOMEventListener interfaces
   NS_DECL_NSIDOMEVENTLISTENER
 
-  TabParent(ContentParent* aManager, const TabId& aTabId,
+  TabParent(nsIContentParent* aManager, const TabId& aTabId,
             const TabContext& aContext, uint32_t aChromeFlags);
 
   Element* GetOwnerElement() const { return mFrameElement; }
   already_AddRefed<nsPIDOMWindowOuter> GetParentWindowOuter();
 
   void SetOwnerElement(Element* aElement);
 
   void CacheFrameLoader(nsFrameLoader* aFrameLoader);
@@ -472,17 +472,17 @@ class TabParent final : public PBrowserP
   static TabParent* GetFrom(nsITabParent* aTabParent);
 
   static TabParent* GetFrom(PBrowserParent* aTabParent);
 
   static TabParent* GetFrom(nsIContent* aContent);
 
   static TabId GetTabIdFrom(nsIDocShell* docshell);
 
-  ContentParent* Manager() const { return mManager; }
+  nsIContentParent* Manager() const { return mManager; }
 
   /**
    * Let managees query if Destroy() is already called so they don't send out
    * messages when the PBrowser actor is being destroyed.
    */
   bool IsDestroyed() const { return mIsDestroyed; }
 
   // Returns the closest widget for our frameloader's content.
@@ -622,17 +622,17 @@ class TabParent final : public PBrowserP
 
   void DestroyInternal();
 
   void SetRenderLayersInternal(bool aEnabled, bool aForceRepaint);
 
   already_AddRefed<nsFrameLoader> GetFrameLoader(
       bool aUseCachedFrameLoaderAfterDestroy = false) const;
 
-  RefPtr<ContentParent> mManager;
+  RefPtr<nsIContentParent> mManager;
   void TryCacheDPIAndScale();
 
   bool AsyncPanZoomEnabled() const;
 
   // Cached value indicating the docshell active state of the remote browser.
   bool mDocShellIsActive;
 
   // Update state prior to routing an APZ-aware event to the child process.
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -26,28 +26,32 @@ EXPORTS.mozilla.dom.ipc += [
     'StringTable.h',
     'StructuredCloneData.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'CoalescedInputData.h',
     'CoalescedMouseData.h',
     'CoalescedWheelData.h',
+    'ContentBridgeChild.h',
+    'ContentBridgeParent.h',
     'ContentChild.h',
     'ContentParent.h',
     'ContentProcess.h',
     'ContentProcessManager.h',
     'CPOWManagerGetter.h',
     'CSPMessageUtils.h',
     'DocShellMessageUtils.h',
     'FilePickerParent.h',
     'JSWindowActorChild.h',
     'JSWindowActorParent.h',
     'JSWindowActorService.h',
     'MemoryReportRequest.h',
+    'nsIContentChild.h',
+    'nsIContentParent.h',
     'PermissionMessageUtils.h',
     'RemoteFrameChild.h',
     'RemoteFrameParent.h',
     'TabChild.h',
     'TabContext.h',
     'TabMessageUtils.h',
     'TabParent.h',
     'URLClassifierChild.h',
@@ -62,28 +66,32 @@ EXPORTS.mozilla += [
     'ProcessHangMonitorIPC.h',
     'ProcessPriorityManager.h',
 ]
 
 UNIFIED_SOURCES += [
     'CoalescedMouseData.cpp',
     'CoalescedWheelData.cpp',
     'ColorPickerParent.cpp',
+    'ContentBridgeChild.cpp',
+    'ContentBridgeParent.cpp',
     'ContentParent.cpp',
     'ContentProcess.cpp',
     'ContentProcessManager.cpp',
     'CSPMessageUtils.cpp',
     'DocShellMessageUtils.cpp',
     'FilePickerParent.cpp',
     'JSWindowActorChild.cpp',
     'JSWindowActorParent.cpp',
     'JSWindowActorService.cpp',
     'MemMapSnapshot.cpp',
     'MemoryReportRequest.cpp',
     'MMPrinter.cpp',
+    'nsIContentChild.cpp',
+    'nsIContentParent.cpp',
     'PermissionMessageUtils.cpp',
     'PreallocatedProcessManager.cpp',
     'ProcessPriorityManager.cpp',
     'RemoteFrameChild.cpp',
     'RemoteFrameParent.cpp',
     'SharedMap.cpp',
     'SharedStringMap.cpp',
     'StructuredCloneData.cpp',
@@ -104,16 +112,17 @@ SOURCES += [
 
 IPDL_SOURCES += [
     'DOMTypes.ipdlh',
     'MemoryReportTypes.ipdlh',
     'PBrowser.ipdl',
     'PBrowserOrId.ipdlh',
     'PColorPicker.ipdl',
     'PContent.ipdl',
+    'PContentBridge.ipdl',
     'PContentPermission.ipdlh',
     'PContentPermissionRequest.ipdl',
     'PCycleCollectWithLogs.ipdl',
     'PFilePicker.ipdl',
     'PLoginReputation.ipdl',
     'PPluginWidget.ipdl',
     'PProcessHangMonitor.ipdl',
     'PrefsTypes.ipdlh',
new file mode 100644
--- /dev/null
+++ b/dom/ipc/nsIContentChild.cpp
@@ -0,0 +1,204 @@
+/* -*- 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 "nsIContentChild.h"
+
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/ChildProcessMessageManager.h"
+#include "mozilla/dom/DOMTypes.h"
+#include "mozilla/dom/File.h"
+#include "mozilla/dom/PermissionMessageUtils.h"
+#include "mozilla/dom/TabChild.h"
+#include "mozilla/dom/TabGroup.h"
+#include "mozilla/dom/ipc/StructuredCloneData.h"
+#include "mozilla/ipc/FileDescriptorSetChild.h"
+#include "mozilla/ipc/InputStreamUtils.h"
+#include "mozilla/ipc/IPCStreamAlloc.h"
+#include "mozilla/ipc/IPCStreamDestination.h"
+#include "mozilla/ipc/IPCStreamSource.h"
+#include "mozilla/ipc/PChildToParentStreamChild.h"
+#include "mozilla/ipc/PParentToChildStreamChild.h"
+#include "mozilla/dom/ipc/IPCBlobInputStreamChild.h"
+
+#include "MMPrinter.h"
+#include "nsPrintfCString.h"
+#include "xpcpublic.h"
+
+using namespace mozilla::ipc;
+using namespace mozilla::jsipc;
+
+namespace mozilla {
+namespace dom {
+
+PJavaScriptChild* nsIContentChild::AllocPJavaScriptChild() {
+  return NewJavaScriptChild();
+}
+
+bool nsIContentChild::DeallocPJavaScriptChild(PJavaScriptChild* aChild) {
+  ReleaseJavaScriptChild(aChild);
+  return true;
+}
+
+PBrowserChild* nsIContentChild::AllocPBrowserChild(
+    const TabId& aTabId, const TabId& aSameTabGroupAs,
+    const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+    const ContentParentId& aCpID, const bool& aIsForBrowser) {
+  // We'll happily accept any kind of IPCTabContext here; we don't need to
+  // check that it's of a certain type for security purposes, because we
+  // believe whatever the parent process tells us.
+
+  MaybeInvalidTabContext tc(aContext);
+  if (!tc.IsValid()) {
+    NS_ERROR(nsPrintfCString("Received an invalid TabContext from "
+                             "the parent process. (%s)  Crashing...",
+                             tc.GetInvalidReason())
+                 .get());
+    MOZ_CRASH("Invalid TabContext received from the parent process.");
+  }
+
+  RefPtr<TabChild> child = TabChild::Create(this, aTabId, aSameTabGroupAs,
+                                            tc.GetTabContext(), aChromeFlags);
+
+  // The ref here is released in DeallocPBrowserChild.
+  return child.forget().take();
+}
+
+bool nsIContentChild::DeallocPBrowserChild(PBrowserChild* aIframe) {
+  TabChild* child = static_cast<TabChild*>(aIframe);
+  NS_RELEASE(child);
+  return true;
+}
+
+mozilla::ipc::IPCResult nsIContentChild::RecvPBrowserConstructor(
+    PBrowserChild* aActor, const TabId& aTabId, const TabId& aSameTabGroupAs,
+    const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+    const ContentParentId& aCpID, const bool& aIsForBrowser) {
+  // This runs after AllocPBrowserChild() returns and the IPC machinery for this
+  // PBrowserChild has been set up.
+
+  auto tabChild = static_cast<TabChild*>(static_cast<TabChild*>(aActor));
+
+  if (NS_WARN_IF(NS_FAILED(tabChild->Init(/* aOpener */ nullptr)))) {
+    return IPC_FAIL(tabChild, "TabChild::Init failed");
+  }
+
+  nsCOMPtr<nsIObserverService> os = services::GetObserverService();
+  if (os) {
+    os->NotifyObservers(static_cast<nsITabChild*>(tabChild),
+                        "tab-child-created", nullptr);
+  }
+  // Notify parent that we are ready to handle input events.
+  tabChild->SendRemoteIsReadyToHandleInputEvents();
+  return IPC_OK();
+}
+
+PIPCBlobInputStreamChild* nsIContentChild::AllocPIPCBlobInputStreamChild(
+    const nsID& aID, const uint64_t& aSize) {
+  // IPCBlobInputStreamChild is refcounted. Here it's created and in
+  // DeallocPIPCBlobInputStreamChild is released.
+
+  RefPtr<IPCBlobInputStreamChild> actor =
+      new IPCBlobInputStreamChild(aID, aSize);
+  return actor.forget().take();
+}
+
+bool nsIContentChild::DeallocPIPCBlobInputStreamChild(
+    PIPCBlobInputStreamChild* aActor) {
+  RefPtr<IPCBlobInputStreamChild> actor =
+      dont_AddRef(static_cast<IPCBlobInputStreamChild*>(aActor));
+  return true;
+}
+
+PChildToParentStreamChild* nsIContentChild::AllocPChildToParentStreamChild() {
+  MOZ_CRASH("PChildToParentStreamChild actors should be manually constructed!");
+}
+
+bool nsIContentChild::DeallocPChildToParentStreamChild(
+    PChildToParentStreamChild* aActor) {
+  delete aActor;
+  return true;
+}
+
+PParentToChildStreamChild* nsIContentChild::AllocPParentToChildStreamChild() {
+  return mozilla::ipc::AllocPParentToChildStreamChild();
+}
+
+bool nsIContentChild::DeallocPParentToChildStreamChild(
+    PParentToChildStreamChild* aActor) {
+  delete aActor;
+  return true;
+}
+
+PFileDescriptorSetChild* nsIContentChild::AllocPFileDescriptorSetChild(
+    const FileDescriptor& aFD) {
+  return new FileDescriptorSetChild(aFD);
+}
+
+bool nsIContentChild::DeallocPFileDescriptorSetChild(
+    PFileDescriptorSetChild* aActor) {
+  delete static_cast<FileDescriptorSetChild*>(aActor);
+  return true;
+}
+
+mozilla::ipc::IPCResult nsIContentChild::RecvAsyncMessage(
+    const nsString& aMsg, InfallibleTArray<CpowEntry>&& aCpows,
+    const IPC::Principal& aPrincipal, const ClonedMessageData& aData) {
+  AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(
+      "nsIContentChild::RecvAsyncMessage", OTHER, aMsg);
+  MMPrinter::Print("nsIContentChild::RecvAsyncMessage", aMsg, aData);
+
+  CrossProcessCpowHolder cpows(this, aCpows);
+  RefPtr<nsFrameMessageManager> cpm =
+      nsFrameMessageManager::GetChildProcessManager();
+  if (cpm) {
+    ipc::StructuredCloneData data;
+    ipc::UnpackClonedMessageDataForChild(aData, data);
+
+    cpm->ReceiveMessage(cpm, nullptr, aMsg, false, &data, &cpows, aPrincipal,
+                        nullptr, IgnoreErrors());
+  }
+  return IPC_OK();
+}
+
+/* static */
+already_AddRefed<nsIEventTarget> nsIContentChild::GetConstructedEventTarget(
+    const IPC::Message& aMsg) {
+  ActorHandle handle;
+  TabId tabId, sameTabGroupAs;
+  PickleIterator iter(aMsg);
+  if (!IPC::ReadParam(&aMsg, &iter, &handle)) {
+    return nullptr;
+  }
+  aMsg.IgnoreSentinel(&iter);
+  if (!IPC::ReadParam(&aMsg, &iter, &tabId)) {
+    return nullptr;
+  }
+  aMsg.IgnoreSentinel(&iter);
+  if (!IPC::ReadParam(&aMsg, &iter, &sameTabGroupAs)) {
+    return nullptr;
+  }
+
+  // If sameTabGroupAs is non-zero, then the new tab will be in the same
+  // TabGroup as a previously created tab. Rather than try to find the
+  // previously created tab (whose constructor message may not even have been
+  // processed yet, in theory) and look up its event target, we just use the
+  // default event target. This means that runnables for this tab will not be
+  // labeled. However, this path is only taken for print preview and view
+  // source, which are not performance-sensitive.
+  if (sameTabGroupAs) {
+    return nullptr;
+  }
+
+  // If the request for a new TabChild is coming from the parent process, then
+  // there is no opener. Therefore, we create a fresh TabGroup.
+  RefPtr<TabGroup> tabGroup = new TabGroup();
+  nsCOMPtr<nsIEventTarget> target =
+      tabGroup->EventTargetFor(TaskCategory::Other);
+  return target.forget();
+}
+
+}  // namespace dom
+}  // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/ipc/nsIContentChild.h
@@ -0,0 +1,128 @@
+/* -*- 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_nsIContentChild_h
+#define mozilla_dom_nsIContentChild_h
+
+#include "mozilla/dom/ipc/IdType.h"
+
+#include "nsISupports.h"
+#include "nsStringFwd.h"
+#include "nsTArrayForwardDeclare.h"
+#include "mozilla/dom/CPOWManagerGetter.h"
+#include "mozilla/ipc/Shmem.h"
+#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
+
+#define NS_ICONTENTCHILD_IID                         \
+  {                                                  \
+    0x4eed2e73, 0x94ba, 0x48a8, {                    \
+      0xa2, 0xd1, 0xa5, 0xed, 0x86, 0xd7, 0xbb, 0xe4 \
+    }                                                \
+  }
+
+namespace IPC {
+class Principal;
+}  // namespace IPC
+
+namespace mozilla {
+namespace ipc {
+class FileDescriptor;
+class PFileDescriptorSetChild;
+class PChildToParentStreamChild;
+class PParentToChildStreamChild;
+class Shmem;
+}  // namespace ipc
+
+namespace jsipc {
+class PJavaScriptChild;
+class CpowEntry;
+}  // namespace jsipc
+
+namespace dom {
+
+class Blob;
+class BlobImpl;
+class BlobConstructorParams;
+class ClonedMessageData;
+class IPCTabContext;
+class PBrowserChild;
+
+class nsIContentChild : public nsISupports,
+                        public CPOWManagerGetter,
+                        public mozilla::ipc::IShmemAllocator {
+ public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONTENTCHILD_IID)
+
+  virtual bool SendPBrowserConstructor(
+      PBrowserChild* aActor, const TabId& aTabId, const TabId& aSameTabGroupAs,
+      const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+      const ContentParentId& aCpID, const bool& aIsForBrowser) = 0;
+
+  virtual mozilla::ipc::PFileDescriptorSetChild*
+  SendPFileDescriptorSetConstructor(const mozilla::ipc::FileDescriptor&) = 0;
+
+  virtual mozilla::ipc::PChildToParentStreamChild*
+  SendPChildToParentStreamConstructor(
+      mozilla::ipc::PChildToParentStreamChild*) = 0;
+
+  virtual already_AddRefed<nsIEventTarget> GetEventTargetFor(
+      TabChild* aTabChild) = 0;
+
+ protected:
+  virtual jsipc::PJavaScriptChild* AllocPJavaScriptChild();
+  virtual bool DeallocPJavaScriptChild(jsipc::PJavaScriptChild*);
+
+  virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
+                                            const TabId& aSameTabGroupAs,
+                                            const IPCTabContext& aContext,
+                                            const uint32_t& aChromeFlags,
+                                            const ContentParentId& aCpId,
+                                            const bool& aIsForBrowser);
+  virtual bool DeallocPBrowserChild(PBrowserChild*);
+
+  virtual mozilla::ipc::IPCResult RecvPBrowserConstructor(
+      PBrowserChild* aActor, const TabId& aTabId, const TabId& aSameTabGroupAs,
+      const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+      const ContentParentId& aCpID, const bool& aIsForBrowse);
+
+  virtual mozilla::ipc::PIPCBlobInputStreamChild* AllocPIPCBlobInputStreamChild(
+      const nsID& aID, const uint64_t& aSize);
+
+  virtual bool DeallocPIPCBlobInputStreamChild(
+      mozilla::ipc::PIPCBlobInputStreamChild* aActor);
+
+  virtual mozilla::ipc::PChildToParentStreamChild*
+  AllocPChildToParentStreamChild();
+
+  virtual bool DeallocPChildToParentStreamChild(
+      mozilla::ipc::PChildToParentStreamChild* aActor);
+
+  virtual mozilla::ipc::PParentToChildStreamChild*
+  AllocPParentToChildStreamChild();
+
+  virtual bool DeallocPParentToChildStreamChild(
+      mozilla::ipc::PParentToChildStreamChild* aActor);
+
+  virtual mozilla::ipc::PFileDescriptorSetChild* AllocPFileDescriptorSetChild(
+      const mozilla::ipc::FileDescriptor& aFD);
+
+  virtual bool DeallocPFileDescriptorSetChild(
+      mozilla::ipc::PFileDescriptorSetChild* aActor);
+
+  virtual mozilla::ipc::IPCResult RecvAsyncMessage(
+      const nsString& aMsg, InfallibleTArray<jsipc::CpowEntry>&& aCpows,
+      const IPC::Principal& aPrincipal, const ClonedMessageData& aData);
+
+  static already_AddRefed<nsIEventTarget> GetConstructedEventTarget(
+      const IPC::Message& aMsg);
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIContentChild, NS_ICONTENTCHILD_IID)
+
+}  // namespace dom
+}  // namespace mozilla
+
+#endif /* mozilla_dom_nsIContentChild_h */
new file mode 100644
--- /dev/null
+++ b/dom/ipc/nsIContentParent.cpp
@@ -0,0 +1,328 @@
+/* -*- 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 "nsIContentParent.h"
+
+#include "mozilla/Preferences.h"
+#include "mozilla/dom/File.h"
+#include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/ContentBridgeParent.h"
+#include "mozilla/dom/ContentProcessManager.h"
+#include "mozilla/dom/PTabContext.h"
+#include "mozilla/dom/PermissionMessageUtils.h"
+#include "mozilla/dom/ProcessMessageManager.h"
+#include "mozilla/dom/TabParent.h"
+#include "mozilla/dom/ipc/IPCBlobInputStreamParent.h"
+#include "mozilla/dom/ipc/StructuredCloneData.h"
+#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
+#include "mozilla/ipc/FileDescriptorSetParent.h"
+#include "mozilla/ipc/PFileDescriptorSetParent.h"
+#include "mozilla/ipc/PIPCBlobInputStreamParent.h"
+#include "mozilla/ipc/IPCStreamAlloc.h"
+#include "mozilla/ipc/IPCStreamDestination.h"
+#include "mozilla/ipc/IPCStreamSource.h"
+#include "mozilla/Unused.h"
+
+#include "MMPrinter.h"
+#include "nsIWebBrowserChrome.h"
+#include "nsPrintfCString.h"
+#include "xpcpublic.h"
+
+using namespace mozilla::ipc;
+using namespace mozilla::jsipc;
+
+// XXX need another bug to move this to a common header.
+#ifdef DISABLE_ASSERTS_FOR_FUZZING
+#  define ASSERT_UNLESS_FUZZING(...) \
+    do {                             \
+    } while (0)
+#else
+#  define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false, __VA_ARGS__)
+#endif
+
+namespace mozilla {
+namespace dom {
+
+nsIContentParent::nsIContentParent() {
+  mMessageManager = nsFrameMessageManager::NewProcessMessageManager(true);
+}
+
+ContentParent* nsIContentParent::AsContentParent() {
+  MOZ_ASSERT(IsContentParent());
+  return static_cast<ContentParent*>(this);
+}
+
+ContentBridgeParent* nsIContentParent::AsContentBridgeParent() {
+  MOZ_ASSERT(IsContentBridgeParent());
+  return static_cast<ContentBridgeParent*>(this);
+}
+
+PJavaScriptParent* nsIContentParent::AllocPJavaScriptParent() {
+  return NewJavaScriptParent();
+}
+
+bool nsIContentParent::DeallocPJavaScriptParent(PJavaScriptParent* aParent) {
+  ReleaseJavaScriptParent(aParent);
+  return true;
+}
+
+bool nsIContentParent::CanOpenBrowser(const IPCTabContext& aContext) {
+  // (PopupIPCTabContext lets the child process prove that it has access to
+  // the app it's trying to open.)
+  // On e10s we also allow UnsafeTabContext to allow service workers to open
+  // windows. This is enforced in MaybeInvalidTabContext.
+  if (aContext.type() != IPCTabContext::TPopupIPCTabContext &&
+      aContext.type() != IPCTabContext::TUnsafeIPCTabContext) {
+    ASSERT_UNLESS_FUZZING(
+        "Unexpected IPCTabContext type.  Aborting AllocPBrowserParent.");
+    return false;
+  }
+
+  if (aContext.type() == IPCTabContext::TPopupIPCTabContext) {
+    const PopupIPCTabContext& popupContext = aContext.get_PopupIPCTabContext();
+    if (popupContext.opener().type() != PBrowserOrId::TPBrowserParent) {
+      ASSERT_UNLESS_FUZZING(
+          "Unexpected PopupIPCTabContext type.  Aborting AllocPBrowserParent.");
+      return false;
+    }
+
+    auto opener =
+        TabParent::GetFrom(popupContext.opener().get_PBrowserParent());
+    if (!opener) {
+      ASSERT_UNLESS_FUZZING(
+          "Got null opener from child; aborting AllocPBrowserParent.");
+      return false;
+    }
+
+    // Popup windows of isMozBrowserElement frames must be isMozBrowserElement
+    // if the parent isMozBrowserElement.  Allocating a !isMozBrowserElement
+    // frame with same app ID would allow the content to access data it's not
+    // supposed to.
+    if (!popupContext.isMozBrowserElement() && opener->IsMozBrowserElement()) {
+      ASSERT_UNLESS_FUZZING(
+          "Child trying to escalate privileges!  Aborting "
+          "AllocPBrowserParent.");
+      return false;
+    }
+  }
+
+  MaybeInvalidTabContext tc(aContext);
+  if (!tc.IsValid()) {
+    NS_ERROR(nsPrintfCString("Child passed us an invalid TabContext.  (%s)  "
+                             "Aborting AllocPBrowserParent.",
+                             tc.GetInvalidReason())
+                 .get());
+    return false;
+  }
+
+  return true;
+}
+
+PBrowserParent* nsIContentParent::AllocPBrowserParent(
+    const TabId& aTabId, const TabId& aSameTabGroupAs,
+    const IPCTabContext& aContext, const uint32_t& aChromeFlags,
+    const ContentParentId& aCpId, const bool& aIsForBrowser) {
+  MOZ_ASSERT(!aSameTabGroupAs);
+
+  Unused << aCpId;
+  Unused << aIsForBrowser;
+
+  if (!CanOpenBrowser(aContext)) {
+    return nullptr;
+  }
+
+  uint32_t chromeFlags = aChromeFlags;
+  TabId openerTabId(0);
+  ContentParentId openerCpId(0);
+  if (aContext.type() == IPCTabContext::TPopupIPCTabContext) {
+    // CanOpenBrowser has ensured that the IPCTabContext is of
+    // type PopupIPCTabContext, and that the opener TabParent is
+    // reachable.
+    const PopupIPCTabContext& popupContext = aContext.get_PopupIPCTabContext();
+    auto opener =
+        TabParent::GetFrom(popupContext.opener().get_PBrowserParent());
+    openerTabId = opener->GetTabId();
+    openerCpId = opener->Manager()->ChildID();
+
+    // We must ensure that the private browsing and remoteness flags
+    // match those of the opener.
+    nsCOMPtr<nsILoadContext> loadContext = opener->GetLoadContext();
+    if (!loadContext) {
+      return nullptr;
+    }
+
+    bool isPrivate;
+    loadContext->GetUsePrivateBrowsing(&isPrivate);
+    if (isPrivate) {
+      chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
+    }
+  }
+
+  if (openerTabId > 0 ||
+      aContext.type() == IPCTabContext::TUnsafeIPCTabContext) {
+    // Creation of PBrowser triggered from grandchild process is currently
+    // broken and not supported (i.e. this code path doesn't work in
+    // ContentBridgeParent).
+    //
+    // If you're working on fixing the code path for ContentBridgeParent,
+    // remember to handle the remote frame registration below carefully as it
+    // has to be registered in parent process.
+    MOZ_ASSERT(XRE_IsParentProcess());
+    if (!XRE_IsParentProcess()) {
+      return nullptr;
+    }
+
+    // The creation of PBrowser was triggered from content process through
+    // either window.open() or service worker's openWindow().
+    // We need to register remote frame with the child generated tab id.
+    ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
+    if (!cpm->RegisterRemoteFrame(aTabId, openerCpId, openerTabId, aContext,
+                                  aCpId)) {
+      return nullptr;
+    }
+  }
+
+  // And because we're allocating a remote browser, of course the
+  // window is remote.
+  chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
+
+  MaybeInvalidTabContext tc(aContext);
+  MOZ_ASSERT(tc.IsValid());
+  TabParent* parent =
+      new TabParent(this, aTabId, tc.GetTabContext(), chromeFlags);
+
+  // We release this ref in DeallocPBrowserParent()
+  NS_ADDREF(parent);
+  return parent;
+}
+
+bool nsIContentParent::DeallocPBrowserParent(PBrowserParent* aFrame) {
+  TabParent* parent = TabParent::GetFrom(aFrame);
+  NS_RELEASE(parent);
+  return true;
+}
+
+mozilla::ipc::IPCResult nsIContentParent::RecvPBrowserConstructor(
+    PBrowserParent* actor, const TabId& tabId, const TabId& sameTabGroupAs,
+    const IPCTabContext& context, const uint32_t& chromeFlags,
+    const ContentParentId& cpId, const bool& isForBrowser) {
+  TabParent* parent = TabParent::GetFrom(actor);
+  // When enabling input event prioritization, input events may preempt other
+  // normal priority IPC messages. To prevent the input events preempt
+  // PBrowserConstructor, we use an IPC 'RemoteIsReadyToHandleInputEvents' to
+  // notify parent that TabChild is created. In this case, PBrowser is initiated
+  // from content so that we can set TabParent as ready to handle input events.
+  parent->SetReadyToHandleInputEvents();
+  return IPC_OK();
+}
+
+PIPCBlobInputStreamParent* nsIContentParent::AllocPIPCBlobInputStreamParent(
+    const nsID& aID, const uint64_t& aSize) {
+  MOZ_CRASH("PIPCBlobInputStreamParent actors should be manually constructed!");
+  return nullptr;
+}
+
+bool nsIContentParent::DeallocPIPCBlobInputStreamParent(
+    PIPCBlobInputStreamParent* aActor) {
+  RefPtr<IPCBlobInputStreamParent> actor =
+      dont_AddRef(static_cast<IPCBlobInputStreamParent*>(aActor));
+  return true;
+}
+
+mozilla::ipc::IPCResult nsIContentParent::RecvSyncMessage(
+    const nsString& aMsg, const ClonedMessageData& aData,
+    InfallibleTArray<CpowEntry>&& aCpows, const IPC::Principal& aPrincipal,
+    nsTArray<ipc::StructuredCloneData>* aRetvals) {
+  AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(
+      "nsIContentParent::RecvSyncMessage", OTHER, aMsg);
+  MMPrinter::Print("nsIContentParent::RecvSyncMessage", aMsg, aData);
+
+  CrossProcessCpowHolder cpows(this, aCpows);
+  RefPtr<nsFrameMessageManager> ppm = mMessageManager;
+  if (ppm) {
+    ipc::StructuredCloneData data;
+    ipc::UnpackClonedMessageDataForParent(aData, data);
+
+    ppm->ReceiveMessage(ppm, nullptr, aMsg, true, &data, &cpows, aPrincipal,
+                        aRetvals, IgnoreErrors());
+  }
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult nsIContentParent::RecvRpcMessage(
+    const nsString& aMsg, const ClonedMessageData& aData,
+    InfallibleTArray<CpowEntry>&& aCpows, const IPC::Principal& aPrincipal,
+    nsTArray<ipc::StructuredCloneData>* aRetvals) {
+  AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING("nsIContentParent::RecvRpcMessage",
+                                             OTHER, aMsg);
+  MMPrinter::Print("nsIContentParent::RecvRpcMessage", aMsg, aData);
+
+  CrossProcessCpowHolder cpows(this, aCpows);
+  RefPtr<nsFrameMessageManager> ppm = mMessageManager;
+  if (ppm) {
+    ipc::StructuredCloneData data;
+    ipc::UnpackClonedMessageDataForParent(aData, data);
+
+    ppm->ReceiveMessage(ppm, nullptr, aMsg, true, &data, &cpows, aPrincipal,
+                        aRetvals, IgnoreErrors());
+  }
+  return IPC_OK();
+}
+
+PFileDescriptorSetParent* nsIContentParent::AllocPFileDescriptorSetParent(
+    const FileDescriptor& aFD) {
+  return new FileDescriptorSetParent(aFD);
+}
+
+bool nsIContentParent::DeallocPFileDescriptorSetParent(
+    PFileDescriptorSetParent* aActor) {
+  delete static_cast<FileDescriptorSetParent*>(aActor);
+  return true;
+}
+
+PChildToParentStreamParent*
+nsIContentParent::AllocPChildToParentStreamParent() {
+  return mozilla::ipc::AllocPChildToParentStreamParent();
+}
+
+bool nsIContentParent::DeallocPChildToParentStreamParent(
+    PChildToParentStreamParent* aActor) {
+  delete aActor;
+  return true;
+}
+
+PParentToChildStreamParent*
+nsIContentParent::AllocPParentToChildStreamParent() {
+  MOZ_CRASH("PParentToChildStreamChild actors should be manually constructed!");
+}
+
+bool nsIContentParent::DeallocPParentToChildStreamParent(
+    PParentToChildStreamParent* aActor) {
+  delete aActor;
+  return true;
+}
+
+mozilla::ipc::IPCResult nsIContentParent::RecvAsyncMessage(
+    const nsString& aMsg, InfallibleTArray<CpowEntry>&& aCpows,
+    const IPC::Principal& aPrincipal, const ClonedMessageData& aData) {
+  AUTO_PROFILER_LABEL_DYNAMIC_LOSSY_NSSTRING(
+      "nsIContentParent::RecvAsyncMessage", OTHER, aMsg);
+  MMPrinter::Print("nsIContentParent::RecvAsyncMessage", aMsg, aData);
+
+  CrossProcessCpowHolder cpows(this, aCpows);
+  RefPtr<nsFrameMessageManager> ppm = mMessageManager;
+  if (ppm) {
+    ipc::StructuredCloneData data;
+    ipc::UnpackClonedMessageDataForParent(aData, data);
+
+    ppm->ReceiveMessage(ppm, nullptr, aMsg, false, &data, &cpows, aPrincipal,
+                        nullptr, IgnoreErrors());
+  }
+  return IPC_OK();
+}
+
+}  // namespace dom
+}  // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/ipc/nsIContentParent.h
@@ -0,0 +1,171 @@
+/* -*- 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_nsIContentParent_h
+#define mozilla_dom_nsIContentParent_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/dom/ipc/IdType.h"
+#include "mozilla/ipc/ProtocolUtils.h"
+#include "mozilla/ipc/PChildToParentStreamParent.h"
+#include "mozilla/ipc/PParentToChildStreamParent.h"
+
+#include "nsFrameMessageManager.h"
+#include "nsISupports.h"
+#include "mozilla/dom/CPOWManagerGetter.h"
+
+#define NS_ICONTENTPARENT_IID                        \
+  {                                                  \
+    0xeeec9ebf, 0x8ecf, 0x4e38, {                    \
+      0x81, 0xda, 0xb7, 0x34, 0x13, 0x7e, 0xac, 0xf3 \
+    }                                                \
+  }
+
+namespace IPC {
+class Principal;
+}  // namespace IPC
+
+namespace mozilla {
+
+namespace jsipc {
+class PJavaScriptParent;
+class CpowEntry;
+}  // namespace jsipc
+
+namespace ipc {
+class PFileDescriptorSetParent;
+class PChildToParentStreamParent;
+class PParentToChildStreamParent;
+class PIPCBlobInputStreamParent;
+}  // namespace ipc
+
+namespace dom {
+
+class Blob;
+class BlobConstructorParams;
+class BlobImpl;
+class ProcessMessageManager;
+class ContentParent;
+class ContentBridgeParent;
+class IPCTabContext;
+class PBrowserParent;
+
+class nsIContentParent : public nsISupports,
+                         public mozilla::dom::ipc::MessageManagerCallback,
+                         public CPOWManagerGetter,
+                         public mozilla::ipc::IShmemAllocator {
+ public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONTENTPARENT_IID)
+
+  nsIContentParent();
+
+  virtual ContentParentId ChildID() const = 0;
+  virtual bool IsForBrowser() const = 0;
+  virtual bool IsForJSPlugin() const = 0;
+
+  virtual mozilla::ipc::PIPCBlobInputStreamParent*
+  SendPIPCBlobInputStreamConstructor(
+      mozilla::ipc::PIPCBlobInputStreamParent* aActor, const nsID& aID,
+      const uint64_t& aSize) = 0;
+
+  MOZ_MUST_USE virtual PBrowserParent* SendPBrowserConstructor(
+      PBrowserParent* actor, const TabId& aTabId, const TabId& aSameTabGroupAs,
+      const IPCTabContext& context, const uint32_t& chromeFlags,
+      const ContentParentId& aCpId, const bool& aIsForBrowser) = 0;
+
+  virtual mozilla::ipc::PFileDescriptorSetParent*
+  SendPFileDescriptorSetConstructor(const mozilla::ipc::FileDescriptor&) = 0;
+
+  virtual bool IsContentParent() const { return false; }
+
+  ContentParent* AsContentParent();
+
+  virtual bool IsContentBridgeParent() const { return false; }
+
+  ContentBridgeParent* AsContentBridgeParent();
+
+  mozilla::dom::ProcessMessageManager* GetMessageManager() const {
+    return mMessageManager;
+  }
+
+  virtual bool SendActivate(PBrowserParent* aTab) = 0;
+
+  virtual bool SendDeactivate(PBrowserParent* aTab) = 0;
+
+  virtual int32_t Pid() const = 0;
+
+  virtual mozilla::ipc::PParentToChildStreamParent*
+  SendPParentToChildStreamConstructor(
+      mozilla::ipc::PParentToChildStreamParent*) = 0;
+
+ protected:  // methods
+  bool CanOpenBrowser(const IPCTabContext& aContext);
+
+ protected:  // IPDL methods
+  virtual mozilla::jsipc::PJavaScriptParent* AllocPJavaScriptParent();
+  virtual bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*);
+
+  virtual PBrowserParent* AllocPBrowserParent(const TabId& aTabId,
+                                              const TabId& aSameTabGroupsAs,
+                                              const IPCTabContext& aContext,
+                                              const uint32_t& aChromeFlags,
+                                              const ContentParentId& aCpId,
+                                              const bool& aIsForBrowser);
+  virtual bool DeallocPBrowserParent(PBrowserParent* frame);
+
+  virtual mozilla::ipc::IPCResult RecvPBrowserConstructor(
+      PBrowserParent* actor, const TabId& tabId, const TabId& sameTabGroupAs,
+      const IPCTabContext& context, const uint32_t& chromeFlags,
+      const ContentParentId& cpId, const bool& isForBrowser);
+
+  virtual mozilla::ipc::PIPCBlobInputStreamParent*
+  AllocPIPCBlobInputStreamParent(const nsID& aID, const uint64_t& aSize);
+
+  virtual bool DeallocPIPCBlobInputStreamParent(
+      mozilla::ipc::PIPCBlobInputStreamParent* aActor);
+
+  virtual mozilla::ipc::PFileDescriptorSetParent* AllocPFileDescriptorSetParent(
+      const mozilla::ipc::FileDescriptor& aFD);
+
+  virtual bool DeallocPFileDescriptorSetParent(
+      mozilla::ipc::PFileDescriptorSetParent* aActor);
+
+  virtual mozilla::ipc::PChildToParentStreamParent*
+  AllocPChildToParentStreamParent();
+
+  virtual bool DeallocPChildToParentStreamParent(
+      mozilla::ipc::PChildToParentStreamParent* aActor);
+
+  virtual mozilla::ipc::PParentToChildStreamParent*
+  AllocPParentToChildStreamParent();
+
+  virtual bool DeallocPParentToChildStreamParent(
+      mozilla::ipc::PParentToChildStreamParent* aActor);
+
+  virtual mozilla::ipc::IPCResult RecvSyncMessage(
+      const nsString& aMsg, const ClonedMessageData& aData,
+      InfallibleTArray<jsipc::CpowEntry>&& aCpows,
+      const IPC::Principal& aPrincipal,
+      nsTArray<ipc::StructuredCloneData>* aRetvals);
+  virtual mozilla::ipc::IPCResult RecvRpcMessage(
+      const nsString& aMsg, const ClonedMessageData& aData,
+      InfallibleTArray<jsipc::CpowEntry>&& aCpows,
+      const IPC::Principal& aPrincipal,
+      nsTArray<ipc::StructuredCloneData>* aRetvals);
+  virtual mozilla::ipc::IPCResult RecvAsyncMessage(
+      const nsString& aMsg, InfallibleTArray<jsipc::CpowEntry>&& aCpows,
+      const IPC::Principal& aPrincipal, const ClonedMessageData& aData);
+
+ protected:  // members
+  RefPtr<mozilla::dom::ProcessMessageManager> mMessageManager;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIContentParent, NS_ICONTENTPARENT_IID)
+
+}  // namespace dom
+}  // namespace mozilla
+
+#endif /* mozilla_dom_nsIContentParent_h */
--- a/dom/presentation/PresentationSessionInfo.h
+++ b/dom/presentation/PresentationSessionInfo.h
@@ -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/. */
 
 #ifndef mozilla_dom_PresentationSessionInfo_h
 #define mozilla_dom_PresentationSessionInfo_h
 
 #include "base/process.h"
-#include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/nsIContentParent.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseNativeHandler.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/RefPtr.h"
 #include "nsCOMPtr.h"
 #include "nsINamed.h"
 #include "nsINetworkInfoService.h"
 #include "nsIPresentationControlChannel.h"
@@ -254,15 +254,15 @@ class PresentationPresentingInfo final :
   RefPtr<PresentationResponderLoadingCallback> mLoadingCallback;
   nsCOMPtr<nsITimer> mTimer;
   nsCOMPtr<nsIPresentationChannelDescription> mRequesterDescription;
   nsTArray<nsString> mPendingCandidates;
   RefPtr<Promise> mPromise;
 
   // The content parent communicating with the content process which the OOP
   // receiver page belongs to.
-  RefPtr<ContentParent> mContentParent;
+  nsCOMPtr<nsIContentParent> mContentParent;
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // mozilla_dom_PresentationSessionInfo_h
--- a/ipc/chromium/src/chrome/common/ipc_message_utils.h
+++ b/ipc/chromium/src/chrome/common/ipc_message_utils.h
@@ -14,19 +14,16 @@
 #include "base/file_path.h"
 #include "base/string_util.h"
 #include "base/string16.h"
 #include "base/time.h"
 
 #if defined(OS_POSIX)
 #  include "chrome/common/file_descriptor_set_posix.h"
 #endif
-#if defined(OS_WIN)
-#  include "windows.h"
-#endif
 #include "chrome/common/ipc_message.h"
 
 template <typename T>
 class RefPtr;
 template <typename T>
 class nsCOMPtr;
 
 namespace IPC {
--- a/ipc/glue/BackgroundImpl.cpp
+++ b/ipc/glue/BackgroundImpl.cpp
@@ -756,17 +756,17 @@ intptr_t ParentImpl::GetRawContentParent
   auto actor = static_cast<ParentImpl*>(aBackgroundActor);
   if (actor->mActorDestroyed) {
     MOZ_ASSERT(false,
                "GetRawContentParentForComparison called after ActorDestroy was "
                "called!");
     return intptr_t(-1);
   }
 
-  return intptr_t(static_cast<ContentParent*>(actor->mContent.get()));
+  return intptr_t(static_cast<nsIContentParent*>(actor->mContent.get()));
 }
 
 // static
 uint64_t ParentImpl::GetChildID(PBackgroundParent* aBackgroundActor) {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aBackgroundActor);
 
   auto actor = static_cast<ParentImpl*>(aBackgroundActor);
--- a/ipc/glue/FileDescriptorSetChild.h
+++ b/ipc/glue/FileDescriptorSetChild.h
@@ -11,28 +11,28 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/ipc/PFileDescriptorSetChild.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 
 namespace dom {
 
-class ContentChild;
+class nsIContentChild;
 
 }  // namespace dom
 
 namespace ipc {
 
 class BackgroundChildImpl;
 class FileDescriptor;
 
 class FileDescriptorSetChild final : public PFileDescriptorSetChild {
   friend class BackgroundChildImpl;
-  friend class mozilla::dom::ContentChild;
+  friend class mozilla::dom::nsIContentChild;
   friend class PFileDescriptorSetChild;
 
   nsTArray<FileDescriptor> mFileDescriptors;
 
  public:
   void ForgetFileDescriptors(nsTArray<FileDescriptor>& aFileDescriptors);
 
  private:
--- a/ipc/glue/FileDescriptorSetParent.h
+++ b/ipc/glue/FileDescriptorSetParent.h
@@ -11,28 +11,28 @@
 #include "mozilla/Attributes.h"
 #include "mozilla/ipc/PFileDescriptorSetParent.h"
 #include "nsTArray.h"
 
 namespace mozilla {
 
 namespace dom {
 
-class ContentParent;
+class nsIContentParent;
 
 }  // namespace dom
 
 namespace ipc {
 
 class BackgroundParentImpl;
 class FileDescriptor;
 
 class FileDescriptorSetParent final : public PFileDescriptorSetParent {
   friend class BackgroundParentImpl;
-  friend class mozilla::dom::ContentParent;
+  friend class mozilla::dom::nsIContentParent;
   friend class PFileDescriptorSetParent;
 
   nsTArray<FileDescriptor> mFileDescriptors;
 
  public:
   void ForgetFileDescriptors(nsTArray<FileDescriptor>& aFileDescriptors);
 
  private:
--- a/ipc/glue/IPCStreamChild.cpp
+++ b/ipc/glue/IPCStreamChild.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 "IPCStreamDestination.h"
 #include "IPCStreamSource.h"
 
 #include "mozilla/Unused.h"
-#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/nsIContentChild.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "mozilla/ipc/PChildToParentStreamChild.h"
 #include "mozilla/ipc/PParentToChildStreamChild.h"
 
 namespace mozilla {
 namespace ipc {
 
 // Child to Parent implementation
@@ -62,17 +62,17 @@ class IPCStreamSourceChild final : publi
  private:
   explicit IPCStreamSourceChild(nsIAsyncInputStream* aInputStream)
       : IPCStreamSource(aInputStream) {}
 };
 
 }  // anonymous namespace
 
 /* static */ PChildToParentStreamChild* IPCStreamSource::Create(
-    nsIAsyncInputStream* aInputStream, dom::ContentChild* aManager) {
+    nsIAsyncInputStream* aInputStream, dom::nsIContentChild* aManager) {
   MOZ_ASSERT(aInputStream);
   MOZ_ASSERT(aManager);
 
   // PContent can only be used on the main thread
   MOZ_ASSERT(NS_IsMainThread());
 
   IPCStreamSourceChild* source = IPCStreamSourceChild::Create(aInputStream);
   if (!source) {
--- a/ipc/glue/IPCStreamParent.cpp
+++ b/ipc/glue/IPCStreamParent.cpp
@@ -1,16 +1,16 @@
 /* -*- 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 "IPCStreamDestination.h"
-#include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/nsIContentParent.h"
 #include "mozilla/ipc/PBackgroundParent.h"
 #include "mozilla/ipc/PChildToParentStreamParent.h"
 #include "mozilla/ipc/PParentToChildStreamParent.h"
 #include "mozilla/Unused.h"
 
 namespace mozilla {
 namespace ipc {
 
@@ -60,17 +60,17 @@ class IPCStreamSourceParent final : publ
  private:
   explicit IPCStreamSourceParent(nsIAsyncInputStream* aInputStream)
       : IPCStreamSource(aInputStream) {}
 };
 
 }  // anonymous namespace
 
 /* static */ PParentToChildStreamParent* IPCStreamSource::Create(
-    nsIAsyncInputStream* aInputStream, dom::ContentParent* aManager) {
+    nsIAsyncInputStream* aInputStream, dom::nsIContentParent* aManager) {
   MOZ_ASSERT(aInputStream);
   MOZ_ASSERT(aManager);
 
   // PContent can only be used on the main thread
   MOZ_ASSERT(NS_IsMainThread());
 
   IPCStreamSourceParent* source = IPCStreamSourceParent::Create(aInputStream);
   if (!source) {
--- a/ipc/glue/IPCStreamSource.h
+++ b/ipc/glue/IPCStreamSource.h
@@ -10,18 +10,18 @@
 #include "mozilla/AlreadyAddRefed.h"
 #include "mozilla/dom/WorkerRef.h"
 
 class nsIAsyncInputStream;
 
 namespace mozilla {
 
 namespace dom {
-class ContentChild;
-class ContentParent;
+class nsIContentChild;
+class nsIContentParent;
 }  // namespace dom
 
 namespace wr {
 struct ByteBuffer;
 }  // namespace wr
 
 namespace ipc {
 
@@ -56,29 +56,29 @@ class PParentToChildStreamParent;
 // In general you should probably use the AutoIPCStreamSource RAII class
 // defined in InputStreamUtils.h instead of using IPCStreamSource directly.
 class IPCStreamSource {
  public:
   // Create a IPCStreamSource using a PContent IPC manager on the
   // main thread.  This can return nullptr if the provided stream is
   // blocking.
   static PChildToParentStreamChild* Create(nsIAsyncInputStream* aInputStream,
-                                           dom::ContentChild* aManager);
+                                           dom::nsIContentChild* aManager);
 
   // Create a IPCStreamSource using a PBackground IPC manager on the
   // main thread or a Worker thread.  This can return nullptr if the provided
   // stream is blocking or if the Worker thread is already shutting down.
   static PChildToParentStreamChild* Create(nsIAsyncInputStream* aInputStream,
                                            PBackgroundChild* aManager);
 
   // Create a IPCStreamSource using a PContent IPC manager on the
   // main thread.  This can return nullptr if the provided stream is
   // blocking.
   static PParentToChildStreamParent* Create(nsIAsyncInputStream* aInputStream,
-                                            dom::ContentParent* aManager);
+                                            dom::nsIContentParent* aManager);
 
   // Create a IPCStreamSource using a PBackground IPC manager on the
   // main thread or a Worker thread.  This can return nullptr if the provided
   // stream is blocking or if the Worker thread is already shutting down.
   static PParentToChildStreamParent* Create(nsIAsyncInputStream* aInputStream,
                                             PBackgroundParent* aManager);
 
   static IPCStreamSource* Cast(PChildToParentStreamChild* aActor);
--- a/ipc/glue/IPCStreamUtils.cpp
+++ b/ipc/glue/IPCStreamUtils.cpp
@@ -326,17 +326,17 @@ AutoIPCStream::~AutoIPCStream() {
   if (mValue && IsSet()) {
     ActivateAndCleanupIPCStream(*mValue, mTaken, mDelayedStart);
   } else {
     ActivateAndCleanupIPCStream(*mOptionalValue, mTaken, mDelayedStart);
   }
 }
 
 bool AutoIPCStream::Serialize(nsIInputStream* aStream,
-                              dom::ContentChild* aManager) {
+                              dom::nsIContentChild* aManager) {
   MOZ_ASSERT(aStream || !mValue);
   MOZ_ASSERT(aManager);
   MOZ_ASSERT(mValue || mOptionalValue);
   MOZ_ASSERT(!mTaken);
   MOZ_ASSERT(!IsSet());
 
   // If NormalizeOptionalValue returns false, we don't have to proceed.
   if (!NormalizeOptionalValue(aStream, mValue, mOptionalValue)) {
@@ -368,17 +368,17 @@ bool AutoIPCStream::Serialize(nsIInputSt
                                  mDelayedStart)) {
     MOZ_CRASH("IPCStream creation failed!");
   }
 
   return true;
 }
 
 bool AutoIPCStream::Serialize(nsIInputStream* aStream,
-                              dom::ContentParent* aManager) {
+                              dom::nsIContentParent* aManager) {
   MOZ_ASSERT(aStream || !mValue);
   MOZ_ASSERT(aManager);
   MOZ_ASSERT(mValue || mOptionalValue);
   MOZ_ASSERT(!mTaken);
   MOZ_ASSERT(!IsSet());
 
   // If NormalizeOptionalValue returns false, we don't have to proceed.
   if (!NormalizeOptionalValue(aStream, mValue, mOptionalValue)) {
--- a/ipc/glue/IPCStreamUtils.h
+++ b/ipc/glue/IPCStreamUtils.h
@@ -9,18 +9,18 @@
 
 #include "mozilla/ipc/IPCStream.h"
 #include "nsCOMPtr.h"
 #include "nsIInputStream.h"
 
 namespace mozilla {
 
 namespace dom {
-class ContentChild;
-class ContentParent;
+class nsIContentChild;
+class nsIContentParent;
 }  // namespace dom
 
 namespace ipc {
 
 class PBackgroundChild;
 class PBackgroundParent;
 
 // Deserialize an IPCStream received from an actor call.  These methods
@@ -143,26 +143,26 @@ class AutoIPCStream final {
   // or TakeOptionalValue can be used.
   explicit AutoIPCStream(Maybe<IPCStream>& aTarget, bool aDelayedStart = false);
 
   ~AutoIPCStream();
 
   // Serialize the input stream or create a SendStream actor using the PContent
   // manager.  If neither of these succeed, then crash.  This should only be
   // used on the main thread.
-  bool Serialize(nsIInputStream* aStream, dom::ContentChild* aManager);
+  bool Serialize(nsIInputStream* aStream, dom::nsIContentChild* aManager);
 
   // Serialize the input stream or create a SendStream actor using the
   // PBackground manager.  If neither of these succeed, then crash.  This can
   // be called on the main thread or Worker threads.
   bool Serialize(nsIInputStream* aStream, PBackgroundChild* aManager);
 
   // Serialize the input stream.
   MOZ_MUST_USE bool Serialize(nsIInputStream* aStream,
-                              dom::ContentParent* aManager);
+                              dom::nsIContentParent* aManager);
 
   // Serialize the input stream.
   MOZ_MUST_USE bool Serialize(nsIInputStream* aStream,
                               PBackgroundParent* aManager);
 
   // Get the IPCStream as a non-optional value.  This will
   // assert if a stream has not been serialized or if it has already been taken.
   // This should only be called if the value is being, or has already been, sent
--- a/ipc/glue/InputStreamUtils.cpp
+++ b/ipc/glue/InputStreamUtils.cpp
@@ -115,65 +115,65 @@ void SerializeInputStreamAsPipeInternal(
       aDelayedStart, IPCStreamSource::Create(asyncStream, aManager), length);
 }
 
 }  // namespace
 
 void InputStreamHelper::SerializeInputStream(
     nsIInputStream* aInputStream, InputStreamParams& aParams,
     nsTArray<FileDescriptor>& aFileDescriptors, bool aDelayedStart,
-    uint32_t aMaxSize, uint32_t* aSizeUsed, ContentChild* aManager) {
+    uint32_t aMaxSize, uint32_t* aSizeUsed, nsIContentChild* aManager) {
   SerializeInputStreamInternal(aInputStream, aParams, aFileDescriptors,
                                aDelayedStart, aMaxSize, aSizeUsed, aManager);
 }
 
 void InputStreamHelper::SerializeInputStream(
     nsIInputStream* aInputStream, InputStreamParams& aParams,
     nsTArray<FileDescriptor>& aFileDescriptors, bool aDelayedStart,
     uint32_t aMaxSize, uint32_t* aSizeUsed, PBackgroundChild* aManager) {
   SerializeInputStreamInternal(aInputStream, aParams, aFileDescriptors,
                                aDelayedStart, aMaxSize, aSizeUsed, aManager);
 }
 
 void InputStreamHelper::SerializeInputStream(
     nsIInputStream* aInputStream, InputStreamParams& aParams,
     nsTArray<FileDescriptor>& aFileDescriptors, bool aDelayedStart,
-    uint32_t aMaxSize, uint32_t* aSizeUsed, ContentParent* aManager) {
+    uint32_t aMaxSize, uint32_t* aSizeUsed, nsIContentParent* aManager) {
   SerializeInputStreamInternal(aInputStream, aParams, aFileDescriptors,
                                aDelayedStart, aMaxSize, aSizeUsed, aManager);
 }
 
 void InputStreamHelper::SerializeInputStream(
     nsIInputStream* aInputStream, InputStreamParams& aParams,
     nsTArray<FileDescriptor>& aFileDescriptors, bool aDelayedStart,
     uint32_t aMaxSize, uint32_t* aSizeUsed, PBackgroundParent* aManager) {
   SerializeInputStreamInternal(aInputStream, aParams, aFileDescriptors,
                                aDelayedStart, aMaxSize, aSizeUsed, aManager);
 }
 
 void InputStreamHelper::SerializeInputStreamAsPipe(nsIInputStream* aInputStream,
                                                    InputStreamParams& aParams,
                                                    bool aDelayedStart,
-                                                   ContentChild* aManager) {
+                                                   nsIContentChild* aManager) {
   SerializeInputStreamAsPipeInternal(aInputStream, aParams, aDelayedStart,
                                      aManager);
 }
 
 void InputStreamHelper::SerializeInputStreamAsPipe(nsIInputStream* aInputStream,
                                                    InputStreamParams& aParams,
                                                    bool aDelayedStart,
                                                    PBackgroundChild* aManager) {
   SerializeInputStreamAsPipeInternal(aInputStream, aParams, aDelayedStart,
                                      aManager);
 }
 
 void InputStreamHelper::SerializeInputStreamAsPipe(nsIInputStream* aInputStream,
                                                    InputStreamParams& aParams,
                                                    bool aDelayedStart,
-                                                   ContentParent* aManager) {
+                                                   nsIContentParent* aManager) {
   SerializeInputStreamAsPipeInternal(aInputStream, aParams, aDelayedStart,
                                      aManager);
 }
 
 void InputStreamHelper::SerializeInputStreamAsPipe(
     nsIInputStream* aInputStream, InputStreamParams& aParams,
     bool aDelayedStart, PBackgroundParent* aManager) {
   SerializeInputStreamAsPipeInternal(aInputStream, aParams, aDelayedStart,
--- a/ipc/glue/InputStreamUtils.h
+++ b/ipc/glue/InputStreamUtils.h
@@ -29,53 +29,53 @@ class InputStreamHelper {
   // pipe in chunks. This sending can start immediatelly or at the first read
   // based on the value of |aDelayedStart|. The IPC message size is returned
   // into |aSizeUsed|.
   static void SerializeInputStream(nsIInputStream* aInputStream,
                                    InputStreamParams& aParams,
                                    nsTArray<FileDescriptor>& aFileDescriptors,
                                    bool aDelayedStart, uint32_t aMaxSize,
                                    uint32_t* aSizeUsed,
-                                   mozilla::dom::ContentChild* aManager);
+                                   mozilla::dom::nsIContentChild* aManager);
 
   static void SerializeInputStream(nsIInputStream* aInputStream,
                                    InputStreamParams& aParams,
                                    nsTArray<FileDescriptor>& aFileDescriptors,
                                    bool aDelayedStart, uint32_t aMaxSize,
                                    uint32_t* aSizeUsed,
                                    PBackgroundChild* aManager);
 
   static void SerializeInputStream(nsIInputStream* aInputStream,
                                    InputStreamParams& aParams,
                                    nsTArray<FileDescriptor>& aFileDescriptors,
                                    bool aDelayedStart, uint32_t aMaxSize,
                                    uint32_t* aSizeUsed,
-                                   mozilla::dom::ContentParent* aManager);
+                                   mozilla::dom::nsIContentParent* aManager);
 
   static void SerializeInputStream(nsIInputStream* aInputStream,
                                    InputStreamParams& aParams,
                                    nsTArray<FileDescriptor>& aFileDescriptors,
                                    bool aDelayedStart, uint32_t aMaxSize,
                                    uint32_t* aSizeUsed,
                                    PBackgroundParent* aManager);
 
   // When a stream wants to serialize itself as IPCRemoteStream, it uses one of
   // these methods.
   static void SerializeInputStreamAsPipe(
       nsIInputStream* aInputStream, InputStreamParams& aParams,
-      bool aDelayedStart, mozilla::dom::ContentChild* aManager);
+      bool aDelayedStart, mozilla::dom::nsIContentChild* aManager);
 
   static void SerializeInputStreamAsPipe(nsIInputStream* aInputStream,
                                          InputStreamParams& aParams,
                                          bool aDelayedStart,
                                          PBackgroundChild* aManager);
 
   static void SerializeInputStreamAsPipe(
       nsIInputStream* aInputStream, InputStreamParams& aParams,
-      bool aDelayedStart, mozilla::dom::ContentParent* aManager);
+      bool aDelayedStart, mozilla::dom::nsIContentParent* aManager);
 
   static void SerializeInputStreamAsPipe(nsIInputStream* aInputStream,
                                          InputStreamParams& aParams,
                                          bool aDelayedStart,
                                          PBackgroundParent* aManager);
 
   // After the sending of the inputStream into the IPC pipe, some of the
   // InputStreamParams data struct needs to be activated (IPCRemoteStream).
--- a/ipc/glue/PChildToParentStream.ipdl
+++ b/ipc/glue/PChildToParentStream.ipdl
@@ -1,27 +1,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 protocol PBackground;
 include protocol PContent;
+include protocol PContentBridge;
 
 include "mozilla/layers/WebRenderMessageUtils.h";
 
 using mozilla::wr::ByteBuffer from "mozilla/webrender/WebRenderTypes.h";
 
 namespace mozilla {
 namespace ipc {
 
 // This is protocol is the opposite of PParentToChildStream. Please keep these
 // protocols in sync.
 protocol PChildToParentStream
 {
-  manager PBackground or PContent;
+  manager PBackground or PContent or PContentBridge;
 
 parent:
   async Buffer(ByteBuffer aBuffer);
   async Close(nsresult aRv);
 
 child:
   // The remote stream can be used in 2 ways: it can start receiving data
   // immediately after the creation of the child actor, or it can wait until
--- a/ipc/glue/PFileDescriptorSet.ipdl
+++ b/ipc/glue/PFileDescriptorSet.ipdl
@@ -1,21 +1,22 @@
 /* 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 PContent;
+include protocol PContentBridge;
 
 namespace mozilla {
 namespace ipc {
 
 protocol PFileDescriptorSet
 {
-  manager PBackground or PContent;
+  manager PBackground or PContent or PContentBridge;
 
 both:
   async AddFileDescriptor(FileDescriptor fd);
 
   async __delete__();
 };
 
 } // namespace ipc
--- a/ipc/glue/PParentToChildStream.ipdl
+++ b/ipc/glue/PParentToChildStream.ipdl
@@ -1,27 +1,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 protocol PBackground;
 include protocol PContent;
+include protocol PContentBridge;
 
 include "mozilla/layers/WebRenderMessageUtils.h";
 
 using mozilla::wr::ByteBuffer from "mozilla/webrender/WebRenderTypes.h";
 
 namespace mozilla {
 namespace ipc {
 
 // This is protocol is the opposite of PChildToParentStream. Please keep these
 // protocols in sync.
 protocol PParentToChildStream
 {
-  manager PBackground or PContent;
+  manager PBackground or PContent or PContentBridge;
 
 child:
   async Buffer(ByteBuffer aBuffer);
   async Close(nsresult aRv);
 
 parent:
   // The remote stream can be used in 2 ways: it can start receiving data
   // immediately after the creation of the child actor, or it can wait until
--- a/ipc/glue/nsIIPCSerializableInputStream.h
+++ b/ipc/glue/nsIIPCSerializableInputStream.h
@@ -11,18 +11,18 @@
 #include "mozilla/Maybe.h"
 #include "nsISupports.h"
 #include "nsTArrayForwardDeclare.h"
 
 namespace mozilla {
 
 namespace dom {
 
-class ContentChild;
-class ContentParent;
+class nsIContentChild;
+class nsIContentParent;
 
 }  // namespace dom
 
 namespace ipc {
 
 class FileDescriptor;
 class InputStreamParams;
 class PBackgroundChild;
@@ -44,29 +44,29 @@ class NS_NO_VTABLE nsIIPCSerializableInp
   typedef nsTArray<mozilla::ipc::FileDescriptor> FileDescriptorArray;
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IIPCSERIALIZABLEINPUTSTREAM_IID)
 
   virtual void Serialize(mozilla::ipc::InputStreamParams& aParams,
                          FileDescriptorArray& aFileDescriptors,
                          bool aDelayedStart, uint32_t aMaxSize,
                          uint32_t* aSizeUsed,
-                         mozilla::dom::ContentChild* aManager) = 0;
+                         mozilla::dom::nsIContentChild* aManager) = 0;
 
   virtual void Serialize(mozilla::ipc::InputStreamParams& aParams,
                          FileDescriptorArray& aFileDescriptors,
                          bool aDelayedStart, uint32_t aMaxSize,
                          uint32_t* aSizeUsed,
                          mozilla::ipc::PBackgroundChild* aManager) = 0;
 
   virtual void Serialize(mozilla::ipc::InputStreamParams& aParams,
                          FileDescriptorArray& aFileDescriptors,
                          bool aDelayedStart, uint32_t aMaxSize,
                          uint32_t* aSizeUsed,
-                         mozilla::dom::ContentParent* aManager) = 0;
+                         mozilla::dom::nsIContentParent* aManager) = 0;
 
   virtual void Serialize(mozilla::ipc::InputStreamParams& aParams,
                          FileDescriptorArray& aFileDescriptors,
                          bool aDelayedStart, uint32_t aMaxSize,
                          uint32_t* aSizeUsed,
                          mozilla::ipc::PBackgroundParent* aManager) = 0;
 
   virtual bool Deserialize(const mozilla::ipc::InputStreamParams& aParams,
@@ -74,39 +74,39 @@ class NS_NO_VTABLE nsIIPCSerializableInp
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIIPCSerializableInputStream,
                               NS_IIPCSERIALIZABLEINPUTSTREAM_IID)
 
 #define NS_DECL_NSIIPCSERIALIZABLEINPUTSTREAM                             \
   virtual void Serialize(mozilla::ipc::InputStreamParams&,                \
                          FileDescriptorArray&, bool, uint32_t, uint32_t*, \
-                         mozilla::dom::ContentChild*) override;        \
+                         mozilla::dom::nsIContentChild*) override;        \
                                                                           \
   virtual void Serialize(mozilla::ipc::InputStreamParams&,                \
                          FileDescriptorArray&, bool, uint32_t, uint32_t*, \
                          mozilla::ipc::PBackgroundChild*) override;       \
                                                                           \
   virtual void Serialize(mozilla::ipc::InputStreamParams&,                \
                          FileDescriptorArray&, bool, uint32_t, uint32_t*, \
-                         mozilla::dom::ContentParent*) override;       \
+                         mozilla::dom::nsIContentParent*) override;       \
                                                                           \
   virtual void Serialize(mozilla::ipc::InputStreamParams&,                \
                          FileDescriptorArray&, bool, uint32_t, uint32_t*, \
                          mozilla::ipc::PBackgroundParent*) override;      \
                                                                           \
   virtual bool Deserialize(const mozilla::ipc::InputStreamParams&,        \
                            const FileDescriptorArray&) override;
 
 #define NS_FORWARD_NSIIPCSERIALIZABLEINPUTSTREAM(_to)                          \
   virtual void Serialize(mozilla::ipc::InputStreamParams& aParams,             \
                          FileDescriptorArray& aFileDescriptors,                \
                          bool aDelayedStart, uint32_t aMaxSize,                \
                          uint32_t* aSizeUsed,                                  \
-                         mozilla::dom::ContentChild* aManager) override {   \
+                         mozilla::dom::nsIContentChild* aManager) override {   \
     _to Serialize(aParams, aFileDescriptors, aDelayedStart, aMaxSize,          \
                   aSizeUsed, aManager);                                        \
   }                                                                            \
                                                                                \
   virtual void Serialize(mozilla::ipc::InputStreamParams& aParams,             \
                          FileDescriptorArray& aFileDescriptors,                \
                          bool aDelayedStart, uint32_t aMaxSize,                \
                          uint32_t* aSizeUsed,                                  \
@@ -114,17 +114,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIIPCSeri
     _to Serialize(aParams, aFileDescriptors, aDelayedStart, aMaxSize,          \
                   aSizeUsed, aManager);                                        \
   }                                                                            \
                                                                                \
   virtual void Serialize(mozilla::ipc::InputStreamParams& aParams,             \
                          FileDescriptorArray& aFileDescriptors,                \
                          bool aDelayedStart, uint32_t aMaxSize,                \
                          uint32_t* aSizeUsed,                                  \
-                         mozilla::dom::ContentParent* aManager) override {  \
+                         mozilla::dom::nsIContentParent* aManager) override {  \
     _to Serialize(aParams, aFileDescriptors, aDelayedStart, aMaxSize,          \
                   aSizeUsed, aManager);                                        \
   }                                                                            \
                                                                                \
   virtual void Serialize(mozilla::ipc::InputStreamParams& aParams,             \
                          FileDescriptorArray& aFileDescriptors,                \
                          bool aDelayedStart, uint32_t aMaxSize,                \
                          uint32_t* aSizeUsed,                                  \
@@ -139,17 +139,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIIPCSeri
     return _to Deserialize(aParams, aFileDescriptors);                         \
   }
 
 #define NS_FORWARD_SAFE_NSIIPCSERIALIZABLEINPUTSTREAM(_to)                     \
   virtual void Serialize(mozilla::ipc::InputStreamParams& aParams,             \
                          FileDescriptorArray& aFileDescriptors,                \
                          bool aDelayedStart, uint32_t aMaxSize,                \
                          uint32_t* aSizeUsed,                                  \
-                         mozilla::dom::ContentChild* aManager) override {   \
+                         mozilla::dom::nsIContentChild* aManager) override {   \
     if (_to) {                                                                 \
       _to->Serialize(aParams, aFileDescriptors, aDelayedStart, aMaxSize,       \
                      aSizeUsed, aManager);                                     \
     }                                                                          \
   }                                                                            \
                                                                                \
   virtual void Serialize(mozilla::ipc::InputStreamParams& aParams,             \
                          FileDescriptorArray& aFileDescriptors,                \
@@ -161,17 +161,17 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIIPCSeri
                      aSizeUsed, aManager);                                     \
     }                                                                          \
   }                                                                            \
                                                                                \
   virtual void Serialize(mozilla::ipc::InputStreamParams& aParams,             \
                          FileDescriptorArray& aFileDescriptors,                \
                          bool aDelayedStart, uint32_t aMaxSize,                \
                          uint32_t* aSizeUsed,                                  \
-                         mozilla::dom::ContentParent* aManager) override {  \
+                         mozilla::dom::nsIContentParent* aManager) override {  \
     if (_to) {                                                                 \
       _to->Serialize(aParams, aFileDescriptors, aDelayedStart, aMaxSize,       \
                      aSizeUsed, aManager);                                     \
     }                                                                          \
   }                                                                            \
                                                                                \
   virtual void Serialize(mozilla::ipc::InputStreamParams& aParams,             \
                          FileDescriptorArray& aFileDescriptors,                \
--- a/ipc/ipdl/sync-messages.ini
+++ b/ipc/ipdl/sync-messages.ini
@@ -843,16 +843,20 @@ description = test only
 [PBrowser::GetSystemFont]
 description = test only
 [PBrowser::SetPrefersReducedMotionOverrideForTest]
 description = test only
 [PBrowser::ResetPrefersReducedMotionOverrideForTest]
 description = test only
 [PContent::SyncMessage]
 description =
+[PContent::CreateChildProcess]
+description =
+[PContent::BridgeToChildProcess]
+description =
 [PContent::OpenRecordReplayChannel]
 description = bug 1475898 this could be async
 [PContent::LoadPlugin]
 description =
 [PContent::ConnectPluginBridge]
 description =
 [PContent::IsSecureURI]
 description =
@@ -887,16 +891,18 @@ description =
 [PContent::GetGraphicsDeviceInitData]
 description =
 [PContent::UngrabPointer]
 description =
 [PContent::RemovePermission]
 description =
 [PContent::GetA11yContentId]
 description =
+[PContentBridge::SyncMessage]
+description =
 [PGMP::StartPlugin]
 description =
 [PGMPService::LaunchGMP]
 description =
 [PGMPService::LaunchGMPForNodeId]
 description =
 [PGMPService::GetGMPNodeId]
 description =
--- a/js/ipc/PJavaScript.ipdl
+++ b/js/ipc/PJavaScript.ipdl
@@ -1,27 +1,28 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=4 sw=4 et 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 protocol PContent;
+include protocol PContentBridge;
 include DOMTypes;
 include JavaScriptTypes;
 
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 
 namespace mozilla {
 namespace jsipc {
 
 nested(upto inside_sync) sync protocol PJavaScript
 {
-    manager PContent;
+    manager PContent or PContentBridge;
 
 both:
     // Sent when a CPOW has been finalized and table entries can be freed up.
     async DropObject(uint64_t objId);
 
     // These roughly map to the ProxyHandler hooks that CPOWs need.
     nested(inside_sync) sync PreventExtensions(uint64_t objId) returns (ReturnStatus rs);
     nested(inside_sync) sync GetOwnPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result);
--- a/layout/ipc/RenderFrame.cpp
+++ b/layout/ipc/RenderFrame.cpp
@@ -53,17 +53,17 @@ bool RenderFrame::Initialize(TabParent* 
   if (mInitialized || !aTabParent) {
     return false;
   }
 
   mTabParent = aTabParent;
   RefPtr<LayerManager> lm = GetLayerManager(mTabParent);
   PCompositorBridgeChild* compositor =
       lm ? lm->GetCompositorBridgeChild() : nullptr;
-  mTabProcessId = mTabParent->Manager()->OtherPid();
+  mTabProcessId = mTabParent->Manager()->AsContentParent()->OtherPid();
 
   // Our remote frame will push layers updates to the compositor,
   // and we'll keep an indirect reference to that tree.
   GPUProcessManager* gpm = GPUProcessManager::Get();
   mLayersConnected = gpm->AllocateAndConnectLayerTreeId(
       compositor, mTabProcessId, &mLayersId, &mCompositorOptions);
 
   mInitialized = true;
--- a/netwerk/base/PartiallySeekableInputStream.cpp
+++ b/netwerk/base/PartiallySeekableInputStream.cpp
@@ -277,17 +277,17 @@ PartiallySeekableInputStream::OnInputStr
 }
 
 // nsIIPCSerializableInputStream
 
 void PartiallySeekableInputStream::Serialize(
     mozilla::ipc::InputStreamParams& aParams,
     FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
     uint32_t aMaxSize, uint32_t* aSizeUsed,
-    mozilla::dom::ContentChild* aManager) {
+    mozilla::dom::nsIContentChild* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void PartiallySeekableInputStream::Serialize(
     mozilla::ipc::InputStreamParams& aParams,
     FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
     uint32_t aMaxSize, uint32_t* aSizeUsed,
@@ -295,17 +295,17 @@ void PartiallySeekableInputStream::Seria
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void PartiallySeekableInputStream::Serialize(
     mozilla::ipc::InputStreamParams& aParams,
     FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
     uint32_t aMaxSize, uint32_t* aSizeUsed,
-    mozilla::dom::ContentParent* aManager) {
+    mozilla::dom::nsIContentParent* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void PartiallySeekableInputStream::Serialize(
     mozilla::ipc::InputStreamParams& aParams,
     FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
     uint32_t aMaxSize, uint32_t* aSizeUsed,
--- a/netwerk/base/nsBufferedStreams.cpp
+++ b/netwerk/base/nsBufferedStreams.cpp
@@ -588,34 +588,34 @@ nsBufferedInputStream::GetUnbufferedStre
   NS_IF_ADDREF(*aStream);
   return NS_OK;
 }
 
 void nsBufferedInputStream::Serialize(InputStreamParams& aParams,
                                       FileDescriptorArray& aFileDescriptors,
                                       bool aDelayedStart, uint32_t aMaxSize,
                                       uint32_t* aSizeUsed,
-                                      mozilla::dom::ContentChild* aManager) {
+                                      mozilla::dom::nsIContentChild* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void nsBufferedInputStream::Serialize(InputStreamParams& aParams,
                                       FileDescriptorArray& aFileDescriptors,
                                       bool aDelayedStart, uint32_t aMaxSize,
                                       uint32_t* aSizeUsed,
                                       PBackgroundChild* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void nsBufferedInputStream::Serialize(
     InputStreamParams& aParams, FileDescriptorArray& aFileDescriptors,
     bool aDelayedStart, uint32_t aMaxSize, uint32_t* aSizeUsed,
-    mozilla::dom::ContentParent* aManager) {
+    mozilla::dom::nsIContentParent* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void nsBufferedInputStream::Serialize(InputStreamParams& aParams,
                                       FileDescriptorArray& aFileDescriptors,
                                       bool aDelayedStart, uint32_t aMaxSize,
                                       uint32_t* aSizeUsed,
--- a/netwerk/base/nsFileStreams.cpp
+++ b/netwerk/base/nsFileStreams.cpp
@@ -534,17 +534,17 @@ NS_IMETHODIMP
 nsFileInputStream::Available(uint64_t* aResult) {
   return nsFileStreamBase::Available(aResult);
 }
 
 void nsFileInputStream::Serialize(InputStreamParams& aParams,
                                   FileDescriptorArray& aFileDescriptors,
                                   bool aDelayedStart, uint32_t aMaxSize,
                                   uint32_t* aSizeUsed,
-                                  mozilla::dom::ContentChild* aManager) {
+                                  mozilla::dom::nsIContentChild* aManager) {
   MOZ_ASSERT(aSizeUsed);
   *aSizeUsed = 0;
 
   SerializeInternal(aParams, aFileDescriptors);
 }
 
 void nsFileInputStream::Serialize(InputStreamParams& aParams,
                                   FileDescriptorArray& aFileDescriptors,
@@ -556,17 +556,17 @@ void nsFileInputStream::Serialize(InputS
 
   SerializeInternal(aParams, aFileDescriptors);
 }
 
 void nsFileInputStream::Serialize(InputStreamParams& aParams,
                                   FileDescriptorArray& aFileDescriptors,
                                   bool aDelayedStart, uint32_t aMaxSize,
                                   uint32_t* aSizeUsed,
-                                  mozilla::dom::ContentParent* aManager) {
+                                  mozilla::dom::nsIContentParent* aManager) {
   MOZ_ASSERT(aSizeUsed);
   *aSizeUsed = 0;
 
   SerializeInternal(aParams, aFileDescriptors);
 }
 
 void nsFileInputStream::Serialize(InputStreamParams& aParams,
                                   FileDescriptorArray& aFileDescriptors,
--- a/netwerk/base/nsMIMEInputStream.cpp
+++ b/netwerk/base/nsMIMEInputStream.cpp
@@ -335,17 +335,17 @@ nsresult nsMIMEInputStreamConstructor(ns
 
   return inst->QueryInterface(iid, result);
 }
 
 void nsMIMEInputStream::Serialize(InputStreamParams& aParams,
                                   FileDescriptorArray& aFileDescriptors,
                                   bool aDelayedStart, uint32_t aMaxSize,
                                   uint32_t* aSizeUsed,
-                                  mozilla::dom::ContentChild* aManager) {
+                                  mozilla::dom::nsIContentChild* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void nsMIMEInputStream::Serialize(InputStreamParams& aParams,
                                   FileDescriptorArray& aFileDescriptors,
                                   bool aDelayedStart, uint32_t aMaxSize,
                                   uint32_t* aSizeUsed,
@@ -353,17 +353,17 @@ void nsMIMEInputStream::Serialize(InputS
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void nsMIMEInputStream::Serialize(InputStreamParams& aParams,
                                   FileDescriptorArray& aFileDescriptors,
                                   bool aDelayedStart, uint32_t aMaxSize,
                                   uint32_t* aSizeUsed,
-                                  mozilla::dom::ContentParent* aManager) {
+                                  mozilla::dom::nsIContentParent* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void nsMIMEInputStream::Serialize(InputStreamParams& aParams,
                                   FileDescriptorArray& aFileDescriptors,
                                   bool aDelayedStart, uint32_t aMaxSize,
                                   uint32_t* aSizeUsed,
--- a/netwerk/protocol/http/HttpChannelParentListener.cpp
+++ b/netwerk/protocol/http/HttpChannelParentListener.cpp
@@ -191,17 +191,19 @@ nsresult HttpChannelParentListener::Trig
 
         nsCOMPtr<nsIURI> originalURI;
         channel->GetOriginalURI(getter_AddRefs(originalURI));
 
         uint64_t channelId;
         MOZ_ALWAYS_SUCCEEDS(httpChannel->GetChannelId(&channelId));
 
         dom::TabParent* tabParent = dom::TabParent::GetFrom(tp);
-        auto result = tabParent->Manager()->SendCrossProcessRedirect(
+        ContentParent* cp = tabParent->Manager()->AsContentParent();
+
+        auto result = cp->SendCrossProcessRedirect(
             self->mRedirectChannelId, uri, newLoadFlags, loadInfoArgs,
             channelId, originalURI, aIdentifier);
 
         MOZ_ASSERT(result, "SendCrossProcessRedirect failed");
 
         return result ? NS_OK : NS_ERROR_UNEXPECTED;
       },
       [httpChannel](nsresult aStatus) {
--- a/security/manager/ssl/PSMContentListener.h
+++ b/security/manager/ssl/PSMContentListener.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_psm_PSMCOntentListener_h_
 #define mozilla_psm_PSMCOntentListener_h_
 
 #include "nsCOMPtr.h"
 #include "nsIURIContentListener.h"
-#include "nsIStreamListener.h"
 #include "nsWeakReference.h"
 #include "mozilla/psm/PPSMContentDownloaderChild.h"
 #include "mozilla/psm/PPSMContentDownloaderParent.h"
 
 #define NS_PSMCONTENTLISTEN_CID                      \
   {                                                  \
     0xc94f4a30, 0x64d7, 0x11d4, {                    \
       0x99, 0x60, 0x00, 0xb0, 0xd0, 0x23, 0x54, 0xa0 \
--- a/testing/web-platform/meta/encrypted-media/__dir__.ini
+++ b/testing/web-platform/meta/encrypted-media/__dir__.ini
@@ -1,5 +1,5 @@
 disabled:
   if asan: https://bugzilla.mozilla.org/show_bug.cgi?id=1522213
 prefs: [dom.security.featurePolicy.enabled:true, dom.security.featurePolicy.header.enabled:true, dom.security.featurePolicy.webidl.enabled:true]
-lsan-allowed: [Alloc, CreateCDMProxy, MakeUnique, Malloc, NewPage, Realloc, mozilla::EMEDecryptor::EMEDecryptor, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::dom::MediaKeys::CreateCDMProxy, mozilla::dom::ContentChild::GetConstructedEventTarget]
+lsan-allowed: [Alloc, CreateCDMProxy, MakeUnique, Malloc, NewPage, Realloc, mozilla::EMEDecryptor::EMEDecryptor, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::dom::MediaKeys::CreateCDMProxy, mozilla::dom::nsIContentChild::GetConstructedEventTarget]
 leak-threshold: [default:51200]
--- a/testing/web-platform/meta/websockets/binary/__dir__.ini
+++ b/testing/web-platform/meta/websockets/binary/__dir__.ini
@@ -1,3 +1,3 @@
-lsan-allowed: [MakeUnique, mozilla::dom::WebSocket::ConstructorCommon, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketEventService::GetOrCreate, Alloc, Create, Malloc, NewPage, PLDHashTable::Add, PLDHashTable::ChangeTable, Realloc, RecvOnAcknowledge, RecvOnStop, mozilla::BasePrincipal::CreateCodebasePrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::ThrottledEventQueue::Create, mozilla::WeakPtr, mozilla::dom::ScriptElement::MaybeProcessScript, mozilla::dom::WebSocket::WebSocket, mozilla::dom::WorkerCSPEventListener::Create, mozilla::dom::ContentChild::GetConstructedEventTarget, mozilla::net::WebSocketChannelChild::RecvOnServerClose, mozilla::net::nsStandardURL::TemplatedMutator, nsAtomTable::Atomize, nsDocShell::Create]
+lsan-allowed: [MakeUnique, mozilla::dom::WebSocket::ConstructorCommon, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketEventService::GetOrCreate, Alloc, Create, Malloc, NewPage, PLDHashTable::Add, PLDHashTable::ChangeTable, Realloc, RecvOnAcknowledge, RecvOnStop, mozilla::BasePrincipal::CreateCodebasePrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::ThrottledEventQueue::Create, mozilla::WeakPtr, mozilla::dom::ScriptElement::MaybeProcessScript, mozilla::dom::WebSocket::WebSocket, mozilla::dom::WorkerCSPEventListener::Create, mozilla::dom::nsIContentChild::GetConstructedEventTarget, mozilla::net::WebSocketChannelChild::RecvOnServerClose, mozilla::net::nsStandardURL::TemplatedMutator, nsAtomTable::Atomize, nsDocShell::Create]
 lsan-max-stack-depth: 7
 leak-threshold: [tab:51200]
--- a/testing/web-platform/meta/websockets/constructor/__dir__.ini
+++ b/testing/web-platform/meta/websockets/constructor/__dir__.ini
@@ -1,3 +1,3 @@
-lsan-allowed: [Alloc, Create, MakeUnique, Malloc, NewPage, PLDHashTable::Add, PLDHashTable::ChangeTable, Realloc, RecvOnAcknowledge, RecvOnStop, SetPropertyAsInterface, SetSucceededCertChain, allocate, mozilla::BasePrincipal::CreateCodebasePrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::ThrottledEventQueue::Create, mozilla::WeakPtr, mozilla::dom::ScriptElement::MaybeProcessScript, mozilla::dom::WebSocket::ConstructorCommon, mozilla::dom::WebSocket::WebSocket, mozilla::dom::WorkerCSPEventListener::Create, mozilla::dom::ContentChild::GetConstructedEventTarget, mozilla::extensions::ChannelWrapper::ChannelWrapper, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketChannelChild::RecvOnServerClose, mozilla::net::WebSocketEventService::GetOrCreate, mozilla::net::nsHttpTransaction::ParseHead, mozilla::net::nsStandardURL::TemplatedMutator, nsAtomTable::Atomize, nsDocShell::Create, nsNSSCertificate::Create, nsNodeSupportsWeakRefTearoff::GetWeakReference, nsSSLIOLayerAddToSocket]
+lsan-allowed: [Alloc, Create, MakeUnique, Malloc, NewPage, PLDHashTable::Add, PLDHashTable::ChangeTable, Realloc, RecvOnAcknowledge, RecvOnStop, SetPropertyAsInterface, SetSucceededCertChain, allocate, mozilla::BasePrincipal::CreateCodebasePrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::ThrottledEventQueue::Create, mozilla::WeakPtr, mozilla::dom::ScriptElement::MaybeProcessScript, mozilla::dom::WebSocket::ConstructorCommon, mozilla::dom::WebSocket::WebSocket, mozilla::dom::WorkerCSPEventListener::Create, mozilla::dom::nsIContentChild::GetConstructedEventTarget, mozilla::extensions::ChannelWrapper::ChannelWrapper, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketChannelChild::RecvOnServerClose, mozilla::net::WebSocketEventService::GetOrCreate, mozilla::net::nsHttpTransaction::ParseHead, mozilla::net::nsStandardURL::TemplatedMutator, nsAtomTable::Atomize, nsDocShell::Create, nsNSSCertificate::Create, nsNodeSupportsWeakRefTearoff::GetWeakReference, nsSSLIOLayerAddToSocket]
 lsan-max-stack-depth: 7
 leak-threshold: [tab:51200]
--- a/toolkit/components/extensions/webrequest/ChannelWrapper.cpp
+++ b/toolkit/components/extensions/webrequest/ChannelWrapper.cpp
@@ -136,19 +136,19 @@ already_AddRefed<ChannelWrapper> Channel
   }
 
   return wrapper.forget();
 }
 
 already_AddRefed<ChannelWrapper> ChannelWrapper::GetRegisteredChannel(
     const GlobalObject& global, uint64_t aChannelId,
     const WebExtensionPolicy& aAddon, nsITabParent* aTabParent) {
-  ContentParent* contentParent = nullptr;
+  nsIContentParent* contentParent = nullptr;
   if (TabParent* parent = static_cast<TabParent*>(aTabParent)) {
-    contentParent = parent->Manager();
+    contentParent = static_cast<nsIContentParent*>(parent->Manager());
   }
 
   auto& webreq = WebRequestService::GetSingleton();
 
   nsCOMPtr<nsITraceableChannel> channel =
       webreq.GetTraceableChannel(aChannelId, aAddon.Id(), contentParent);
   if (!channel) {
     return nullptr;
@@ -672,22 +672,23 @@ void ChannelWrapper::RegisterTraceableCh
   mAddonEntries.Put(aAddon.Id(), aTabParent);
   if (!mChannelEntry) {
     mChannelEntry = WebRequestService::GetSingleton().RegisterChannel(this);
     CheckEventListeners();
   }
 }
 
 already_AddRefed<nsITraceableChannel> ChannelWrapper::GetTraceableChannel(
-    nsAtom* aAddonId, dom::ContentParent* aContentParent) const {
+    nsAtom* aAddonId, dom::nsIContentParent* aContentParent) const {
   nsCOMPtr<nsITabParent> tabParent;
   if (mAddonEntries.Get(aAddonId, getter_AddRefs(tabParent))) {
-    ContentParent* contentParent = nullptr;
+    nsIContentParent* contentParent = nullptr;
     if (tabParent) {
-      contentParent = static_cast<TabParent*>(tabParent.get())->Manager();
+      contentParent = static_cast<nsIContentParent*>(
+          static_cast<TabParent*>(tabParent.get())->Manager());
     }
 
     if (contentParent == aContentParent) {
       nsCOMPtr<nsITraceableChannel> chan = QueryChannel();
       return chan.forget();
     }
   }
   return nullptr;
--- a/toolkit/components/extensions/webrequest/ChannelWrapper.h
+++ b/toolkit/components/extensions/webrequest/ChannelWrapper.h
@@ -40,17 +40,17 @@
     }                                                \
   }
 
 class nsILoadContext;
 class nsITraceableChannel;
 
 namespace mozilla {
 namespace dom {
-class ContentParent;
+class nsIContentParent;
 class Element;
 }  // namespace dom
 namespace extensions {
 
 namespace detail {
 
 // We need to store our wrapped channel as a weak reference, since channels
 // are not cycle collected, and we're going to be hanging this wrapper
@@ -146,17 +146,17 @@ class ChannelWrapper final : public DOME
 
   void GetContentType(nsCString& aContentType) const;
   void SetContentType(const nsACString& aContentType);
 
   void RegisterTraceableChannel(const WebExtensionPolicy& aAddon,
                                 nsITabParent* aTabParent);
 
   already_AddRefed<nsITraceableChannel> GetTraceableChannel(
-      nsAtom* aAddonId, dom::ContentParent* aContentParent) const;
+      nsAtom* aAddonId, dom::nsIContentParent* aContentParent) const;
 
   void GetMethod(nsCString& aRetVal) const;
 
   dom::MozContentPolicyType Type() const;
 
   uint32_t StatusCode() const;
 
   void GetStatusLine(nsCString& aRetVal) const;
--- a/toolkit/components/extensions/webrequest/WebRequestService.cpp
+++ b/toolkit/components/extensions/webrequest/WebRequestService.cpp
@@ -39,17 +39,17 @@ UniquePtr<WebRequestChannelEntry> WebReq
   auto key = mChannelEntries.LookupForAdd(entry->mChannelId);
   MOZ_DIAGNOSTIC_ASSERT(!key);
   key.OrInsert([&entry]() { return entry.get(); });
 
   return entry;
 }
 
 already_AddRefed<nsITraceableChannel> WebRequestService::GetTraceableChannel(
-    uint64_t aChannelId, nsAtom* aAddonId, ContentParent* aContentParent) {
+    uint64_t aChannelId, nsAtom* aAddonId, nsIContentParent* aContentParent) {
   if (auto entry = mChannelEntries.Get(aChannelId)) {
     if (entry->mChannel) {
       return entry->mChannel->GetTraceableChannel(aAddonId, aContentParent);
     }
   }
   return nullptr;
 }
 
--- a/toolkit/components/extensions/webrequest/WebRequestService.h
+++ b/toolkit/components/extensions/webrequest/WebRequestService.h
@@ -18,17 +18,17 @@
 
 class nsAtom;
 class nsITabParent;
 class nsITraceableChannel;
 
 namespace mozilla {
 namespace dom {
 class TabParent;
-class ContentParent;
+class nsIContentParent;
 }  // namespace dom
 
 namespace extensions {
 
 class WebRequestChannelEntry final {
  public:
   ~WebRequestChannelEntry();
 
@@ -56,17 +56,17 @@ class WebRequestService final {
   using ChannelEntry = WebRequestChannelEntry;
 
   UniquePtr<ChannelEntry> RegisterChannel(ChannelWrapper* aChannel);
 
   void UnregisterTraceableChannel(uint64_t aChannelId);
 
   already_AddRefed<nsITraceableChannel> GetTraceableChannel(
       uint64_t aChannelId, nsAtom* aAddonId,
-      dom::ContentParent* aContentParent);
+      dom::nsIContentParent* aContentParent);
 
  private:
   ~WebRequestService();
 
   friend ChannelEntry;
 
   nsDataHashtable<nsUint64HashKey, ChannelEntry*> mChannelEntries;
 };
--- a/xpcom/io/InputStreamLengthWrapper.cpp
+++ b/xpcom/io/InputStreamLengthWrapper.cpp
@@ -255,17 +255,17 @@ InputStreamLengthWrapper::OnInputStreamR
 }
 
 // nsIIPCSerializableInputStream
 
 void InputStreamLengthWrapper::Serialize(
     mozilla::ipc::InputStreamParams& aParams,
     FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
     uint32_t aMaxSize, uint32_t* aSizeUsed,
-    mozilla::dom::ContentChild* aManager) {
+    mozilla::dom::nsIContentChild* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void InputStreamLengthWrapper::Serialize(
     mozilla::ipc::InputStreamParams& aParams,
     FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
     uint32_t aMaxSize, uint32_t* aSizeUsed,
@@ -273,17 +273,17 @@ void InputStreamLengthWrapper::Serialize
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void InputStreamLengthWrapper::Serialize(
     mozilla::ipc::InputStreamParams& aParams,
     FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
     uint32_t aMaxSize, uint32_t* aSizeUsed,
-    mozilla::dom::ContentParent* aManager) {
+    mozilla::dom::nsIContentParent* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void InputStreamLengthWrapper::Serialize(
     mozilla::ipc::InputStreamParams& aParams,
     FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
     uint32_t aMaxSize, uint32_t* aSizeUsed,
--- a/xpcom/io/NonBlockingAsyncInputStream.cpp
+++ b/xpcom/io/NonBlockingAsyncInputStream.cpp
@@ -315,17 +315,17 @@ NonBlockingAsyncInputStream::AsyncWait(n
 }
 
 // nsIIPCSerializableInputStream
 
 void NonBlockingAsyncInputStream::Serialize(
     mozilla::ipc::InputStreamParams& aParams,
     FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
     uint32_t aMaxSize, uint32_t* aSizeUsed,
-    mozilla::dom::ContentChild* aManager) {
+    mozilla::dom::nsIContentChild* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void NonBlockingAsyncInputStream::Serialize(
     mozilla::ipc::InputStreamParams& aParams,
     FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
     uint32_t aMaxSize, uint32_t* aSizeUsed,
@@ -333,17 +333,17 @@ void NonBlockingAsyncInputStream::Serial
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void NonBlockingAsyncInputStream::Serialize(
     mozilla::ipc::InputStreamParams& aParams,
     FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
     uint32_t aMaxSize, uint32_t* aSizeUsed,
-    mozilla::dom::ContentParent* aManager) {
+    mozilla::dom::nsIContentParent* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void NonBlockingAsyncInputStream::Serialize(
     mozilla::ipc::InputStreamParams& aParams,
     FileDescriptorArray& aFileDescriptors, bool aDelayedStart,
     uint32_t aMaxSize, uint32_t* aSizeUsed,
--- a/xpcom/io/SlicedInputStream.cpp
+++ b/xpcom/io/SlicedInputStream.cpp
@@ -419,17 +419,17 @@ SlicedInputStream::OnInputStreamReady(ns
 }
 
 // nsIIPCSerializableInputStream
 
 void SlicedInputStream::Serialize(mozilla::ipc::InputStreamParams& aParams,
                                   FileDescriptorArray& aFileDescriptors,
                                   bool aDelayedStart, uint32_t aMaxSize,
                                   uint32_t* aSizeUsed,
-                                  mozilla::dom::ContentChild* aManager) {
+                                  mozilla::dom::nsIContentChild* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void SlicedInputStream::Serialize(mozilla::ipc::InputStreamParams& aParams,
                                   FileDescriptorArray& aFileDescriptors,
                                   bool aDelayedStart, uint32_t aMaxSize,
                                   uint32_t* aSizeUsed,
@@ -437,17 +437,17 @@ void SlicedInputStream::Serialize(mozill
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void SlicedInputStream::Serialize(mozilla::ipc::InputStreamParams& aParams,
                                   FileDescriptorArray& aFileDescriptors,
                                   bool aDelayedStart, uint32_t aMaxSize,
                                   uint32_t* aSizeUsed,
-                                  mozilla::dom::ContentParent* aManager) {
+                                  mozilla::dom::nsIContentParent* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void SlicedInputStream::Serialize(mozilla::ipc::InputStreamParams& aParams,
                                   FileDescriptorArray& aFileDescriptors,
                                   bool aDelayedStart, uint32_t aMaxSize,
                                   uint32_t* aSizeUsed,
--- a/xpcom/io/nsMultiplexInputStream.cpp
+++ b/xpcom/io/nsMultiplexInputStream.cpp
@@ -988,34 +988,34 @@ nsresult nsMultiplexInputStreamConstruct
   RefPtr<nsMultiplexInputStream> inst = new nsMultiplexInputStream();
 
   return inst->QueryInterface(aIID, aResult);
 }
 
 void nsMultiplexInputStream::Serialize(
     InputStreamParams& aParams, FileDescriptorArray& aFileDescriptors,
     bool aDelayedStart, uint32_t aMaxSize, uint32_t* aSizeUsed,
-    mozilla::dom::ContentChild* aManager) {
+    mozilla::dom::nsIContentChild* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void nsMultiplexInputStream::Serialize(InputStreamParams& aParams,
                                        FileDescriptorArray& aFileDescriptors,
                                        bool aDelayedStart, uint32_t aMaxSize,
                                        uint32_t* aSizeUsed,
                                        PBackgroundChild* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void nsMultiplexInputStream::Serialize(
     InputStreamParams& aParams, FileDescriptorArray& aFileDescriptors,
     bool aDelayedStart, uint32_t aMaxSize, uint32_t* aSizeUsed,
-    mozilla::dom::ContentParent* aManager) {
+    mozilla::dom::nsIContentParent* aManager) {
   SerializeInternal(aParams, aFileDescriptors, aDelayedStart, aMaxSize,
                     aSizeUsed, aManager);
 }
 
 void nsMultiplexInputStream::Serialize(InputStreamParams& aParams,
                                        FileDescriptorArray& aFileDescriptors,
                                        bool aDelayedStart, uint32_t aMaxSize,
                                        uint32_t* aSizeUsed,
--- a/xpcom/io/nsStorageStream.cpp
+++ b/xpcom/io/nsStorageStream.cpp
@@ -548,31 +548,31 @@ nsresult nsStorageInputStream::Seek(uint
   mSegmentEnd = mReadCursor + XPCOM_MIN(mSegmentSize - mReadCursor, available);
   mLogicalCursor = aPosition;
   return NS_OK;
 }
 
 void nsStorageInputStream::Serialize(InputStreamParams& aParams,
                                      FileDescriptorArray&, bool aDelayedStart,
                                      uint32_t aMaxSize, uint32_t* aSizeUsed,
-                                     mozilla::dom::ContentChild* aManager) {
+                                     mozilla::dom::nsIContentChild* aManager) {
   SerializeInternal(aParams, aDelayedStart, aMaxSize, aSizeUsed, aManager);
 }
 
 void nsStorageInputStream::Serialize(InputStreamParams& aParams,
                                      FileDescriptorArray&, bool aDelayedStart,
                                      uint32_t aMaxSize, uint32_t* aSizeUsed,
                                      mozilla::ipc::PBackgroundChild* aManager) {
   SerializeInternal(aParams, aDelayedStart, aMaxSize, aSizeUsed, aManager);
 }
 
 void nsStorageInputStream::Serialize(InputStreamParams& aParams,
                                      FileDescriptorArray&, bool aDelayedStart,
                                      uint32_t aMaxSize, uint32_t* aSizeUsed,
-                                     mozilla::dom::ContentParent* aManager) {
+                                     mozilla::dom::nsIContentParent* aManager) {
   SerializeInternal(aParams, aDelayedStart, aMaxSize, aSizeUsed, aManager);
 }
 
 void nsStorageInputStream::Serialize(
     InputStreamParams& aParams, FileDescriptorArray&, bool aDelayedStart,
     uint32_t aMaxSize, uint32_t* aSizeUsed,
     mozilla::ipc::PBackgroundParent* aManager) {
   SerializeInternal(aParams, aDelayedStart, aMaxSize, aSizeUsed, aManager);
--- a/xpcom/io/nsStringStream.cpp
+++ b/xpcom/io/nsStringStream.cpp
@@ -343,33 +343,33 @@ nsStringInputStream::Tell(int64_t* aOutW
 /////////
 // nsIIPCSerializableInputStream implementation
 /////////
 
 void nsStringInputStream::Serialize(InputStreamParams& aParams,
                                     FileDescriptorArray& /* aFDs */,
                                     bool aDelayedStart, uint32_t aMaxSize,
                                     uint32_t* aSizeUsed,
-                                    mozilla::dom::ContentChild* aManager) {
+                                    mozilla::dom::nsIContentChild* aManager) {
   SerializeInternal(aParams, aDelayedStart, aMaxSize, aSizeUsed, aManager);
 }
 
 void nsStringInputStream::Serialize(InputStreamParams& aParams,
                                     FileDescriptorArray& /* aFDs */,
                                     bool aDelayedStart, uint32_t aMaxSize,
                                     uint32_t* aSizeUsed,
                                     PBackgroundChild* aManager) {
   SerializeInternal(aParams, aDelayedStart, aMaxSize, aSizeUsed, aManager);
 }
 
 void nsStringInputStream::Serialize(InputStreamParams& aParams,
                                     FileDescriptorArray& /* aFDs */,
                                     bool aDelayedStart, uint32_t aMaxSize,
                                     uint32_t* aSizeUsed,
-                                    mozilla::dom::ContentParent* aManager) {
+                                    mozilla::dom::nsIContentParent* aManager) {
   SerializeInternal(aParams, aDelayedStart, aMaxSize, aSizeUsed, aManager);
 }
 
 void nsStringInputStream::Serialize(InputStreamParams& aParams,
                                     FileDescriptorArray& /* aFDs */,
                                     bool aDelayedStart, uint32_t aMaxSize,
                                     uint32_t* aSizeUsed,
                                     PBackgroundParent* aManager) {
--- a/xpcom/tests/gtest/TestNonBlockingAsyncInputStream.cpp
+++ b/xpcom/tests/gtest/TestNonBlockingAsyncInputStream.cpp
@@ -264,24 +264,24 @@ class QIInputStream final : public nsIIn
   // nsICloneableInputStream
   NS_IMETHOD GetCloneable(bool*) override { return NS_ERROR_NOT_IMPLEMENTED; }
   NS_IMETHOD Clone(nsIInputStream**) override {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   // nsIIPCSerializableInputStream
   void Serialize(mozilla::ipc::InputStreamParams&, FileDescriptorArray&, bool,
-                 uint32_t, uint32_t*, mozilla::dom::ContentChild*) override {
+                 uint32_t, uint32_t*, mozilla::dom::nsIContentChild*) override {
   }
   void Serialize(mozilla::ipc::InputStreamParams&, FileDescriptorArray&, bool,
                  uint32_t, uint32_t*,
                  mozilla::ipc::PBackgroundChild*) override {}
   void Serialize(mozilla::ipc::InputStreamParams&, FileDescriptorArray&, bool,
                  uint32_t, uint32_t*,
-                 mozilla::dom::ContentParent*) override {}
+                 mozilla::dom::nsIContentParent*) override {}
   void Serialize(mozilla::ipc::InputStreamParams&, FileDescriptorArray&, bool,
                  uint32_t, uint32_t*,
                  mozilla::ipc::PBackgroundParent*) override {}
   bool Deserialize(const mozilla::ipc::InputStreamParams&,
                    const FileDescriptorArray&) override {
     return false;
   }