Bug 771765 - Support template content process, part 4: Clone IPC protocol objects that will be up when the template process is ready. r=khuey, r=bent
authorThinker Lee <tlee@mozilla.com>, Cervantes Yu <cyu@mozilla.com>
Mon, 03 Jun 2013 18:14:37 +0800
changeset 149326 21edfc4062023e746a017ae6ef5dcd8c0e85f912
parent 149325 ae442e5de1ad8ac0d89819999173d04c222cf3f2
child 149327 f75dd995b88d5dd7138556073f655ce9576dabf4
push id25382
push userryanvm@gmail.com
push dateMon, 30 Sep 2013 20:47:44 +0000
treeherdermozilla-central@1b8d32bf6058 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey, bent
bugs771765
milestone27.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 771765 - Support template content process, part 4: Clone IPC protocol objects that will be up when the template process is ready. r=khuey, r=bent
dom/indexedDB/ipc/IndexedDBParent.cpp
dom/indexedDB/ipc/IndexedDBParent.h
dom/ipc/ContentParent.h
dom/ipc/CrashReporterParent.cpp
dom/ipc/CrashReporterParent.h
dom/src/storage/DOMStorageIPC.cpp
dom/src/storage/DOMStorageIPC.h
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/CompositorParent.h
gfx/layers/ipc/ImageBridgeParent.cpp
gfx/layers/ipc/ImageBridgeParent.h
gfx/layers/ipc/PImageBridge.ipdl
hal/sandbox/SandboxHal.cpp
ipc/glue/GeckoChildProcessHost.h
ipc/glue/Transport.h
ipc/glue/Transport_posix.cpp
ipc/glue/Transport_win.cpp
js/ipc/JavaScriptParent.cpp
js/ipc/JavaScriptParent.h
netwerk/cookie/CookieServiceParent.cpp
netwerk/cookie/CookieServiceParent.h
netwerk/ipc/NeckoParent.cpp
netwerk/ipc/NeckoParent.h
--- a/dom/indexedDB/ipc/IndexedDBParent.cpp
+++ b/dom/indexedDB/ipc/IndexedDBParent.cpp
@@ -107,16 +107,34 @@ IndexedDBParent::CheckWritePermission(co
 {
   // Write permission assumes read permission is granted as well.
   MOZ_ASSERT(CheckReadPermission(aDatabaseName));
 
   NS_NAMED_LITERAL_CSTRING(permission, PERMISSION_SUFFIX_WRITE);
   return CheckPermissionInternal(aDatabaseName, permission);
 }
 
+mozilla::ipc::IProtocol*
+IndexedDBParent::CloneProtocol(Channel* aChannel,
+                               mozilla::ipc::ProtocolCloneContext* aCtx)
+{
+  MOZ_ASSERT(mManagerContent != nullptr);
+  MOZ_ASSERT(mManagerTab == nullptr);
+  MOZ_ASSERT(!mDisconnected);
+  MOZ_ASSERT(IndexedDatabaseManager::Get());
+  MOZ_ASSERT(IndexedDatabaseManager::IsMainProcess());
+
+  ContentParent* contentParent = aCtx->GetContentParent();
+  nsAutoPtr<PIndexedDBParent> actor(contentParent->AllocPIndexedDBParent());
+  if (!actor || !contentParent->RecvPIndexedDBConstructor(actor)) {
+    return nullptr;
+  }
+  return actor.forget();
+}
+
 bool
 IndexedDBParent::CheckPermissionInternal(const nsAString& aDatabaseName,
                                          const nsDependentCString& aPermission)
 {
   MOZ_ASSERT(!mASCIIOrigin.IsEmpty());
   MOZ_ASSERT(mManagerContent || mManagerTab);
 
   if (mASCIIOrigin.EqualsLiteral(CHROME_ORIGIN)) {
--- a/dom/indexedDB/ipc/IndexedDBParent.h
+++ b/dom/indexedDB/ipc/IndexedDBParent.h
@@ -189,16 +189,20 @@ public:
   }
 
   bool
   CheckReadPermission(const nsAString& aDatabaseName);
 
   bool
   CheckWritePermission(const nsAString& aDatabaseName);
 
+  mozilla::ipc::IProtocol*
+  CloneProtocol(Channel* aChannel,
+                mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
+
 protected:
   bool
   CheckPermissionInternal(const nsAString& aDatabaseName,
                           const nsDependentCString& aPermission);
 
   virtual void
   ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -34,16 +34,17 @@ namespace mozilla {
 namespace ipc {
 class OptionalURIParams;
 class URIParams;
 class TestShellParent;
 } // namespace ipc
 
 namespace jsipc {
 class JavaScriptParent;
+class PJavaScriptParent;
 }
 
 namespace layers {
 class PCompositorParent;
 } // namespace layers
 
 namespace dom {
 
@@ -166,16 +167,49 @@ public:
     /**
      * 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);
 
+    virtual PIndexedDBParent* AllocPIndexedDBParent() MOZ_OVERRIDE;
+    virtual bool
+    RecvPIndexedDBConstructor(PIndexedDBParent* aActor) MOZ_OVERRIDE;
+
+    virtual PCrashReporterParent*
+    AllocPCrashReporterParent(const NativeThreadId& tid,
+                        const uint32_t& processType) MOZ_OVERRIDE;
+    virtual bool
+    RecvPCrashReporterConstructor(PCrashReporterParent* actor,
+                                  const NativeThreadId& tid,
+                                  const uint32_t& processType) MOZ_OVERRIDE;
+
+    virtual PNeckoParent* AllocPNeckoParent() MOZ_OVERRIDE;
+    virtual bool RecvPNeckoConstructor(PNeckoParent* aActor) MOZ_OVERRIDE {
+        return PContentParent::RecvPNeckoConstructor(aActor);
+    }
+
+    virtual PHalParent* AllocPHalParent() MOZ_OVERRIDE;
+    virtual bool RecvPHalConstructor(PHalParent* aActor) MOZ_OVERRIDE {
+        return PContentParent::RecvPHalConstructor(aActor);
+    }
+
+    virtual PStorageParent* AllocPStorageParent() MOZ_OVERRIDE;
+    virtual bool RecvPStorageConstructor(PStorageParent* aActor) MOZ_OVERRIDE {
+        return PContentParent::RecvPStorageConstructor(aActor);
+    }
+    virtual PJavaScriptParent*
+    AllocPJavaScriptParent() MOZ_OVERRIDE;
+    virtual bool
+    RecvPJavaScriptConstructor(PJavaScriptParent* aActor) MOZ_OVERRIDE {
+        return PContentParent::RecvPJavaScriptConstructor(aActor);
+    }
+
 protected:
     void OnChannelConnected(int32_t pid) MOZ_OVERRIDE;
     virtual void ActorDestroy(ActorDestroyReason why);
 
     bool ShouldContinueFromReplyTimeout() MOZ_OVERRIDE;
 
 private:
     static nsDataHashtable<nsStringHashKey, ContentParent*> *sAppContentParents;
@@ -257,56 +291,43 @@ private:
     AllocPImageBridgeParent(mozilla::ipc::Transport* aTransport,
                             base::ProcessId aOtherProcess) MOZ_OVERRIDE;
 
     virtual bool RecvGetProcessAttributes(uint64_t* aId,
                                           bool* aIsForApp,
                                           bool* aIsForBrowser) MOZ_OVERRIDE;
     virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline) MOZ_OVERRIDE;
 
-    virtual mozilla::jsipc::PJavaScriptParent* AllocPJavaScriptParent();
     virtual bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*);
 
     virtual PBrowserParent* AllocPBrowserParent(const IPCTabContext& aContext,
                                                 const uint32_t& aChromeFlags);
     virtual bool DeallocPBrowserParent(PBrowserParent* frame);
 
     virtual PDeviceStorageRequestParent* AllocPDeviceStorageRequestParent(const DeviceStorageParams&);
     virtual bool DeallocPDeviceStorageRequestParent(PDeviceStorageRequestParent*);
 
     virtual PBlobParent* AllocPBlobParent(const BlobConstructorParams& aParams);
     virtual bool DeallocPBlobParent(PBlobParent*);
 
-    virtual PCrashReporterParent* AllocPCrashReporterParent(const NativeThreadId& tid,
-                                                            const uint32_t& processType);
     virtual bool DeallocPCrashReporterParent(PCrashReporterParent* crashreporter);
-    virtual bool RecvPCrashReporterConstructor(PCrashReporterParent* actor,
-                                               const NativeThreadId& tid,
-                                               const uint32_t& processType);
 
     virtual bool RecvGetRandomValues(const uint32_t& length,
                                      InfallibleTArray<uint8_t>* randomValues);
 
-    virtual PHalParent* AllocPHalParent() MOZ_OVERRIDE;
     virtual bool DeallocPHalParent(PHalParent*) MOZ_OVERRIDE;
 
-    virtual PIndexedDBParent* AllocPIndexedDBParent();
-
     virtual bool DeallocPIndexedDBParent(PIndexedDBParent* aActor);
 
-    virtual bool
-    RecvPIndexedDBConstructor(PIndexedDBParent* aActor);
-
     virtual PMemoryReportRequestParent* AllocPMemoryReportRequestParent();
     virtual bool DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor);
 
     virtual PTestShellParent* AllocPTestShellParent();
     virtual bool DeallocPTestShellParent(PTestShellParent* shell);
 
-    virtual PNeckoParent* AllocPNeckoParent();
     virtual bool DeallocPNeckoParent(PNeckoParent* necko);
 
     virtual PExternalHelperAppParent* AllocPExternalHelperAppParent(
             const OptionalURIParams& aUri,
             const nsCString& aMimeContentType,
             const nsCString& aContentDisposition,
             const bool& aForceSave,
             const int64_t& aContentLength,
@@ -315,17 +336,16 @@ private:
     virtual bool DeallocPExternalHelperAppParent(PExternalHelperAppParent* aService);
 
     virtual PSmsParent* AllocPSmsParent();
     virtual bool DeallocPSmsParent(PSmsParent*);
 
     virtual PTelephonyParent* AllocPTelephonyParent();
     virtual bool DeallocPTelephonyParent(PTelephonyParent*);
 
-    virtual PStorageParent* AllocPStorageParent();
     virtual bool DeallocPStorageParent(PStorageParent* aActor);
 
     virtual PBluetoothParent* AllocPBluetoothParent();
     virtual bool DeallocPBluetoothParent(PBluetoothParent* aActor);
     virtual bool RecvPBluetoothConstructor(PBluetoothParent* aActor);
 
     virtual PFMRadioParent* AllocPFMRadioParent();
     virtual bool DeallocPFMRadioParent(PFMRadioParent* aActor);
--- a/dom/ipc/CrashReporterParent.cpp
+++ b/dom/ipc/CrashReporterParent.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set sw=4 ts=8 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 "CrashReporterParent.h"
+#include "mozilla/dom/ContentParent.h"
 #include "nsXULAppAPI.h"
 
 #include <time.h>
 
 using namespace base;
 
 namespace mozilla {
 namespace dom {
@@ -24,16 +25,39 @@ CrashReporterParent::AnnotateCrashReport
 
 bool
 CrashReporterParent::RecvAppendAppNotes(const nsCString& data)
 {
     mAppNotes.Append(data);
     return true;
 }
 
+mozilla::ipc::IProtocol*
+CrashReporterParent::CloneProtocol(Channel* aChannel,
+                                   mozilla::ipc::ProtocolCloneContext* aCtx)
+{
+    ContentParent* contentParent = aCtx->GetContentParent();
+    CrashReporter::ThreadId childThreadId = contentParent->Pid();
+    GeckoProcessType childProcessType =
+        contentParent->Process()->GetProcessType();
+
+    nsAutoPtr<PCrashReporterParent> actor(
+        contentParent->AllocPCrashReporterParent(childThreadId,
+                                                 childProcessType)
+    );
+    if (!actor ||
+        !contentParent->RecvPCrashReporterConstructor(actor,
+                                                      childThreadId,
+                                                      childThreadId)) {
+      return nullptr;
+    }
+
+    return actor.forget();
+}
+
 CrashReporterParent::CrashReporterParent()
     :
 #ifdef MOZ_CRASHREPORTER
       mNotes(4),
 #endif
       mStartTime(time(NULL))
     , mInitialized(false)
 {
--- a/dom/ipc/CrashReporterParent.h
+++ b/dom/ipc/CrashReporterParent.h
@@ -75,16 +75,19 @@ public:
  protected:
   virtual bool
     RecvAnnotateCrashReport(const nsCString& key, const nsCString& data) {
     AnnotateCrashReport(key, data);
     return true;
   }
   virtual bool
     RecvAppendAppNotes(const nsCString& data);
+  virtual mozilla::ipc::IProtocol*
+  CloneProtocol(Channel* aChannel,
+                mozilla::ipc::ProtocolCloneContext *aCtx) MOZ_OVERRIDE;
 
 #ifdef MOZ_CRASHREPORTER
   AnnotationTable mNotes;
 #endif
   nsCString mAppNotes;
   nsString mChildDumpID;
   NativeThreadId mMainThread;
   time_t mStartTime;
--- a/dom/src/storage/DOMStorageIPC.cpp
+++ b/dom/src/storage/DOMStorageIPC.cpp
@@ -3,16 +3,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 "DOMStorageIPC.h"
 
 #include "DOMStorageManager.h"
 
 #include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/ContentParent.h"
 #include "mozilla/unused.h"
 #include "nsIDiskSpaceWatcher.h"
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 // ----------------------------------------------------------------------------
@@ -359,16 +360,28 @@ DOMStorageDBParent::DOMStorageDBParent()
 DOMStorageDBParent::~DOMStorageDBParent()
 {
   DOMStorageObserver* observer = DOMStorageObserver::Self();
   if (observer) {
     observer->RemoveSink(this);
   }
 }
 
+mozilla::ipc::IProtocol*
+DOMStorageDBParent::CloneProtocol(Channel* aChannel,
+                                  mozilla::ipc::ProtocolCloneContext* aCtx)
+{
+  ContentParent* contentParent = aCtx->GetContentParent();
+  nsAutoPtr<PStorageParent> actor(contentParent->AllocPStorageParent());
+  if (!actor || !contentParent->RecvPStorageConstructor(actor)) {
+    return nullptr;
+  }
+  return actor.forget();
+}
+
 DOMStorageDBParent::CacheParentBridge*
 DOMStorageDBParent::NewCache(const nsACString& aScope)
 {
   return new CacheParentBridge(this, aScope);
 }
 
 bool
 DOMStorageDBParent::RecvAsyncPreload(const nsCString& aScope, const bool& aPriority)
--- a/dom/src/storage/DOMStorageIPC.h
+++ b/dom/src/storage/DOMStorageIPC.h
@@ -107,16 +107,20 @@ private:
 // such as cookie cleaning etc to the child process.
 class DOMStorageDBParent MOZ_FINAL : public PStorageParent
                                    , public DOMStorageObserverSink
 {
 public:
   DOMStorageDBParent();
   virtual ~DOMStorageDBParent();
 
+  virtual mozilla::ipc::IProtocol*
+  CloneProtocol(Channel* aChannel,
+                mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
+
   NS_IMETHOD_(nsrefcnt) AddRef(void);
   NS_IMETHOD_(nsrefcnt) Release(void);
 
   void AddIPDLReference();
   void ReleaseIPDLReference();
 
   bool IPCOpen() { return mIPCOpen; }
 
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -44,16 +44,17 @@
 #include "nsThreadUtils.h"              // for NS_IsMainThread
 #include "nsTraceRefcnt.h"              // for MOZ_COUNT_CTOR, etc
 #include "nsXULAppAPI.h"                // for XRE_GetIOMessageLoop
 #ifdef XP_WIN
 #include "mozilla/layers/CompositorD3D11.h"
 #include "mozilla/layers/CompositorD3D9.h"
 #endif
 #include "GeckoProfiler.h"
+#include "mozilla/ipc/ProtocolTypes.h"
 
 using namespace base;
 using namespace mozilla;
 using namespace mozilla::ipc;
 using namespace mozilla::gfx;
 using namespace std;
 
 namespace mozilla {
@@ -864,16 +865,22 @@ class CrossProcessCompositorParent : pub
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CrossProcessCompositorParent)
 public:
   CrossProcessCompositorParent(Transport* aTransport)
     : mTransport(aTransport)
   {}
   virtual ~CrossProcessCompositorParent();
 
+  // IToplevelProtocol::CloneToplevel()
+  virtual IToplevelProtocol*
+  CloneToplevel(const InfallibleTArray<mozilla::ipc::ProtocolFdMapping>& aFds,
+                base::ProcessHandle aPeerProcess,
+                mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
+
   virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
   // FIXME/bug 774388: work out what shutdown protocol we need.
   virtual bool RecvWillStop() MOZ_OVERRIDE { return true; }
   virtual bool RecvStop() MOZ_OVERRIDE { return true; }
   virtual bool RecvPause() MOZ_OVERRIDE { return true; }
   virtual bool RecvResume() MOZ_OVERRIDE { return true; }
   virtual bool RecvNotifyChildCreated(const uint64_t& child) MOZ_OVERRIDE;
@@ -926,16 +933,34 @@ CompositorParent::Create(Transport* aTra
   cpcp->mSelfRef = cpcp;
   CompositorLoop()->PostTask(
     FROM_HERE,
     NewRunnableFunction(OpenCompositor, cpcp.get(),
                         aTransport, handle, XRE_GetIOMessageLoop()));
   return true;
 }
 
+IToplevelProtocol*
+CompositorParent::CloneToplevel(const InfallibleTArray<mozilla::ipc::ProtocolFdMapping>& aFds,
+                                base::ProcessHandle aPeerProcess,
+                                mozilla::ipc::ProtocolCloneContext* aCtx)
+{
+  for (unsigned int i = 0; i < aFds.Length(); i++) {
+    if (aFds[i].protocolId() == (unsigned)GetProtocolId()) {
+      Transport* transport = OpenDescriptor(aFds[i].fd(),
+                                            Transport::MODE_SERVER);
+      PCompositorParent* compositor = Create(transport, base::GetProcId(aPeerProcess));
+      compositor->CloneManagees(this, aCtx);
+      compositor->IToplevelProtocol::SetTransport(transport);
+      return compositor;
+    }
+  }
+  return nullptr;
+}
+
 static void
 UpdateIndirectTree(uint64_t aId, Layer* aRoot, const TargetConfig& aTargetConfig)
 {
   sIndirectLayerTrees[aId].mRoot = aRoot;
   sIndirectLayerTrees[aId].mTargetConfig = aTargetConfig;
 }
 
 /* static */ const CompositorParent::LayerTreeState*
@@ -1025,10 +1050,29 @@ CrossProcessCompositorParent::DeferredDe
 }
 
 CrossProcessCompositorParent::~CrossProcessCompositorParent()
 {
   XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
                                    new DeleteTask<Transport>(mTransport));
 }
 
+IToplevelProtocol*
+CrossProcessCompositorParent::CloneToplevel(const InfallibleTArray<mozilla::ipc::ProtocolFdMapping>& aFds,
+                                            base::ProcessHandle aPeerProcess,
+                                            mozilla::ipc::ProtocolCloneContext* aCtx)
+{
+  for (unsigned int i = 0; i < aFds.Length(); i++) {
+    if (aFds[i].protocolId() == (unsigned)GetProtocolId()) {
+      Transport* transport = OpenDescriptor(aFds[i].fd(),
+                                            Transport::MODE_SERVER);
+      PCompositorParent* compositor =
+        CompositorParent::Create(transport, base::GetProcId(aPeerProcess));
+      compositor->CloneManagees(this, aCtx);
+      compositor->IToplevelProtocol::SetTransport(transport);
+      return compositor;
+    }
+  }
+  return nullptr;
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -68,16 +68,22 @@ class CompositorParent : public PComposi
 
 public:
   CompositorParent(nsIWidget* aWidget,
                    bool aUseExternalSurfaceSize = false,
                    int aSurfaceWidth = -1, int aSurfaceHeight = -1);
 
   virtual ~CompositorParent();
 
+  // IToplevelProtocol::CloneToplevel()
+  virtual IToplevelProtocol*
+  CloneToplevel(const InfallibleTArray<mozilla::ipc::ProtocolFdMapping>& aFds,
+                base::ProcessHandle aPeerProcess,
+                mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
+
   virtual bool RecvWillStop() MOZ_OVERRIDE;
   virtual bool RecvStop() MOZ_OVERRIDE;
   virtual bool RecvPause() MOZ_OVERRIDE;
   virtual bool RecvResume() MOZ_OVERRIDE;
   virtual bool RecvNotifyChildCreated(const uint64_t& child) MOZ_OVERRIDE;
   virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
                                 SurfaceDescriptor* aOutSnapshot);
   virtual bool RecvFlushRendering() MOZ_OVERRIDE;
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -180,10 +180,28 @@ MessageLoop * ImageBridgeParent::GetMess
 
 void
 ImageBridgeParent::DeferredDestroy()
 {
   mSelfRef = nullptr;
   // |this| was just destroyed, hands off
 }
 
+IToplevelProtocol*
+ImageBridgeParent::CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds,
+                                 base::ProcessHandle aPeerProcess,
+                                 mozilla::ipc::ProtocolCloneContext* aCtx)
+{
+  for (unsigned int i = 0; i < aFds.Length(); i++) {
+    if (aFds[i].protocolId() == (int)GetProtocolId()) {
+      Transport* transport = OpenDescriptor(aFds[i].fd(),
+                                            Transport::MODE_SERVER);
+      PImageBridgeParent* bridge = Create(transport, base::GetProcId(aPeerProcess));
+      bridge->CloneManagees(this, aCtx);
+      bridge->IToplevelProtocol::SetTransport(transport);
+      return bridge;
+    }
+  }
+  return nullptr;
+}
+
 } // layers
 } // mozilla
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -83,16 +83,22 @@ public:
     return AllocUnsafeShmem(aSize, aType, aShmem);
   }
 
   void DeallocShmem(ipc::Shmem& aShmem) MOZ_OVERRIDE
   {
     PImageBridgeParent::DeallocShmem(aShmem);
   }
 
+  // Overriden from IToplevelProtocol
+  IToplevelProtocol*
+  CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds,
+                base::ProcessHandle aPeerProcess,
+                mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
+
 private:
   void DeferredDestroy();
 
   MessageLoop* mMessageLoop;
   Transport* mTransport;
   // This keeps us alive until ActorDestroy(), at which point we do a
   // deferred destruction of ourselves.
   nsRefPtr<ImageBridgeParent> mSelfRef;
--- a/gfx/layers/ipc/PImageBridge.ipdl
+++ b/gfx/layers/ipc/PImageBridge.ipdl
@@ -2,16 +2,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 LayersSurfaces;
 include LayersMessages;
 include protocol PGrallocBuffer;
 include protocol PCompositable;
+include ProtocolTypes;
 
 include "mozilla/layers/CompositorTypes.h";
 include "mozilla/GfxMessageUtils.h";
 
 using ImageHandle;
 using mozilla::layers::TextureInfo;
 
 namespace mozilla {
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -2,16 +2,17 @@
 /* vim: set sw=2 ts=8 et 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 "Hal.h"
 #include "mozilla/AppProcessChecker.h"
 #include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/ContentParent.h"
 #include "mozilla/hal_sandbox/PHalChild.h"
 #include "mozilla/hal_sandbox/PHalParent.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/battery/Types.h"
 #include "mozilla/dom/network/Types.h"
 #include "mozilla/dom/ScreenOrientation.h"
 #include "mozilla/Observer.h"
@@ -810,16 +811,28 @@ public:
   RecvFactoryReset()
   {
     if (!AssertAppProcessPermission(this, "power")) {
       return false;
     }
     hal::FactoryReset();
     return true;
   }
+
+  virtual mozilla::ipc::IProtocol*
+  CloneProtocol(Channel* aChannel,
+                mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE
+  {
+    ContentParent* contentParent = aCtx->GetContentParent();
+    nsAutoPtr<PHalParent> actor(contentParent->AllocPHalParent());
+    if (!actor || !contentParent->RecvPHalConstructor(actor)) {
+      return nullptr;
+    }
+    return actor.forget();
+  }
 };
 
 class HalChild : public PHalChild {
 public:
   virtual void
   ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE
   {
     sHalChildDestroyed = true;
--- a/ipc/glue/GeckoChildProcessHost.h
+++ b/ipc/glue/GeckoChildProcessHost.h
@@ -88,16 +88,20 @@ public:
   base::WaitableEvent* GetShutDownEvent() {
     return GetProcessEvent();
   }
 
   ProcessHandle GetChildProcessHandle() {
     return mChildProcessHandle;
   }
 
+  GeckoProcessType GetProcessType() {
+    return mProcessType;
+  }
+
 #ifdef XP_MACOSX
   task_t GetChildTask() {
     return mChildTask;
   }
 #endif
 
   /**
    * Must run on the IO thread.  Cause the OS process to exit and
--- a/ipc/glue/Transport.h
+++ b/ipc/glue/Transport.h
@@ -15,23 +15,27 @@
 # include "mozilla/ipc/Transport_posix.h"
 #elif OS_WIN
 # include "mozilla/ipc/Transport_win.h"
 #endif
 
 namespace mozilla {
 namespace ipc {
 
+class FileDescriptor;
 
 typedef IPC::Channel Transport;
 
 bool CreateTransport(base::ProcessHandle aProcOne, base::ProcessHandle aProcTwo,
                      TransportDescriptor* aOne, TransportDescriptor* aTwo);
 
 Transport* OpenDescriptor(const TransportDescriptor& aTd,
                           Transport::Mode aMode);
 
+Transport* OpenDescriptor(const FileDescriptor& aFd,
+                          Transport::Mode aMode);
+
 void CloseDescriptor(const TransportDescriptor& aTd);
 
 } // namespace ipc
 } // namespace mozilla
 
 #endif  // mozilla_ipc_Transport_h
--- a/ipc/glue/Transport_posix.cpp
+++ b/ipc/glue/Transport_posix.cpp
@@ -7,16 +7,17 @@
 
 #include <unistd.h>
 
 #include <string>
 
 #include "chrome/common/child_process_info.h"
 
 #include "mozilla/ipc/Transport.h"
+#include "mozilla/ipc/FileDescriptor.h"
 
 using namespace base;
 using namespace std;
 
 namespace mozilla {
 namespace ipc {
 
 bool
@@ -39,27 +40,33 @@ CreateTransport(ProcessHandle /*unused*/
   // The Transport closes these fds when it goes out of scope, so we
   // dup them here
   fd1 = dup(fd1);
   fd2 = dup(fd2);
   if (fd1 < 0 || fd2 < 0) {
     return false;
   }
 
-  aOne->mFd = FileDescriptor(fd1, true/*close after sending*/);
-  aTwo->mFd = FileDescriptor(fd2, true/*close after sending*/);
+  aOne->mFd = base::FileDescriptor(fd1, true/*close after sending*/);
+  aTwo->mFd = base::FileDescriptor(fd2, true/*close after sending*/);
   return true;
 }
 
 Transport*
 OpenDescriptor(const TransportDescriptor& aTd, Transport::Mode aMode)
 {
   return new Transport(aTd.mFd.fd, aMode, nullptr);
 }
 
+Transport*
+OpenDescriptor(const FileDescriptor& aFd, Transport::Mode aMode)
+{
+  return new Transport(aFd.PlatformHandle(), aMode, nullptr);
+}
+
 void
 CloseDescriptor(const TransportDescriptor& aTd)
 {
   close(aTd.mFd.fd);
 }
 
 } // namespace ipc
 } // namespace mozilla
--- a/ipc/glue/Transport_win.cpp
+++ b/ipc/glue/Transport_win.cpp
@@ -53,16 +53,23 @@ CreateTransport(ProcessHandle aProcOne, 
 }
 
 Transport*
 OpenDescriptor(const TransportDescriptor& aTd, Transport::Mode aMode)
 {
   return new Transport(aTd.mPipeName, aTd.mServerPipe, aMode, nullptr);
 }
 
+Transport*
+OpenDescriptor(const FileDescriptor& aFd, Transport::Mode aMode)
+{
+  NS_NOTREACHED("Not implemented!");
+  return nullptr;
+}
+
 void
 CloseDescriptor(const TransportDescriptor& aTd)
 {
   CloseHandle(aTd.mServerPipe);
 }
 
 } // namespace ipc
 } // namespace mozilla
--- a/js/ipc/JavaScriptParent.cpp
+++ b/js/ipc/JavaScriptParent.cpp
@@ -14,16 +14,17 @@
 #include "HeapAPI.h"
 #include "xpcprivate.h"
 #include "mozilla/Casting.h"
 
 using namespace js;
 using namespace JS;
 using namespace mozilla;
 using namespace mozilla::jsipc;
+using namespace mozilla::dom;
 
 JavaScriptParent::JavaScriptParent()
   : refcount_(1),
     inactive_(false)
 {
 }
 
 static inline JavaScriptParent *
@@ -678,8 +679,19 @@ JavaScriptParent::domInstanceOf(JSObject
     if (!CallDOMInstanceOf(objId, prototypeID, depth, &status, bp))
         return false;
 
     if (!status.ok())
         return false;
 
     return true;
 }
+
+mozilla::ipc::IProtocol*
+JavaScriptParent::CloneProtocol(Channel* aChannel, ProtocolCloneContext* aCtx)
+{
+    ContentParent *contentParent = aCtx->GetContentParent();
+    nsAutoPtr<PJavaScriptParent> actor(contentParent->AllocPJavaScriptParent());
+    if (!actor || !contentParent->RecvPJavaScriptConstructor(actor)) {
+        return nullptr;
+    }
+    return actor.forget();
+}
--- a/js/ipc/JavaScriptParent.h
+++ b/js/ipc/JavaScriptParent.h
@@ -72,16 +72,19 @@ class JavaScriptParent
 
     /*
      * Check that |obj| is a DOM wrapper whose prototype chain contains
      * |prototypeID| at depth |depth|.
      */
     static bool DOMInstanceOf(JSObject *obj, int prototypeID, int depth, bool *bp);
     bool domInstanceOf(JSObject *obj, int prototypeID, int depth, bool *bp);
 
+    mozilla::ipc::IProtocol*
+    CloneProtocol(Channel* aChannel, ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
+
   protected:
     JSObject *unwrap(JSContext *cx, ObjectId objId);
 
   private:
     bool makeId(JSContext *cx, JSObject *obj, ObjectId *idp);
     bool getPropertyNames(JSContext *cx, JS::HandleObject proxy, uint32_t flags,
                           JS::AutoIdVector &props);
     ObjectId idOf(JSObject *obj);
--- a/netwerk/cookie/CookieServiceParent.cpp
+++ b/netwerk/cookie/CookieServiceParent.cpp
@@ -122,11 +122,23 @@ CookieServiceParent::RecvSetCookieString
   nsDependentCString cookieString(aCookieString, 0);
   //TODO: bug 812475, pass a real channel object
   mCookieService->SetCookieStringInternal(hostURI, aIsForeign, cookieString,
                                           aServerTime, aFromHttp, appId,
                                           isInBrowserElement, isPrivate, nullptr);
   return true;
 }
 
+mozilla::ipc::IProtocol*
+CookieServiceParent::CloneProtocol(Channel* aChannel,
+                                   mozilla::ipc::ProtocolCloneContext* aCtx)
+{
+  NeckoParent* manager = aCtx->GetNeckoParent();
+  nsAutoPtr<PCookieServiceParent> actor(manager->AllocPCookieServiceParent());
+  if (!actor || !manager->RecvPCookieServiceConstructor(actor)) {
+    return nullptr;
+  }
+  return actor.forget();
+}
+
 }
 }
 
--- a/netwerk/cookie/CookieServiceParent.h
+++ b/netwerk/cookie/CookieServiceParent.h
@@ -38,16 +38,20 @@ protected:
   virtual bool RecvSetCookieString(const URIParams& aHost,
                                    const bool& aIsForeign,
                                    const nsCString& aCookieString,
                                    const nsCString& aServerTime,
                                    const bool& aFromHttp,
                                    const IPC::SerializedLoadContext&
                                          loadContext) MOZ_OVERRIDE;
 
+  virtual mozilla::ipc::IProtocol*
+  CloneProtocol(Channel* aChannel,
+                mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
+
   nsRefPtr<nsCookieService> mCookieService;
 };
 
 }
 }
 
 #endif // mozilla_net_CookieServiceParent_h
 
--- a/netwerk/ipc/NeckoParent.cpp
+++ b/netwerk/ipc/NeckoParent.cpp
@@ -500,9 +500,29 @@ bool
 NeckoParent::RecvCancelHTMLDNSPrefetch(const nsString& hostname,
                                  const uint16_t& flags,
                                  const nsresult& reason)
 {
   nsHTMLDNSPrefetch::CancelPrefetch(hostname, flags, reason);
   return true;
 }
 
+void
+NeckoParent::CloneManagees(ProtocolBase* aSource,
+                         mozilla::ipc::ProtocolCloneContext* aCtx)
+{
+  aCtx->SetNeckoParent(this); // For cloning protocols managed by this.
+  PNeckoParent::CloneManagees(aSource, aCtx);
+}
+
+mozilla::ipc::IProtocol*
+NeckoParent::CloneProtocol(Channel* aChannel,
+                           mozilla::ipc::ProtocolCloneContext* aCtx)
+{
+  ContentParent* contentParent = aCtx->GetContentParent();
+  nsAutoPtr<PNeckoParent> actor(contentParent->AllocPNeckoParent());
+  if (!actor || !contentParent->RecvPNeckoConstructor(actor)) {
+    return nullptr;
+  }
+  return actor.forget();
+}
+
 }} // mozilla::net
--- a/netwerk/ipc/NeckoParent.h
+++ b/netwerk/ipc/NeckoParent.h
@@ -52,28 +52,37 @@ public:
    */
   MOZ_WARN_UNUSED_RESULT
   static const char*
   CreateChannelLoadContext(PBrowserParent* aBrowser,
                            PContentParent* aContent,
                            const SerializedLoadContext& aSerialized,
                            nsCOMPtr<nsILoadContext> &aResult);
 
+  virtual void
+  CloneManagees(ProtocolBase* aSource,
+              mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
+  virtual PCookieServiceParent* AllocPCookieServiceParent() MOZ_OVERRIDE;
+  virtual bool
+  RecvPCookieServiceConstructor(PCookieServiceParent* aActor) MOZ_OVERRIDE
+  {
+    return PNeckoParent::RecvPCookieServiceConstructor(aActor);
+  }
+
 protected:
   virtual PHttpChannelParent*
     AllocPHttpChannelParent(PBrowserParent*, const SerializedLoadContext&,
                             const HttpChannelCreationArgs& aOpenArgs);
   virtual bool
     RecvPHttpChannelConstructor(
                       PHttpChannelParent* aActor,
                       PBrowserParent* aBrowser,
                       const SerializedLoadContext& aSerialized,
                       const HttpChannelCreationArgs& aOpenArgs);
   virtual bool DeallocPHttpChannelParent(PHttpChannelParent*);
-  virtual PCookieServiceParent* AllocPCookieServiceParent();
   virtual bool DeallocPCookieServiceParent(PCookieServiceParent*);
   virtual PWyciwygChannelParent* AllocPWyciwygChannelParent();
   virtual bool DeallocPWyciwygChannelParent(PWyciwygChannelParent*);
   virtual PFTPChannelParent*
     AllocPFTPChannelParent(PBrowserParent* aBrowser,
                            const SerializedLoadContext& aSerialized,
                            const FTPChannelCreationArgs& aOpenArgs);
   virtual bool
@@ -107,16 +116,21 @@ protected:
                                                const uint16_t& aBacklog,
                                                const nsString& aBinaryType);
   virtual bool DeallocPTCPServerSocketParent(PTCPServerSocketParent*);
   virtual bool RecvHTMLDNSPrefetch(const nsString& hostname,
                                    const uint16_t& flags);
   virtual bool RecvCancelHTMLDNSPrefetch(const nsString& hostname,
                                          const uint16_t& flags,
                                          const nsresult& reason);
+
+  virtual mozilla::ipc::IProtocol*
+  CloneProtocol(Channel* aChannel,
+                mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
+
 private:
   nsCString mCoreAppsBasePath;
   nsCString mWebAppsBasePath;
 };
 
 } // namespace net
 } // namespace mozilla