Bug 1557739 - Be more consistent with IPC Transport APIs, r=jld
authorNika Layzell <nika@thelayzells.com>
Thu, 06 Feb 2020 22:41:56 +0000
changeset 512809 66d07ba43d6def0cfb7a344e5784aca055856b81
parent 512808 1d190ee669ee3d1ef14ffd79b001dacdc801994d
child 512810 5d3e1eab99b8bdfba6e53f5615ceba7330138894
push id37098
push usercsabou@mozilla.com
push dateFri, 07 Feb 2020 03:55:51 +0000
treeherdermozilla-central@7dcafc398876 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjld
bugs1557739
milestone74.0a1
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
Bug 1557739 - Be more consistent with IPC Transport APIs, r=jld Differential Revision: https://phabricator.services.mozilla.com/D60285
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentProcess.cpp
dom/media/gmp/GMPChild.cpp
dom/media/gmp/GMPChild.h
dom/media/gmp/GMPParent.cpp
dom/media/gmp/GMPProcessChild.cpp
dom/media/gmp/GMPServiceParent.cpp
dom/media/gmp/GMPServiceParent.h
dom/media/ipc/RDDParent.cpp
dom/media/ipc/RDDParent.h
dom/media/ipc/RDDProcessHost.cpp
dom/media/ipc/RDDProcessImpl.cpp
dom/plugins/ipc/PluginModuleChild.cpp
dom/plugins/ipc/PluginModuleChild.h
dom/plugins/ipc/PluginModuleParent.cpp
dom/plugins/ipc/PluginProcessChild.cpp
gfx/ipc/GPUParent.cpp
gfx/ipc/GPUParent.h
gfx/ipc/GPUProcessHost.cpp
gfx/ipc/GPUProcessImpl.cpp
gfx/vr/ipc/VRParent.cpp
gfx/vr/ipc/VRParent.h
gfx/vr/ipc/VRProcessChild.cpp
gfx/vr/ipc/VRProcessParent.cpp
ipc/chromium/src/chrome/common/child_process_host.h
ipc/chromium/src/chrome/common/child_thread.h
ipc/glue/GeckoChildProcessHost.h
ipc/glue/IOThreadChild.h
ipc/glue/MessageChannel.cpp
ipc/glue/MessageChannel.h
ipc/glue/MessageLink.cpp
ipc/glue/MessageLink.h
ipc/glue/ProtocolUtils.cpp
ipc/glue/ProtocolUtils.h
ipc/ipdl/test/cxx/IPDLUnitTestProcessChild.cpp
netwerk/ipc/SocketProcessChild.cpp
netwerk/ipc/SocketProcessChild.h
netwerk/ipc/SocketProcessHost.cpp
netwerk/ipc/SocketProcessImpl.cpp
security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.cpp
security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.h
security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.cpp
security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessChild.cpp
toolkit/recordreplay/ipc/ParentForwarding.cpp
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -626,18 +626,19 @@ mozilla::ipc::IPCResult ContentChild::Re
   InitSharedUASheets(aSharedUASheetHandle, aSharedUASheetAddress);
   InitXPCOM(aXPCOMInit, aInitialData);
   InitGraphicsDeviceData(aXPCOMInit.contentDeviceData());
 
   return IPC_OK();
 }
 
 bool ContentChild::Init(MessageLoop* aIOLoop, base::ProcessId aParentPid,
-                        const char* aParentBuildID, IPC::Channel* aChannel,
-                        uint64_t aChildID, bool aIsForBrowser) {
+                        const char* aParentBuildID,
+                        UniquePtr<IPC::Channel> aChannel, uint64_t aChildID,
+                        bool aIsForBrowser) {
 #ifdef MOZ_WIDGET_GTK
   // When running X11 only build we need to pass a display down
   // to gtk_init because it's not going to use the one from the environment
   // on its own when deciding which backend to use, and when starting under
   // XWayland, it may choose to start with the wayland backend
   // instead of the x11 backend.
   // The DISPLAY environment variable is normally set by the parent process.
   // The MOZ_GDK_DISPLAY environment variable is set from nsAppRunner.cpp
@@ -691,17 +692,17 @@ bool ContentChild::Init(MessageLoop* aIO
     SetMiddlemanIPCChannel(recordreplay::parent::ChannelToUIProcess());
 
     // Eagerly mark this child as connected, as using another IPC channel will
     // cause that channel's protocol to be marked as connected instead and
     // prevent this one from being able to send IPDL messages.
     ActorConnected();
   }
 
-  if (!Open(aChannel, aParentPid, aIOLoop)) {
+  if (!Open(std::move(aChannel), aParentPid, aIOLoop)) {
     return false;
   }
   sSingleton = this;
 
   // If communications with the parent have broken down, take the process
   // down so it's not hanging around.
   GetIPCChannel()->SetAbortOnError(true);
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -115,17 +115,17 @@ class ContentChild final
                                bool aPositionSpecified, bool aSizeSpecified,
                                nsIURI* aURI, const nsAString& aName,
                                const nsACString& aFeatures, bool aForceNoOpener,
                                bool aForceNoReferrer,
                                nsDocShellLoadState* aLoadState,
                                bool* aWindowIsNew, BrowsingContext** aReturn);
 
   bool Init(MessageLoop* aIOLoop, base::ProcessId aParentPid,
-            const char* aParentBuildID, IPC::Channel* aChannel,
+            const char* aParentBuildID, UniquePtr<IPC::Channel> aChannel,
             uint64_t aChildID, bool aIsForBrowser);
 
   void InitXPCOM(const XPCOMInitData& aXPCOMInit,
                  const mozilla::dom::ipc::StructuredCloneData& aInitialData);
 
   void InitSharedUASheets(const Maybe<base::SharedMemoryHandle>& aHandle,
                           uintptr_t aAddress);
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2314,17 +2314,17 @@ void ContentParent::LaunchSubprocessInte
       nsCOMPtr<nsIObserverService> obs =
           mozilla::services::GetObserverService();
       obs->NotifyObservers(nullptr, "ipc:first-content-process-created",
                            nullptr);
       sCreatedFirstContentProcess = true;
     }
 
     base::ProcessId procId = base::GetProcId(handle);
-    Open(mSubprocess->GetChannel(), procId);
+    Open(mSubprocess->TakeChannel(), procId);
 #ifdef MOZ_CODE_COVERAGE
     Unused << SendShareCodeCoverageMutex(
         CodeCoverageHandler::Get()->GetMutexHandle(procId));
 #endif
 
     mLifecycleState = LifecycleState::ALIVE;
     if (!InitInternal(aInitialPriority)) {
       NS_WARNING("failed to initialize child in the parent");
--- a/dom/ipc/ContentProcess.cpp
+++ b/dom/ipc/ContentProcess.cpp
@@ -178,17 +178,17 @@ bool ContentProcess::Init(int aArgc, cha
 
   if (recordreplay::IsMiddleman()) {
     recordreplay::parent::InitializeMiddleman(aArgc, aArgv, ParentPid(),
                                               deserializer.GetPrefsHandle(),
                                               deserializer.GetPrefMapHandle());
   }
 
   mContent.Init(IOThreadChild::message_loop(), ParentPid(), *parentBuildID,
-                IOThreadChild::channel(), *childID, *isForBrowser);
+                IOThreadChild::TakeChannel(), *childID, *isForBrowser);
 
   mXREEmbed.Start();
 #if (defined(XP_MACOSX)) && defined(MOZ_SANDBOX)
   mContent.SetProfileDir(profileDir);
 #  if defined(DEBUG)
   // For WebReplay middleman processes, the sandbox is
   // started after receiving the SetProcessSandbox message.
   if (IsContentSandboxEnabled() &&
--- a/dom/media/gmp/GMPChild.cpp
+++ b/dom/media/gmp/GMPChild.cpp
@@ -150,21 +150,21 @@ static bool GetPluginPaths(const nsAStri
   aPluginFilePath = GetNativeTarget(libFile);
 
   return true;
 }
 #  endif  // MOZ_SANDBOX
 #endif    // XP_MACOSX
 
 bool GMPChild::Init(const nsAString& aPluginPath, base::ProcessId aParentPid,
-                    MessageLoop* aIOLoop, IPC::Channel* aChannel) {
+                    MessageLoop* aIOLoop, UniquePtr<IPC::Channel> aChannel) {
   GMP_CHILD_LOG_DEBUG("%s pluginPath=%s", __FUNCTION__,
                       NS_ConvertUTF16toUTF8(aPluginPath).get());
 
-  if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) {
+  if (NS_WARN_IF(!Open(std::move(aChannel), aParentPid, aIOLoop))) {
     return false;
   }
 
   CrashReporterClient::InitSingleton(this);
 
   mPluginPath = aPluginPath;
 
   return true;
--- a/dom/media/gmp/GMPChild.h
+++ b/dom/media/gmp/GMPChild.h
@@ -22,17 +22,17 @@ class GMPContentChild;
 class GMPChild : public PGMPChild {
   friend class PGMPChild;
 
  public:
   GMPChild();
   virtual ~GMPChild();
 
   bool Init(const nsAString& aPluginPath, base::ProcessId aParentPid,
-            MessageLoop* aIOLoop, IPC::Channel* aChannel);
+            MessageLoop* aIOLoop, UniquePtr<IPC::Channel> aChannel);
   MessageLoop* GMPMessageLoop();
 
   // Main thread only.
   GMPTimerChild* GetGMPTimers();
   GMPStorageChild* GetGMPStorage();
 
 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
   bool SetMacSandboxInfo(bool aAllowWindowServer);
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -149,17 +149,17 @@ nsresult GMPParent::LoadProcess() {
       mProcess->Delete();
       mProcess = nullptr;
       return NS_ERROR_FAILURE;
     }
 
     mChildPid = base::GetProcId(mProcess->GetChildProcessHandle());
     GMP_PARENT_LOG_DEBUG("%s: Launched new child process", __FUNCTION__);
 
-    bool opened = Open(mProcess->GetChannel(),
+    bool opened = Open(mProcess->TakeChannel(),
                        base::GetProcId(mProcess->GetChildProcessHandle()));
     if (!opened) {
       GMP_PARENT_LOG_DEBUG("%s: Failed to open channel to new child process",
                            __FUNCTION__);
       mProcess->Delete();
       mProcess = nullptr;
       return NS_ERROR_FAILURE;
     }
--- a/dom/media/gmp/GMPProcessChild.cpp
+++ b/dom/media/gmp/GMPProcessChild.cpp
@@ -37,15 +37,16 @@ bool GMPProcessChild::Init(int aArgc, ch
   pluginFilename = nsDependentString(values[0].c_str());
 #else
 #  error Not implemented
 #endif
 
   BackgroundHangMonitor::Startup();
 
   return mPlugin.Init(pluginFilename, ParentPid(),
-                      IOThreadChild::message_loop(), IOThreadChild::channel());
+                      IOThreadChild::message_loop(),
+                      IOThreadChild::TakeChannel());
 }
 
 void GMPProcessChild::CleanUp() { BackgroundHangMonitor::Shutdown(); }
 
 }  // namespace gmp
 }  // namespace mozilla
--- a/dom/media/gmp/GMPServiceParent.cpp
+++ b/dom/media/gmp/GMPServiceParent.cpp
@@ -1687,55 +1687,22 @@ mozilla::ipc::IPCResult GMPServiceParent
     const nsString& aGMPName, nsCString* aID) {
   nsresult rv = mService->GetNodeId(aOrigin, aTopLevelOrigin, aGMPName, *aID);
   if (!NS_SUCCEEDED(rv)) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
-void GMPServiceParent::CloseTransport(Monitor* aSyncMonitor, bool* aCompleted) {
-  MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-
-  MonitorAutoLock lock(*aSyncMonitor);
-
-  // This deletes the transport.
-  SetTransport(nullptr);
-
-  *aCompleted = true;
-  lock.NotifyAll();
-}
-
-void GMPServiceParent::ActorDestroy(ActorDestroyReason aWhy) {
-  Monitor monitor("DeleteGMPServiceParent");
-  bool completed = false;
-
-  // Make sure the IPC channel is closed before destroying mToDelete.
-  MonitorAutoLock lock(monitor);
-  RefPtr<Runnable> task = NewNonOwningRunnableMethod<Monitor*, bool*>(
-      "gmp::GMPServiceParent::CloseTransport", this,
-      &GMPServiceParent::CloseTransport, &monitor, &completed);
-  XRE_GetIOMessageLoop()->PostTask(task.forget());
-
-  while (!completed) {
-    lock.Wait();
-  }
-
-  // Dispatch a task to the current thread to ensure we don't delete the
-  // GMPServiceParent until the current calling context is finished with
-  // the object.
-  GMPServiceParent* self = this;
-  NS_DispatchToCurrentThread(
-      NS_NewRunnableFunction("gmp::GMPServiceParent::ActorDestroy", [self]() {
-        // The GMPServiceParent must be destroyed on the main thread.
-        self->mService->mMainThread->Dispatch(
-            NS_NewRunnableFunction("gmp::GMPServiceParent::ActorDestroy",
-                                   [self]() { delete self; }),
-            NS_DISPATCH_NORMAL);
-      }));
+void GMPServiceParent::ActorDealloc() {
+  // The GMPServiceParent must be destroyed on the main thread.
+  mService->mMainThread->Dispatch(
+      NS_NewRunnableFunction("gmp::GMPServiceParent::ActorDealloc",
+                             [this]() { delete this; }),
+      NS_DISPATCH_NORMAL);
 }
 
 class OpenPGMPServiceParent : public mozilla::Runnable {
  public:
   OpenPGMPServiceParent(GMPServiceParent* aGMPServiceParent,
                         ipc::Endpoint<PGMPServiceParent>&& aEndpoint,
                         bool* aResult)
       : Runnable("gmp::OpenPGMPServiceParent"),
--- a/dom/media/gmp/GMPServiceParent.h
+++ b/dom/media/gmp/GMPServiceParent.h
@@ -215,17 +215,17 @@ class GMPServiceParent final : public PG
  public:
   explicit GMPServiceParent(GeckoMediaPluginServiceParent* aService);
   virtual ~GMPServiceParent();
 
   ipc::IPCResult RecvGetGMPNodeId(const nsString& aOrigin,
                                   const nsString& aTopLevelOrigin,
                                   const nsString& aGMPName,
                                   nsCString* aID) override;
-  void ActorDestroy(ActorDestroyReason aWhy) override;
+  void ActorDealloc() override;
 
   static bool Create(Endpoint<PGMPServiceParent>&& aGMPService);
 
   ipc::IPCResult RecvLaunchGMP(const nsCString& aNodeId, const nsCString& aAPI,
                                nsTArray<nsCString>&& aTags,
                                nsTArray<ProcessId>&& aAlreadyBridgedTo,
                                uint32_t* aOutPluginId, ProcessId* aOutID,
                                nsCString* aOutDisplayName,
@@ -236,17 +236,15 @@ class GMPServiceParent final : public PG
   ipc::IPCResult RecvLaunchGMPForNodeId(
       const NodeIdData& nodeId, const nsCString& aAPI,
       nsTArray<nsCString>&& aTags, nsTArray<ProcessId>&& aAlreadyBridgedTo,
       uint32_t* aOutPluginId, ProcessId* aOutID, nsCString* aOutDisplayName,
       Endpoint<PGMPContentParent>* aOutEndpoint, nsresult* aOutRv,
       nsCString* aOutErrorDescription) override;
 
  private:
-  void CloseTransport(Monitor* aSyncMonitor, bool* aCompleted);
-
   RefPtr<GeckoMediaPluginServiceParent> mService;
 };
 
 }  // namespace gmp
 }  // namespace mozilla
 
 #endif  // GMPServiceParent_h_
--- a/dom/media/ipc/RDDParent.cpp
+++ b/dom/media/ipc/RDDParent.cpp
@@ -49,25 +49,25 @@ static RDDParent* sRDDParent;
 RDDParent::RDDParent() : mLaunchTime(TimeStamp::Now()) { sRDDParent = this; }
 
 RDDParent::~RDDParent() { sRDDParent = nullptr; }
 
 /* static */
 RDDParent* RDDParent::GetSingleton() { return sRDDParent; }
 
 bool RDDParent::Init(base::ProcessId aParentPid, const char* aParentBuildID,
-                     MessageLoop* aIOLoop, IPC::Channel* aChannel) {
+                     MessageLoop* aIOLoop, UniquePtr<IPC::Channel> aChannel) {
   // Initialize the thread manager before starting IPC. Otherwise, messages
   // may be posted to the main thread and we won't be able to process them.
   if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) {
     return false;
   }
 
   // Now it's safe to start IPC.
-  if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) {
+  if (NS_WARN_IF(!Open(std::move(aChannel), aParentPid, aIOLoop))) {
     return false;
   }
 
   nsDebugImpl::SetMultiprocessMode("RDD");
 
   // This must be checked before any IPDL message, which may hit sentinel
   // errors due to parent and content processes having different
   // versions.
--- a/dom/media/ipc/RDDParent.h
+++ b/dom/media/ipc/RDDParent.h
@@ -17,17 +17,17 @@ class ChildProfilerController;
 class RDDParent final : public PRDDParent {
  public:
   RDDParent();
   ~RDDParent();
 
   static RDDParent* GetSingleton();
 
   bool Init(base::ProcessId aParentPid, const char* aParentBuildID,
-            MessageLoop* aIOLoop, IPC::Channel* aChannel);
+            MessageLoop* aIOLoop, UniquePtr<IPC::Channel> aChannel);
 
   mozilla::ipc::IPCResult RecvInit(nsTArray<GfxVarUpdate>&& vars,
                                    const Maybe<ipc::FileDescriptor>& aBrokerFd,
                                    const bool& aCanRecordReleaseTelemetry);
   mozilla::ipc::IPCResult RecvInitProfiler(
       Endpoint<PProfilerChild>&& aEndpoint);
 
   mozilla::ipc::IPCResult RecvNewContentRemoteDecoderManager(
--- a/dom/media/ipc/RDDProcessHost.cpp
+++ b/dom/media/ipc/RDDProcessHost.cpp
@@ -142,18 +142,18 @@ void RDDProcessHost::InitAfterConnect(bo
   MOZ_ASSERT(mLaunchPhase == LaunchPhase::Waiting);
   MOZ_ASSERT(!mRDDChild);
 
   mLaunchPhase = LaunchPhase::Complete;
 
   if (aSucceeded) {
     mProcessToken = ++sRDDProcessTokenCounter;
     mRDDChild = MakeUnique<RDDChild>(this);
-    DebugOnly<bool> rv =
-        mRDDChild->Open(GetChannel(), base::GetProcId(GetChildProcessHandle()));
+    DebugOnly<bool> rv = mRDDChild->Open(
+        TakeChannel(), base::GetProcId(GetChildProcessHandle()));
     MOZ_ASSERT(rv);
 
     // Only clear mPrefSerializer in the success case to avoid a
     // possible race in the case case of a timeout on Windows launch.
     // See Bug 1555076 comment 7:
     // https://bugzilla.mozilla.org/show_bug.cgi?id=1555076#c7
     mPrefSerializer = nullptr;
 
--- a/dom/media/ipc/RDDProcessImpl.cpp
+++ b/dom/media/ipc/RDDProcessImpl.cpp
@@ -69,14 +69,14 @@ bool RDDProcessImpl::Init(int aArgc, cha
 
   SharedPreferenceDeserializer deserializer;
   if (!deserializer.DeserializeFromSharedMemory(prefsHandle, prefMapHandle,
                                                 prefsLen, prefMapSize)) {
     return false;
   }
 
   return mRDD.Init(ParentPid(), parentBuildID, IOThreadChild::message_loop(),
-                   IOThreadChild::channel());
+                   IOThreadChild::TakeChannel());
 }
 
 void RDDProcessImpl::CleanUp() { NS_ShutdownXPCOM(nullptr); }
 
 }  // namespace mozilla
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -217,17 +217,17 @@ void PluginModuleChild::SetFlashRoamingP
 /* static */ std::wstring PluginModuleChild::GetFlashRoamingPath() {
   return sRoamingPath;
 }
 #endif
 
 bool PluginModuleChild::InitForChrome(const std::string& aPluginFilename,
                                       base::ProcessId aParentPid,
                                       MessageLoop* aIOLoop,
-                                      IPC::Channel* aChannel) {
+                                      UniquePtr<IPC::Channel> aChannel) {
   NS_ASSERTION(aChannel, "need a channel");
 
 #if defined(OS_WIN) && defined(MOZ_SANDBOX)
   MOZ_ASSERT(!sRoamingPath.empty(),
              "Should have already called SetFlashRoamingPath");
 #endif
 
   if (!InitGraphics()) return false;
@@ -273,17 +273,17 @@ bool PluginModuleChild::InitForChrome(co
   {
     nsresult rv = pluginFile.LoadPlugin(&mLibrary);
     if (NS_FAILED(rv)) return false;
   }
   NS_ASSERTION(mLibrary, "couldn't open shared object");
 
   CommonInit();
 
-  if (!Open(aChannel, aParentPid, aIOLoop)) {
+  if (!Open(std::move(aChannel), aParentPid, aIOLoop)) {
     return false;
   }
 
   GetIPCChannel()->SetAbortOnError(true);
 
 #if defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
   mShutdownFunc =
       (NP_PLUGINSHUTDOWN)PR_FindFunctionSymbol(mLibrary, "NP_Shutdown");
--- a/dom/plugins/ipc/PluginModuleChild.h
+++ b/dom/plugins/ipc/PluginModuleChild.h
@@ -116,17 +116,17 @@ class PluginModuleChild : public PPlugin
   // behavior blocked by the sandbox.
   static void SetFlashRoamingPath(const std::wstring& aRoamingPath);
   static std::wstring GetFlashRoamingPath();
 #endif
 
   // aPluginFilename is UTF8, not native-charset!
   bool InitForChrome(const std::string& aPluginFilename,
                      base::ProcessId aParentPid, MessageLoop* aIOLoop,
-                     IPC::Channel* aChannel);
+                     UniquePtr<IPC::Channel> aChannel);
 
   bool InitForContent(Endpoint<PPluginModuleChild>&& aEndpoint);
 
   static bool CreateForContentProcess(Endpoint<PPluginModuleChild>&& aEndpoint);
 
   void CleanUp();
 
   NPError NP_Shutdown();
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -481,17 +481,17 @@ void PluginModuleChromeParent::OnProcess
     return;
   }
   // We may have already been initialized by another call that was waiting
   // for process connect. If so, this function doesn't need to run.
   if (mShutdown) {
     return;
   }
 
-  Open(mSubprocess->GetChannel(),
+  Open(mSubprocess->TakeChannel(),
        base::GetProcId(mSubprocess->GetChildProcessHandle()));
 
   // Request Windows message deferral behavior on our channel. This
   // applies to the top level and all sub plugin protocols since they
   // all share the same channel.
   GetIPCChannel()->SetChannelFlags(
       MessageChannel::REQUIRE_DEFERRED_MESSAGE_PROTECTION);
 
--- a/dom/plugins/ipc/PluginProcessChild.cpp
+++ b/dom/plugins/ipc/PluginProcessChild.cpp
@@ -162,17 +162,17 @@ bool PluginProcessChild::Init(int aArgc,
   mozilla::SandboxTarget::Instance()->StartSandbox();
 #  endif
 #else
 #  error Sorry
 #endif
 
   bool retval = mPlugin.InitForChrome(pluginFilename, ParentPid(),
                                       IOThreadChild::message_loop(),
-                                      IOThreadChild::channel());
+                                      IOThreadChild::TakeChannel());
 #if defined(XP_MACOSX)
   if (nsCocoaFeatures::OnYosemiteOrLater()) {
     // Explicitly turn off CGEvent logging.  This works around bug 1092855.
     // If there are already CGEvents in the log, turning off logging also
     // causes those events to be written to disk.  But at this point no
     // CGEvents have yet been processed.  CGEvents are events (usually
     // input events) pulled from the WindowServer.  An option of 0x80000008
     // turns on CGEvent logging.
--- a/gfx/ipc/GPUParent.cpp
+++ b/gfx/ipc/GPUParent.cpp
@@ -83,25 +83,25 @@ static GPUParent* sGPUParent;
 GPUParent::GPUParent() : mLaunchTime(TimeStamp::Now()) { sGPUParent = this; }
 
 GPUParent::~GPUParent() { sGPUParent = nullptr; }
 
 /* static */
 GPUParent* GPUParent::GetSingleton() { return sGPUParent; }
 
 bool GPUParent::Init(base::ProcessId aParentPid, const char* aParentBuildID,
-                     MessageLoop* aIOLoop, IPC::Channel* aChannel) {
+                     MessageLoop* aIOLoop, UniquePtr<IPC::Channel> aChannel) {
   // Initialize the thread manager before starting IPC. Otherwise, messages
   // may be posted to the main thread and we won't be able to process them.
   if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) {
     return false;
   }
 
   // Now it's safe to start IPC.
-  if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) {
+  if (NS_WARN_IF(!Open(std::move(aChannel), aParentPid, aIOLoop))) {
     return false;
   }
 
   nsDebugImpl::SetMultiprocessMode("GPU");
 
   // This must be checked before any IPDL message, which may hit sentinel
   // errors due to parent and content processes having different
   // versions.
--- a/gfx/ipc/GPUParent.h
+++ b/gfx/ipc/GPUParent.h
@@ -26,17 +26,17 @@ class GPUParent final : public PGPUParen
   static GPUParent* GetSingleton();
 
   // Gets the name of the GPU process, in the format expected by about:memory.
   // There must be a GPU process active, and the caller must be either in that
   // process or the parent process.
   static void GetGPUProcessName(nsACString& aStr);
 
   bool Init(base::ProcessId aParentPid, const char* aParentBuildID,
-            MessageLoop* aIOLoop, IPC::Channel* aChannel);
+            MessageLoop* aIOLoop, UniquePtr<IPC::Channel> aChannel);
   void NotifyDeviceReset();
 
   already_AddRefed<PAPZInputBridgeParent> AllocPAPZInputBridgeParent(
       const LayersId& aLayersId);
 
   mozilla::ipc::IPCResult RecvInit(nsTArray<GfxVarUpdate>&& vars,
                                    const DevicePrefs& devicePrefs,
                                    nsTArray<LayerTreeIdMapping>&& mappings);
--- a/gfx/ipc/GPUProcessHost.cpp
+++ b/gfx/ipc/GPUProcessHost.cpp
@@ -131,18 +131,18 @@ void GPUProcessHost::InitAfterConnect(bo
   MOZ_ASSERT(!mGPUChild);
 
   mLaunchPhase = LaunchPhase::Complete;
   mPrefSerializer = nullptr;
 
   if (aSucceeded) {
     mProcessToken = ++sProcessTokenCounter;
     mGPUChild = MakeUnique<GPUChild>(this);
-    DebugOnly<bool> rv =
-        mGPUChild->Open(GetChannel(), base::GetProcId(GetChildProcessHandle()));
+    DebugOnly<bool> rv = mGPUChild->Open(
+        TakeChannel(), base::GetProcId(GetChildProcessHandle()));
     MOZ_ASSERT(rv);
 
     mGPUChild->Init();
   }
 
   if (mListener) {
     mListener->OnProcessLaunchComplete(this);
   }
--- a/gfx/ipc/GPUProcessImpl.cpp
+++ b/gfx/ipc/GPUProcessImpl.cpp
@@ -69,15 +69,15 @@ bool GPUProcessImpl::Init(int aArgc, cha
 
   SharedPreferenceDeserializer deserializer;
   if (!deserializer.DeserializeFromSharedMemory(prefsHandle, prefMapHandle,
                                                 prefsLen, prefMapSize)) {
     return false;
   }
 
   return mGPU.Init(ParentPid(), parentBuildID, IOThreadChild::message_loop(),
-                   IOThreadChild::channel());
+                   IOThreadChild::TakeChannel());
 }
 
 void GPUProcessImpl::CleanUp() { NS_ShutdownXPCOM(nullptr); }
 
 }  // namespace gfx
 }  // namespace mozilla
--- a/gfx/vr/ipc/VRParent.cpp
+++ b/gfx/vr/ipc/VRParent.cpp
@@ -131,25 +131,25 @@ void VRParent::ActorDestroy(ActorDestroy
   CrashReporterClient::DestroySingleton();
   // Only calling XRE_ShutdownChildProcess() at the child process
   // instead of the main process. Otherwise, it will close all child processes
   // that are spawned from the main process.
   XRE_ShutdownChildProcess();
 }
 
 bool VRParent::Init(base::ProcessId aParentPid, const char* aParentBuildID,
-                    MessageLoop* aIOLoop, IPC::Channel* aChannel) {
+                    MessageLoop* aIOLoop, UniquePtr<IPC::Channel> aChannel) {
   // Initialize the thread manager before starting IPC. Otherwise, messages
   // may be posted to the main thread and we won't be able to process them.
   if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) {
     return false;
   }
 
   // Now it's safe to start IPC.
-  if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) {
+  if (NS_WARN_IF(!Open(std::move(aChannel), aParentPid, aIOLoop))) {
     return false;
   }
 
   nsDebugImpl::SetMultiprocessMode("VR");
 
   // This must be checked before any IPDL message, which may hit sentinel
   // errors due to parent and content processes having different
   // versions.
@@ -186,9 +186,9 @@ bool VRParent::GetOpenVRControllerAction
 }
 
 bool VRParent::GetOpenVRControllerManifestPath(OpenVRControllerType aType,
                                                nsCString* aPath) {
   return mOpenVRControllerManifest.Get(static_cast<uint32_t>(aType), aPath);
 }
 
 }  // namespace gfx
-}  // namespace mozilla
\ No newline at end of file
+}  // namespace mozilla
--- a/gfx/vr/ipc/VRParent.h
+++ b/gfx/vr/ipc/VRParent.h
@@ -20,17 +20,17 @@ class VRParent final : public PVRParent 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRParent);
 
   friend class PVRParent;
 
  public:
   explicit VRParent();
 
   bool Init(base::ProcessId aParentPid, const char* aParentBuildID,
-            MessageLoop* aIOLoop, IPC::Channel* aChannel);
+            MessageLoop* aIOLoop, UniquePtr<IPC::Channel> aChannel);
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
   bool GetOpenVRControllerActionPath(nsCString* aPath);
   bool GetOpenVRControllerManifestPath(OpenVRControllerType aType,
                                        nsCString* aPath);
 
  protected:
   ~VRParent() = default;
 
--- a/gfx/vr/ipc/VRProcessChild.cpp
+++ b/gfx/vr/ipc/VRProcessChild.cpp
@@ -68,17 +68,17 @@ bool VRProcessChild::Init(int aArgc, cha
   SharedPreferenceDeserializer deserializer;
   if (!deserializer.DeserializeFromSharedMemory(prefsHandle, prefMapHandle,
                                                 prefsLen, prefMapSize)) {
     return false;
   }
 
   sVRParent = new VRParent();
   sVRParent->Init(ParentPid(), parentBuildID, IOThreadChild::message_loop(),
-                  IOThreadChild::channel());
+                  IOThreadChild::TakeChannel());
 
   return true;
 }
 
 void VRProcessChild::CleanUp() {
   sVRParent = nullptr;
   NS_ShutdownXPCOM(nullptr);
-}
\ No newline at end of file
+}
--- a/gfx/vr/ipc/VRProcessParent.cpp
+++ b/gfx/vr/ipc/VRProcessParent.cpp
@@ -152,17 +152,17 @@ bool VRProcessParent::InitAfterConnect(b
           "GPU process haven't connected with the parent process yet"
           "when creating VR process.");
       return false;
     }
 
     mVRChild = MakeUnique<VRChild>(this);
 
     DebugOnly<bool> rv =
-        mVRChild->Open(GetChannel(), base::GetProcId(GetChildProcessHandle()));
+        mVRChild->Open(TakeChannel(), base::GetProcId(GetChildProcessHandle()));
     MOZ_ASSERT(rv);
 
     mVRChild->Init();
 
     if (mListener) {
       mListener->OnProcessLaunchComplete(this);
     }
 
--- a/ipc/chromium/src/chrome/common/child_process_host.h
+++ b/ipc/chromium/src/chrome/common/child_process_host.h
@@ -41,18 +41,18 @@ class ChildProcessHost : public IPC::Cha
   // IPC::Channel::Listener implementation:
   virtual void OnMessageReceived(IPC::Message&& msg) override {}
   virtual void OnChannelConnected(int32_t peer_pid) override {}
   virtual void OnChannelError() override {}
 
   bool opening_channel() { return opening_channel_; }
   const std::wstring& channel_id() { return channel_id_; }
 
-  const IPC::Channel& channel() const { return *channel_; }
   IPC::Channel* channelp() const { return channel_.get(); }
+  mozilla::UniquePtr<IPC::Channel> TakeChannel() { return std::move(channel_); }
 
  private:
   // By using an internal class as the IPC::Channel::Listener, we can intercept
   // OnMessageReceived/OnChannelConnected and do our own processing before
   // calling the subclass' implementation.
   class ListenerHook : public IPC::Channel::Listener {
    public:
     explicit ListenerHook(ChildProcessHost* host);
--- a/ipc/chromium/src/chrome/common/child_thread.h
+++ b/ipc/chromium/src/chrome/common/child_thread.h
@@ -25,17 +25,17 @@ class ChildThread : public IPC::Channel:
 
   // Starts the thread.
   bool Run();
 
  protected:
   // Returns the one child thread.
   static ChildThread* current();
 
-  IPC::Channel* channel() { return channel_.get(); }
+  mozilla::UniquePtr<IPC::Channel> TakeChannel() { return std::move(channel_); }
 
   // Thread implementation.
   virtual void Init() override;
   virtual void CleanUp() override;
 
  private:
   // IPC::Channel::Listener implementation:
   virtual void OnMessageReceived(IPC::Message&& msg) override;
--- a/ipc/glue/GeckoChildProcessHost.h
+++ b/ipc/glue/GeckoChildProcessHost.h
@@ -113,16 +113,17 @@ class GeckoChildProcessHost : public Chi
   // Resolves to the process handle when it's available (see
   // LaunchAndWaitForProcessHandle); use with AsyncLaunch.
   RefPtr<ProcessHandlePromise> WhenProcessHandleReady();
 
   virtual void InitializeChannel();
 
   virtual bool CanShutdown() override { return true; }
 
+  using ChildProcessHost::TakeChannel;
   IPC::Channel* GetChannel() { return channelp(); }
   std::wstring GetChannelId() { return channel_id(); }
 
   // Returns a "borrowed" handle to the child process - the handle returned
   // by this function must not be closed by the caller.
   ProcessHandle GetChildProcessHandle() { return mChildProcessHandle; }
 
   GeckoProcessType GetProcessType() { return mProcessType; }
--- a/ipc/glue/IOThreadChild.h
+++ b/ipc/glue/IOThreadChild.h
@@ -23,19 +23,18 @@ class IOThreadChild : public ChildThread
   {}
 
   ~IOThreadChild() {}
 
   static MessageLoop* message_loop() {
     return IOThreadChild::current()->Thread::message_loop();
   }
 
-  // IOThreadChild owns the returned IPC::Channel.
-  static IPC::Channel* channel() {
-    return IOThreadChild::current()->ChildThread::channel();
+  static UniquePtr<IPC::Channel> TakeChannel() {
+    return IOThreadChild::current()->ChildThread::TakeChannel();
   }
 
  protected:
   static IOThreadChild* current() {
     return static_cast<IOThreadChild*>(ChildThread::current());
   }
 
  private:
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -825,28 +825,29 @@ void MessageChannel::Clear() {
   mMaybeDeferredPendingCount = 0;
 
   mOutOfTurnReplies.clear();
   while (!mDeferred.empty()) {
     mDeferred.pop();
   }
 }
 
-bool MessageChannel::Open(Transport* aTransport, MessageLoop* aIOLoop,
-                          Side aSide) {
+bool MessageChannel::Open(mozilla::UniquePtr<Transport> aTransport,
+                          MessageLoop* aIOLoop, Side aSide) {
   MOZ_ASSERT(!mLink, "Open() called > once");
 
   mMonitor = new RefCountedMonitor();
   mWorkerLoop = MessageLoop::current();
   mWorkerThread = PR_GetCurrentThread();
   mWorkerLoop->AddDestructionObserver(this);
   mListener->OnIPCChannelOpened();
 
   ProcessLink* link = new ProcessLink(this);
-  link->Open(aTransport, aIOLoop, aSide);  // :TODO: n.b.: sets mChild
+  link->Open(std::move(aTransport), aIOLoop,
+             aSide);  // :TODO: n.b.: sets mChild
   mLink = link;
   mIsCrossProcess = true;
   ChannelCountReporter::Increment(mName);
   return true;
 }
 
 bool MessageChannel::Open(MessageChannel* aTargetChan,
                           nsIEventTarget* aEventTarget, Side aSide) {
--- a/ipc/glue/MessageChannel.h
+++ b/ipc/glue/MessageChannel.h
@@ -149,17 +149,17 @@ class MessageChannel : HasResultCodes, M
 
   IToplevelProtocol* Listener() const { return mListener; }
 
   // "Open" from the perspective of the transport layer; the underlying
   // socketpair/pipe should already be created.
   //
   // Returns true if the transport layer was successfully connected,
   // i.e., mChannelState == ChannelConnected.
-  bool Open(Transport* aTransport, MessageLoop* aIOLoop = 0,
+  bool Open(UniquePtr<Transport> aTransport, MessageLoop* aIOLoop = 0,
             Side aSide = UnknownSide);
 
   // "Open" a connection to another thread in the same process.
   //
   // Returns true if the transport layer was successfully connected,
   // i.e., mChannelState == ChannelConnected.
   //
   // For more details on the process of opening a channel between
--- a/ipc/glue/MessageLink.cpp
+++ b/ipc/glue/MessageLink.cpp
@@ -5,16 +5,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/ipc/MessageLink.h"
 #include "mozilla/ipc/MessageChannel.h"
 #include "mozilla/ipc/BrowserProcessSubThread.h"
 #include "mozilla/ipc/ProtocolUtils.h"
 #include "chrome/common/ipc_channel.h"
+#include "base/task.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/DebugOnly.h"
 #include "nsDebug.h"
 #include "nsExceptionHandler.h"
 #include "nsISupportsImpl.h"
 #include "nsPrintfCString.h"
 #include "nsXULAppAPI.h"
@@ -41,38 +42,39 @@ MessageLink::MessageLink(MessageChannel*
 
 MessageLink::~MessageLink() {
 #ifdef DEBUG
   mChan = nullptr;
 #endif
 }
 
 ProcessLink::ProcessLink(MessageChannel* aChan)
-    : MessageLink(aChan),
-      mTransport(nullptr),
-      mIOLoop(nullptr),
-      mExistingListener(nullptr) {}
+    : MessageLink(aChan), mIOLoop(nullptr), mExistingListener(nullptr) {}
 
 ProcessLink::~ProcessLink() {
+  // Dispatch the delete of the transport to the IO thread.
+  RefPtr<DeleteTask<IPC::Channel>> task =
+      new DeleteTask<IPC::Channel>(mTransport.release());
+  XRE_GetIOMessageLoop()->PostTask(task.forget());
+
 #ifdef DEBUG
-  mTransport = nullptr;
   mIOLoop = nullptr;
   mExistingListener = nullptr;
 #endif
 }
 
-void ProcessLink::Open(mozilla::ipc::Transport* aTransport,
-                       MessageLoop* aIOLoop, Side aSide) {
+void ProcessLink::Open(UniquePtr<Transport> aTransport, MessageLoop* aIOLoop,
+                       Side aSide) {
   mChan->AssertWorkerThread();
 
   MOZ_ASSERT(aTransport, "need transport layer");
 
   // FIXME need to check for valid channel
 
-  mTransport = aTransport;
+  mTransport = std::move(aTransport);
 
   // FIXME figure out whether we're in parent or child, grab IO loop
   // appropriately
   bool needOpen = true;
   if (aIOLoop) {
     // We're a child or using the new arguments.  Either way, we
     // need an open.
     needOpen = true;
@@ -152,17 +154,17 @@ void ProcessLink::SendMessage(Message* m
   }
 
   if (!mChan->mIsPostponingSends) {
     mChan->AssertWorkerThread();
   }
   mChan->mMonitor->AssertCurrentThreadOwns();
 
   mIOLoop->PostTask(NewNonOwningRunnableMethod<Message*>(
-      "IPC::Channel::Send", mTransport, &Transport::Send, msg));
+      "IPC::Channel::Send", mTransport.get(), &Transport::Send, msg));
 }
 
 void ProcessLink::SendClose() {
   mChan->AssertWorkerThread();
   mChan->mMonitor->AssertCurrentThreadOwns();
 
   mIOLoop->PostTask(NewNonOwningRunnableMethod(
       "ipc::ProcessLink::OnCloseChannel", this, &ProcessLink::OnCloseChannel));
--- a/ipc/glue/MessageLink.h
+++ b/ipc/glue/MessageLink.h
@@ -7,16 +7,17 @@
 
 #ifndef ipc_glue_MessageLink_h
 #define ipc_glue_MessageLink_h 1
 
 #include "base/basictypes.h"
 #include "base/message_loop.h"
 
 #include "mozilla/WeakPtr.h"
+#include "mozilla/UniquePtr.h"
 #include "mozilla/ipc/Transport.h"
 
 namespace mozilla {
 namespace ipc {
 
 class MessageChannel;
 
 struct HasResultCodes {
@@ -70,17 +71,17 @@ class ProcessLink : public MessageLink, 
 
   // The ProcessLink will register itself as the IPC::Channel::Listener on the
   // transport passed here. If the transport already has a listener registered
   // then a listener chain will be established (the ProcessLink listener
   // methods will be called first and may call some methods on the original
   // listener as well). Once the channel is closed (either via normal shutdown
   // or a pipe error) the chain will be destroyed and the original listener
   // will again be registered.
-  void Open(Transport* aTransport, MessageLoop* aIOLoop, Side aSide);
+  void Open(UniquePtr<Transport> aTransport, MessageLoop* aIOLoop, Side aSide);
 
   // Run on the I/O thread, only when using inter-process link.
   // These methods acquire the monitor and forward to the
   // similarly named methods in AsyncChannel below
   // (OnMessageReceivedFromLink(), etc)
   virtual void OnMessageReceived(Message&& msg) override;
   virtual void OnChannelConnected(int32_t peer_pid) override;
   virtual void OnChannelError() override;
@@ -91,17 +92,17 @@ class ProcessLink : public MessageLink, 
 
   virtual bool Unsound_IsClosed() const override;
   virtual uint32_t Unsound_NumQueuedMessages() const override;
 
  protected:
   void OnChannelConnectError();
 
  protected:
-  Transport* mTransport;
+  UniquePtr<Transport> mTransport;
   MessageLoop* mIOLoop;                    // thread where IO happens
   Transport::Listener* mExistingListener;  // channel's previous listener
 };
 
 class ThreadLink : public MessageLink {
  public:
   ThreadLink(MessageChannel* aChan, MessageChannel* aTargetChan);
   virtual ~ThreadLink();
--- a/ipc/glue/ProtocolUtils.cpp
+++ b/ipc/glue/ProtocolUtils.cpp
@@ -579,24 +579,16 @@ IToplevelProtocol::IToplevelProtocol(con
       mOtherPid(mozilla::ipc::kInvalidProcessId),
       mLastLocalId(0),
       mEventTargetMutex("ProtocolEventTargetMutex"),
       mMiddlemanChannelOverride(nullptr),
       mChannel(aName, this) {
   mToplevel = this;
 }
 
-IToplevelProtocol::~IToplevelProtocol() {
-  if (mTrans) {
-    RefPtr<DeleteTask<Transport>> task =
-        new DeleteTask<Transport>(mTrans.release());
-    XRE_GetIOMessageLoop()->PostTask(task.forget());
-  }
-}
-
 base::ProcessId IToplevelProtocol::OtherPid() const {
   base::ProcessId pid = OtherPidMaybeInvalid();
   MOZ_RELEASE_ASSERT(pid != kInvalidProcessId);
   return pid;
 }
 
 void IToplevelProtocol::SetOtherProcessId(base::ProcessId aOtherPid) {
   // When recording an execution, all communication we do is forwarded from
@@ -605,21 +597,21 @@ void IToplevelProtocol::SetOtherProcessI
   if (recordreplay::IsRecordingOrReplaying() &&
       aOtherPid == recordreplay::child::MiddlemanProcessId()) {
     mOtherPid = recordreplay::child::ParentProcessId();
   } else {
     mOtherPid = aOtherPid;
   }
 }
 
-bool IToplevelProtocol::Open(mozilla::ipc::Transport* aTransport,
+bool IToplevelProtocol::Open(UniquePtr<Transport> aTransport,
                              base::ProcessId aOtherPid, MessageLoop* aThread,
                              mozilla::ipc::Side aSide) {
   SetOtherProcessId(aOtherPid);
-  return GetIPCChannel()->Open(aTransport, aThread, aSide);
+  return GetIPCChannel()->Open(std::move(aTransport), aThread, aSide);
 }
 
 bool IToplevelProtocol::Open(MessageChannel* aChannel,
                              MessageLoop* aMessageLoop,
                              mozilla::ipc::Side aSide) {
   SetOtherProcessId(base::GetCurrentProcId());
   return GetIPCChannel()->Open(aChannel, aMessageLoop->SerialEventTarget(),
                                aSide);
@@ -627,22 +619,16 @@ bool IToplevelProtocol::Open(MessageChan
 
 bool IToplevelProtocol::Open(MessageChannel* aChannel,
                              nsIEventTarget* aEventTarget,
                              mozilla::ipc::Side aSide) {
   SetOtherProcessId(base::GetCurrentProcId());
   return GetIPCChannel()->Open(aChannel, aEventTarget, aSide);
 }
 
-bool IToplevelProtocol::OpenWithAsyncPid(mozilla::ipc::Transport* aTransport,
-                                         MessageLoop* aThread,
-                                         mozilla::ipc::Side aSide) {
-  return GetIPCChannel()->Open(aTransport, aThread, aSide);
-}
-
 bool IToplevelProtocol::OpenOnSameThread(MessageChannel* aChannel, Side aSide) {
   SetOtherProcessId(base::GetCurrentProcId());
   return GetIPCChannel()->OpenOnSameThread(aChannel, aSide);
 }
 
 void IToplevelProtocol::Close() { GetIPCChannel()->Close(); }
 
 void IToplevelProtocol::SetReplyTimeoutMs(int32_t aTimeoutMs) {
--- a/ipc/glue/ProtocolUtils.h
+++ b/ipc/glue/ProtocolUtils.h
@@ -384,17 +384,17 @@ class IToplevelProtocol : public IProtoc
 #endif
 
   template <class PFooSide>
   friend class Endpoint;
 
  protected:
   explicit IToplevelProtocol(const char* aName, ProtocolId aProtoId,
                              Side aSide);
-  ~IToplevelProtocol();
+  ~IToplevelProtocol() = default;
 
  public:
   // Shadow methods on IProtocol which are implemented directly on toplevel
   // actors.
   int32_t Register(IProtocol* aRouted);
   int32_t RegisterID(IProtocol* aRouted, int32_t aId);
   IProtocol* Lookup(int32_t aId);
   void Unregister(int32_t aId);
@@ -426,40 +426,31 @@ class IToplevelProtocol : public IProtoc
                                   nsIEventTarget* aEventTarget);
   void SetEventTargetForRoute(int32_t aRoute, nsIEventTarget* aEventTarget);
   nsIEventTarget* GetActorEventTarget();
   already_AddRefed<nsIEventTarget> GetActorEventTarget(IProtocol* aActor);
 
   ProcessId OtherPid() const;
   void SetOtherProcessId(base::ProcessId aOtherPid);
 
-  // Toplevel protocol specific methods.
-  void SetTransport(UniquePtr<Transport> aTrans) { mTrans = std::move(aTrans); }
-
-  Transport* GetTransport() const { return mTrans.get(); }
-
   virtual void OnChannelClose() = 0;
   virtual void OnChannelError() = 0;
   virtual void ProcessingError(Result aError, const char* aMsgName) {}
   virtual void OnChannelConnected(int32_t peer_pid) {}
 
-  bool Open(mozilla::ipc::Transport* aTransport, base::ProcessId aOtherPid,
+  bool Open(UniquePtr<Transport> aTransport, base::ProcessId aOtherPid,
             MessageLoop* aThread = nullptr,
             mozilla::ipc::Side aSide = mozilla::ipc::UnknownSide);
 
   bool Open(MessageChannel* aChannel, MessageLoop* aMessageLoop,
             mozilla::ipc::Side aSide = mozilla::ipc::UnknownSide);
 
   bool Open(MessageChannel* aChannel, nsIEventTarget* aEventTarget,
             mozilla::ipc::Side aSide = mozilla::ipc::UnknownSide);
 
-  bool OpenWithAsyncPid(mozilla::ipc::Transport* aTransport,
-                        MessageLoop* aThread = nullptr,
-                        mozilla::ipc::Side aSide = mozilla::ipc::UnknownSide);
-
   // Open a toplevel actor such that both ends of the actor's channel are on
   // the same thread. This method should be called on the thread to perform
   // the link.
   //
   // WARNING: Attempting to send a sync or intr message on the same thread
   // will crash.
   bool OpenOnSameThread(MessageChannel* aChannel,
                         mozilla::ipc::Side aSide = mozilla::ipc::UnknownSide);
@@ -551,17 +542,16 @@ class IToplevelProtocol : public IProtoc
     return nullptr;
   }
 
  private:
   base::ProcessId OtherPidMaybeInvalid() const { return mOtherPid; }
 
   int32_t NextId();
 
-  UniquePtr<Transport> mTrans;
   base::ProcessId mOtherPid;
 
   // NOTE NOTE NOTE
   // Used to be on mState
   int32_t mLastLocalId;
   IDMap<IProtocol*> mActorMap;
   IDMap<Shmem::SharedMemory*> mShmemMap;
 
@@ -762,27 +752,27 @@ class Endpoint {
       // middleman process instead. Fix this here. If we're replaying
       // we'll see the pid of the middleman used while recording.
       MOZ_RELEASE_ASSERT(recordreplay::IsRecordingOrReplaying());
       MOZ_RELEASE_ASSERT(recordreplay::IsReplaying() ||
                          mMyPid == recordreplay::child::MiddlemanProcessId());
       mMyPid = base::GetCurrentProcId();
     }
 
-    UniquePtr<Transport> t = mozilla::ipc::OpenDescriptor(mTransport, mMode);
-    if (!t) {
+    UniquePtr<Transport> transport =
+        mozilla::ipc::OpenDescriptor(mTransport, mMode);
+    if (!transport) {
       return false;
     }
     if (!aActor->Open(
-            t.get(), mOtherPid, XRE_GetIOMessageLoop(),
+            std::move(transport), mOtherPid, XRE_GetIOMessageLoop(),
             mMode == Transport::MODE_SERVER ? ParentSide : ChildSide)) {
       return false;
     }
     mValid = false;
-    aActor->SetTransport(std::move(t));
     return true;
   }
 
   bool IsValid() const { return mValid; }
 
  private:
   friend struct IPC::ParamTraits<Endpoint<PFooSide>>;
 
--- a/ipc/ipdl/test/cxx/IPDLUnitTestProcessChild.cpp
+++ b/ipc/ipdl/test/cxx/IPDLUnitTestProcessChild.cpp
@@ -11,16 +11,16 @@
 #include "nsRegion.h"
 
 using mozilla::ipc::IOThreadChild;
 
 namespace mozilla {
 namespace _ipdltest {
 
 bool IPDLUnitTestProcessChild::Init(int aArgc, char* aArgv[]) {
-  IPDLUnitTestChildInit(IOThreadChild::channel(), ParentPid(),
+  IPDLUnitTestChildInit(IOThreadChild::TakeChannel(), ParentPid(),
                         IOThreadChild::message_loop());
 
   return true;
 }
 
 }  // namespace _ipdltest
 }  // namespace mozilla
--- a/netwerk/ipc/SocketProcessChild.cpp
+++ b/netwerk/ipc/SocketProcessChild.cpp
@@ -64,21 +64,21 @@ SocketProcessChild* SocketProcessChild::
 #if defined(XP_MACOSX)
 extern "C" {
 void CGSShutdownServerConnections();
 };
 #endif
 
 bool SocketProcessChild::Init(base::ProcessId aParentPid,
                               const char* aParentBuildID, MessageLoop* aIOLoop,
-                              IPC::Channel* aChannel) {
+                              UniquePtr<IPC::Channel> aChannel) {
   if (NS_WARN_IF(NS_FAILED(nsThreadManager::get().Init()))) {
     return false;
   }
-  if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) {
+  if (NS_WARN_IF(!Open(std::move(aChannel), aParentPid, aIOLoop))) {
     return false;
   }
   // This must be sent before any IPDL message, which may hit sentinel
   // errors due to parent and content processes having different
   // versions.
   MessageChannel* channel = GetIPCChannel();
   if (channel && !channel->SendBuildIDsMatchMessage(aParentBuildID)) {
     // We need to quit this process if the buildID doesn't match the parent's.
--- a/netwerk/ipc/SocketProcessChild.h
+++ b/netwerk/ipc/SocketProcessChild.h
@@ -26,17 +26,17 @@ class SocketProcessChild final
       public mozilla::ipc::ChildToParentStreamActorManager {
  public:
   SocketProcessChild();
   ~SocketProcessChild();
 
   static SocketProcessChild* GetSingleton();
 
   bool Init(base::ProcessId aParentPid, const char* aParentBuildID,
-            MessageLoop* aIOLoop, IPC::Channel* aChannel);
+            MessageLoop* aIOLoop, UniquePtr<IPC::Channel> aChannel);
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   mozilla::ipc::IPCResult RecvPreferenceUpdate(const Pref& aPref);
   mozilla::ipc::IPCResult RecvRequestMemoryReport(
       const uint32_t& generation, const bool& anonymize,
       const bool& minimizeMemoryUsage,
       const Maybe<mozilla::ipc::FileDescriptor>& DMDFile);
--- a/netwerk/ipc/SocketProcessHost.cpp
+++ b/netwerk/ipc/SocketProcessHost.cpp
@@ -175,17 +175,17 @@ void SocketProcessHost::InitAfterConnect
   MOZ_ASSERT(!mSocketProcessParent);
   MOZ_ASSERT(NS_IsMainThread());
 
   mLaunchPhase = LaunchPhase::Complete;
 
   if (aSucceeded) {
     mSocketProcessParent = MakeUnique<SocketProcessParent>(this);
     DebugOnly<bool> rv = mSocketProcessParent->Open(
-        GetChannel(), base::GetProcId(GetChildProcessHandle()));
+        TakeChannel(), base::GetProcId(GetChildProcessHandle()));
     MOZ_ASSERT(rv);
 
     nsCOMPtr<nsIIOService> ioService(do_GetIOService());
     MOZ_ASSERT(ioService, "No IO service?");
     bool offline = false;
     DebugOnly<nsresult> result = ioService->GetOffline(&offline);
     MOZ_ASSERT(NS_SUCCEEDED(result), "Failed getting offline?");
 
--- a/netwerk/ipc/SocketProcessImpl.cpp
+++ b/netwerk/ipc/SocketProcessImpl.cpp
@@ -78,15 +78,15 @@ bool SocketProcessImpl::Init(int aArgc, 
   SharedPreferenceDeserializer deserializer;
   if (!deserializer.DeserializeFromSharedMemory(prefsHandle, prefMapHandle,
                                                 prefsLen, prefMapSize)) {
     return false;
   }
 
   return mSocketProcessChild.Init(ParentPid(), parentBuildID,
                                   IOThreadChild::message_loop(),
-                                  IOThreadChild::channel());
+                                  IOThreadChild::TakeChannel());
 }
 
 void SocketProcessImpl::CleanUp() { mSocketProcessChild.CleanUp(); }
 
 }  // namespace net
 }  // namespace mozilla
--- a/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.cpp
+++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.cpp
@@ -17,18 +17,18 @@ namespace mozilla {
 RemoteSandboxBrokerChild::RemoteSandboxBrokerChild() {
   nsDebugImpl::SetMultiprocessMode("RemoteSandboxBroker");
 }
 
 RemoteSandboxBrokerChild::~RemoteSandboxBrokerChild() {}
 
 bool RemoteSandboxBrokerChild::Init(base::ProcessId aParentPid,
                                     MessageLoop* aIOLoop,
-                                    IPC::Channel* aChannel) {
-  if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) {
+                                    UniquePtr<IPC::Channel> aChannel) {
+  if (NS_WARN_IF(!Open(std::move(aChannel), aParentPid, aIOLoop))) {
     return false;
   }
   CrashReporterClient::InitSingleton(this);
   return true;
 }
 
 void RemoteSandboxBrokerChild::ActorDestroy(ActorDestroyReason aWhy) {
   if (AbnormalShutdown == aWhy) {
--- a/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.h
+++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.h
@@ -14,17 +14,17 @@ namespace mozilla {
 
 class RemoteSandboxBrokerChild : public PRemoteSandboxBrokerChild {
   friend class PRemoteSandboxBrokerChild;
 
  public:
   RemoteSandboxBrokerChild();
   virtual ~RemoteSandboxBrokerChild();
   bool Init(base::ProcessId aParentPid, MessageLoop* aIOLoop,
-            IPC::Channel* aChannel);
+            UniquePtr<IPC::Channel> aChannel);
 
  private:
   mozilla::ipc::IPCResult AnswerLaunchApp(LaunchParameters&& aParams,
                                           bool* aOutOk, uint64_t* aOutHandle);
 
   void ActorDestroy(ActorDestroyReason aWhy);
   SandboxBroker mSandboxBroker;
 };
--- a/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.cpp
+++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.cpp
@@ -22,17 +22,17 @@ RefPtr<GenericPromise> RemoteSandboxBrok
   mProcess = new RemoteSandboxBrokerProcessParent();
   for (uint64_t handle : aHandlesToShare) {
     mProcess->AddHandleToShare(HANDLE(handle));
   }
 
   // Note: we rely on the caller to keep this instance alive while we launch
   // the process, so that these closures point to valid memory.
   auto resolve = [this](base::ProcessHandle handle) {
-    mOpened = Open(mProcess->GetChannel(), base::GetProcId(handle));
+    mOpened = Open(mProcess->TakeChannel(), base::GetProcId(handle));
     if (!mOpened) {
       mProcess->Destroy();
       mProcess = nullptr;
       return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
     }
     return GenericPromise::CreateAndResolve(true, __func__);
   };
 
--- a/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessChild.cpp
+++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessChild.cpp
@@ -17,16 +17,16 @@ RemoteSandboxBrokerProcessChild::RemoteS
     ProcessId aParentPid)
     : ProcessChild(aParentPid) {}
 
 RemoteSandboxBrokerProcessChild::~RemoteSandboxBrokerProcessChild() {}
 
 bool RemoteSandboxBrokerProcessChild::Init(int aArgc, char* aArgv[]) {
   BackgroundHangMonitor::Startup();
   return mSandboxBrokerChild.Init(ParentPid(), IOThreadChild::message_loop(),
-                                  IOThreadChild::channel());
+                                  IOThreadChild::TakeChannel());
 }
 
 void RemoteSandboxBrokerProcessChild::CleanUp() {
   BackgroundHangMonitor::Shutdown();
 }
 
 }  // namespace mozilla
--- a/toolkit/recordreplay/ipc/ParentForwarding.cpp
+++ b/toolkit/recordreplay/ipc/ParentForwarding.cpp
@@ -342,17 +342,17 @@ static void ForwardingMessageLoopMain(vo
   MOZ_RELEASE_ASSERT(ActiveChildIsRecording());
 
   MessageLoop messageLoop;
   gForwardingMessageLoop = &messageLoop;
 
   gChildProtocol->mOppositeMessageLoop = gForwardingMessageLoop;
 
   gParentProtocol->Open(
-      gRecordingProcess->GetChannel(),
+      gRecordingProcess->TakeChannel(),
       base::GetProcId(gRecordingProcess->GetChildProcessHandle()));
 
   // Notify the main thread that we have finished initialization.
   {
     MonitorAutoLock lock(*gMonitor);
     gParentProtocolOpened = true;
     gMonitor->Notify();
   }