Bug 782456, part 0: Add the cross-process ImageBridge glue. r=roc
authorChris Jones <jones.chris.g@gmail.com>
Wed, 29 Aug 2012 09:24:48 -0300
changeset 105796 cf396cb6d4af6f1110c4635f8e41db788d82931b
parent 105795 67c5a4852b9f85cb48c40ed2bf8f279b927e0a6a
child 105797 8f22c4560de7c61a4e72c71cbefcce8c989aa349
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewersroc
bugs782456
milestone18.0a1
Bug 782456, part 0: Add the cross-process ImageBridge glue. r=roc
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
gfx/layers/ipc/ImageBridgeChild.cpp
gfx/layers/ipc/ImageBridgeChild.h
gfx/layers/ipc/ImageBridgeParent.cpp
gfx/layers/ipc/ImageBridgeParent.h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -22,16 +22,17 @@
 #include "mozilla/dom/ExternalHelperAppChild.h"
 #include "mozilla/dom/PCrashReporterChild.h"
 #include "mozilla/dom/StorageChild.h"
 #include "mozilla/hal_sandbox/PHalChild.h"
 #include "mozilla/ipc/TestShellChild.h"
 #include "mozilla/ipc/XPCShellEnvironment.h"
 #include "mozilla/jsipc/PContextWrapperChild.h"
 #include "mozilla/layers/CompositorChild.h"
+#include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layers/PCompositorChild.h"
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Attributes.h"
 
 #if defined(MOZ_SYDNEYAUDIO)
 #include "nsAudioStream.h"
 #endif
@@ -411,16 +412,23 @@ ContentChild::DeallocPMemoryReportReques
 
 PCompositorChild*
 ContentChild::AllocPCompositor(mozilla::ipc::Transport* aTransport,
                                base::ProcessId aOtherProcess)
 {
     return CompositorChild::Create(aTransport, aOtherProcess);
 }
 
+PImageBridgeChild*
+ContentChild::AllocPImageBridge(mozilla::ipc::Transport* aTransport,
+                                base::ProcessId aOtherProcess)
+{
+    return ImageBridgeChild::StartUpInChildProcess(aTransport, aOtherProcess);
+}
+
 PBrowserChild*
 ContentChild::AllocPBrowser(const uint32_t& aChromeFlags,
                             const bool& aIsBrowserElement, const AppId& aApp)
 {
     uint32_t appId = aApp.get_uint32_t();
     nsRefPtr<TabChild> iframe = new TabChild(aChromeFlags, aIsBrowserElement,
                                              appId);
     return NS_SUCCEEDED(iframe->Init()) ? iframe.forget().get() : NULL;
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -36,17 +36,16 @@ namespace dom {
 class AlertObserver;
 class PrefObserver;
 class ConsoleListener;
 class PStorageChild;
 class ClonedMessageData;
 
 class ContentChild : public PContentChild
 {
-    typedef layers::PCompositorChild PCompositorChild;
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
     typedef mozilla::ipc::OptionalURIParams OptionalURIParams;
     typedef mozilla::ipc::URIParams URIParams;
 
 public:
     ContentChild();
     virtual ~ContentChild();
 
@@ -65,18 +64,22 @@ public:
         NS_ASSERTION(sSingleton, "not initialized");
         return sSingleton;
     }
 
     const AppInfo& GetAppInfo() {
         return mAppInfo;
     }
 
-    PCompositorChild* AllocPCompositor(mozilla::ipc::Transport* aTransport,
-                                       base::ProcessId aOtherProcess) MOZ_OVERRIDE;
+    PCompositorChild*
+    AllocPCompositor(mozilla::ipc::Transport* aTransport,
+                     base::ProcessId aOtherProcess) MOZ_OVERRIDE;
+    PImageBridgeChild*
+    AllocPImageBridge(mozilla::ipc::Transport* aTransport,
+                      base::ProcessId aOtherProcess) MOZ_OVERRIDE;
 
     virtual PBrowserChild* AllocPBrowser(const uint32_t& aChromeFlags,
                                          const bool& aIsBrowserElement,
                                          const AppId& aAppId);
     virtual bool DeallocPBrowser(PBrowserChild*);
 
     virtual PDeviceStorageRequestChild* AllocPDeviceStorageRequest(const DeviceStorageParams&);
     virtual bool DeallocPDeviceStorageRequest(PDeviceStorageRequestChild*);
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -26,16 +26,17 @@
 #include "mozilla/dom/ExternalHelperAppParent.h"
 #include "mozilla/dom/PMemoryReportRequestParent.h"
 #include "mozilla/dom/StorageParent.h"
 #include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
 #include "mozilla/dom/sms/SmsParent.h"
 #include "mozilla/hal_sandbox/PHalParent.h"
 #include "mozilla/ipc/TestShellParent.h"
 #include "mozilla/layers/CompositorParent.h"
+#include "mozilla/layers/ImageBridgeParent.h"
 #include "mozilla/net/NeckoParent.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Util.h"
 #include "mozilla/unused.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsAppDirectoryServiceDefs.h"
@@ -690,16 +691,21 @@ ContentParent::ContentParent(const nsASt
     // channel, so delivery will happen-before any other messages
     // we send.  The CompositorChild must be created before any
     // PBrowsers are created, because they rely on the Compositor
     // already being around.  (Creation is async, so can't happen
     // on demand.)
     if (useOffMainThreadCompositing) {
         DebugOnly<bool> opened = PCompositor::Open(this);
         MOZ_ASSERT(opened);
+
+        if (Preferences::GetBool("layers.async-video.enabled",false)) {
+            opened = PImageBridge::Open(this);
+            MOZ_ASSERT(opened);
+        }
     }
 
     nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
     nsChromeRegistryChrome* chromeRegistry =
         static_cast<nsChromeRegistryChrome*>(registrySvc.get());
     chromeRegistry->SendRegisteredChrome(this);
     mMessageManager = nsFrameMessageManager::NewProcessMessageManager(this);
 
@@ -1046,16 +1052,23 @@ ContentParent::Observe(nsISupports* aSub
 
 PCompositorParent*
 ContentParent::AllocPCompositor(mozilla::ipc::Transport* aTransport,
                                 base::ProcessId aOtherProcess)
 {
     return CompositorParent::Create(aTransport, aOtherProcess);
 }
 
+PImageBridgeParent*
+ContentParent::AllocPImageBridge(mozilla::ipc::Transport* aTransport,
+                                 base::ProcessId aOtherProcess)
+{
+    return ImageBridgeParent::Create(aTransport, aOtherProcess);
+}
+
 PBrowserParent*
 ContentParent::AllocPBrowser(const uint32_t& aChromeFlags,
                              const bool& aIsBrowserElement, const AppId& aApp)
 {
     // We only use this Alloc() method when the content processes asks
     // us to open a window.  In that case, we're expecting to see the
     // opening PBrowser as its app descriptor, and we can trust the data
     // associated with that PBrowser since it's fully owned by this
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -51,17 +51,16 @@ class ContentParent : public PContentPar
                     , public nsIObserver
                     , public nsIThreadObserver
                     , public nsIDOMGeoPositionCallback
 {
     typedef mozilla::ipc::GeckoChildProcessHost GeckoChildProcessHost;
     typedef mozilla::ipc::OptionalURIParams OptionalURIParams;
     typedef mozilla::ipc::TestShellParent TestShellParent;
     typedef mozilla::ipc::URIParams URIParams;
-    typedef mozilla::layers::PCompositorParent PCompositorParent;
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
 
 public:
     /**
      * Start up the content-process machinery.  This might include
      * scheduling pre-launch tasks.
      */
     static void StartUp();
@@ -150,18 +149,22 @@ private:
     /**
      * Exit the subprocess and vamoose.  After this call IsAlive()
      * will return false and this ContentParent will not be returned
      * by the Get*() funtions.  However, the shutdown sequence itself
      * may be asynchronous.
      */
     void ShutDownProcess();
 
-    PCompositorParent* AllocPCompositor(mozilla::ipc::Transport* aTransport,
-                                        base::ProcessId aOtherProcess) MOZ_OVERRIDE;
+    PCompositorParent*
+    AllocPCompositor(mozilla::ipc::Transport* aTransport,
+                     base::ProcessId aOtherProcess) MOZ_OVERRIDE;
+    PImageBridgeParent*
+    AllocPImageBridge(mozilla::ipc::Transport* aTransport,
+                      base::ProcessId aOtherProcess) MOZ_OVERRIDE;
 
     virtual PBrowserParent* AllocPBrowser(const uint32_t& aChromeFlags,
                                           const bool& aIsBrowserElement,
                                           const AppId& aApp);
     virtual bool DeallocPBrowser(PBrowserParent* frame);
 
     virtual PDeviceStorageRequestParent* AllocPDeviceStorageRequest(const DeviceStorageParams&);
     virtual bool DeallocPDeviceStorageRequest(PDeviceStorageRequestParent*);
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -7,16 +7,17 @@
 include protocol PAudio;
 include protocol PBlob;
 include protocol PBrowser;
 include protocol PCompositor;
 include protocol PCrashReporter;
 include protocol PExternalHelperApp;
 include protocol PDeviceStorageRequest;
 include protocol PHal;
+include protocol PImageBridge;
 include protocol PIndexedDB;
 include protocol PMemoryReportRequest;
 include protocol PNecko;
 include protocol PSms;
 include protocol PStorage;
 include protocol PTestShell;
 include DOMTypes;
 include URIParams;
@@ -148,16 +149,17 @@ struct PrefSetting {
   nsCString name;
   MaybePrefValue defaultValue;
   MaybePrefValue userValue;
 };
 
 rpc protocol PContent
 {
     parent opens PCompositor;
+    parent opens PImageBridge;
 
     manages PAudio;
     manages PBlob;
     manages PBrowser;
     manages PCrashReporter;
     manages PDeviceStorageRequest;
     manages PExternalHelperApp;
     manages PHal;
@@ -321,9 +323,9 @@ parent:
     // Notify the parent of the presence or absence of private docshells
     PrivateDocShellsExist(bool aExist);
 
 both:
      AsyncMessage(nsString aMessage, ClonedMessageData aData);
 };
 
 }
-}
\ No newline at end of file
+}
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -1,25 +1,28 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "base/thread.h"
+
+#include "CompositorParent.h"
 #include "ImageBridgeChild.h"
-#include "ImageContainerChild.h"
-#include "CompositorParent.h"
 #include "ImageBridgeParent.h"
-#include "gfxSharedImageSurface.h"
+#include "ImageContainerChild.h"
 #include "ImageLayers.h"
-#include "base/thread.h"
+#include "gfxSharedImageSurface.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "mozilla/layers/ShadowLayers.h"
+#include "nsXULAppAPI.h"
 
 using namespace base;
+using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace layers {
 
 // Singleton 
 static ImageBridgeChild *sImageBridgeChildSingleton = nullptr;
 static Thread *sImageBridgeChildThread = nullptr;
 
@@ -139,16 +142,51 @@ bool ImageBridgeChild::IsCreated()
 }
 
 void ImageBridgeChild::StartUp()
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
   ImageBridgeChild::StartUpOnThread(new Thread("ImageBridgeChild"));
 }
 
+static void
+ConnectImageBridgeInChildProcess(Transport* aTransport,
+                                 ProcessHandle aOtherProcess)
+{
+  // Bind the IPC channel to the image bridge thread.
+  sImageBridgeChildSingleton->Open(aTransport, aOtherProcess,
+                                   XRE_GetIOMessageLoop(),
+                                   AsyncChannel::Child);
+}
+
+PImageBridgeChild*
+ImageBridgeChild::StartUpInChildProcess(Transport* aTransport,
+                                        ProcessId aOtherProcess)
+{
+  NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
+
+  ProcessHandle processHandle;
+  if (!base::OpenProcessHandle(aOtherProcess, &processHandle)) {
+    return nullptr;
+  }
+
+  sImageBridgeChildThread = new Thread("ImageBridgeChild");
+  if (!sImageBridgeChildThread->Start()) {
+    return nullptr;
+  }
+
+  sImageBridgeChildSingleton = new ImageBridgeChild();
+  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
+    FROM_HERE,
+    NewRunnableFunction(ConnectImageBridgeInChildProcess,
+                        aTransport, processHandle));
+  
+  return sImageBridgeChildSingleton;
+}
+
 void ImageBridgeChild::ShutDown()
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
   if (ImageBridgeChild::IsCreated()) {
     ImageBridgeChild::DestroyBridge();
     delete sImageBridgeChildThread;
     sImageBridgeChildThread = nullptr;
   }
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -79,16 +79,19 @@ public:
   /**
    * Creates the image bridge with a dedicated thread for ImageBridgeChild.
    *
    * We may want to use a specifi thread in the future. In this case, use
    * CreateWithThread instead. 
    */
   static void StartUp();
 
+  static PImageBridgeChild*
+  StartUpInChildProcess(Transport* aTransport, ProcessId aOtherProcess);
+
   /**
    * Destroys the image bridge by calling DestroyBridge, and destroys the 
    * ImageBridge's thread.
    *
    * If you don't want to destroy the thread, call DestroyBridge directly 
    * instead.
    */
   static void ShutDown();
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -1,35 +1,64 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "base/thread.h"
+
+#include "mozilla/layers/CompositorParent.h"
 #include "mozilla/layers/ImageBridgeParent.h"
 #include "mozilla/layers/ImageContainerParent.h"
-#include "mozilla/layers/CompositorParent.h"
+#include "nsTArray.h"
+#include "nsXULAppAPI.h"
 
-#include "base/thread.h"
-#include "nsTArray.h"
+using namespace base;
+using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace layers {
 
 
 ImageBridgeParent::ImageBridgeParent(MessageLoop* aLoop)
 : mMessageLoop(aLoop)
 {
   ImageContainerParent::CreateSharedImageMap();
 }
 
 ImageBridgeParent::~ImageBridgeParent()
 {
   ImageContainerParent::DestroySharedImageMap();
 }
 
+static void
+ConnectImageBridgeInParentProcess(ImageBridgeParent* aBridge,
+                                  Transport* aTransport,
+                                  ProcessHandle aOtherProcess)
+{
+  aBridge->Open(aTransport, aOtherProcess,
+                XRE_GetIOMessageLoop(), AsyncChannel::Parent);
+}
+
+/*static*/ PImageBridgeParent*
+ImageBridgeParent::Create(Transport* aTransport, ProcessId aOtherProcess)
+{
+  ProcessHandle processHandle;
+  if (!base::OpenProcessHandle(aOtherProcess, &processHandle)) {
+    return nullptr;
+  }
+
+  MessageLoop* loop = CompositorParent::CompositorLoop();
+  ImageBridgeParent* bridge = new ImageBridgeParent(loop);
+  loop->PostTask(FROM_HERE,
+                 NewRunnableFunction(ConnectImageBridgeInParentProcess,
+                                     bridge, aTransport, processHandle));
+  return bridge;
+}
+
 bool ImageBridgeParent::RecvStop()
 {
   int numChildren = ManagedPImageContainerParent().Length();
   for (unsigned int i = 0; i < numChildren; ++i) {
     static_cast<ImageContainerParent*>(
       ManagedPImageContainerParent()[i]
     )->DoStop();
   }
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -18,16 +18,18 @@ class CompositorParent;
  */
 class ImageBridgeParent : public PImageBridgeParent
 {
 public:
 
   ImageBridgeParent(MessageLoop* aLoop);
   ~ImageBridgeParent();
 
+  static PImageBridgeParent*
+  Create(Transport* aTransport, ProcessId aOtherProcess);
 
   virtual PGrallocBufferParent*
   AllocPGrallocBuffer(const gfxIntSize&, const uint32_t&, const uint32_t&,
                       MaybeMagicGrallocBufferHandle*) MOZ_OVERRIDE;
 
   virtual bool
   DeallocPGrallocBuffer(PGrallocBufferParent* actor) MOZ_OVERRIDE;