Bug 1289650 - Move PAPZ from PContent to PCompositorBridge. r=kats
☠☠ backed out by 14102af32bb8 ☠ ☠
authorRyan Hunt <rhunt@mozilla.com>
Mon, 01 Aug 2016 23:59:00 -0700
changeset 354533 1c7162137f665332129ca242437e079d3a26886d
parent 354532 9fa5ccaa8c6ce7a9b53cc0590654c231570f303e
child 354534 beb32bdb4d1ca6167cd5b6b72c88e5087e9569de
push id1324
push usermtabara@mozilla.com
push dateMon, 16 Jan 2017 13:07:44 +0000
treeherdermozilla-release@a01c49833940 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1289650
milestone51.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 1289650 - Move PAPZ from PContent to PCompositorBridge. r=kats MozReview-Commit-ID: GzU1iEVqSx6
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
gfx/ipc/GPUProcessManager.cpp
gfx/ipc/GPUProcessManager.h
gfx/layers/apz/public/GeckoContentController.h
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/src/AsyncPanZoomController.cpp
gfx/layers/apz/test/gtest/APZTestCommon.h
gfx/layers/apz/util/ChromeProcessController.cpp
gfx/layers/apz/util/ChromeProcessController.h
gfx/layers/ipc/APZChild.cpp
gfx/layers/ipc/APZChild.h
gfx/layers/ipc/CompositorBridgeChild.cpp
gfx/layers/ipc/CompositorBridgeChild.h
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/layers/ipc/CompositorBridgeParent.h
gfx/layers/ipc/PAPZ.ipdl
gfx/layers/ipc/PCompositorBridge.ipdl
gfx/layers/ipc/RemoteContentController.cpp
gfx/layers/ipc/RemoteContentController.h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -1155,29 +1155,16 @@ ContentChild::AllocPContentBridgeParent(
 
 PGMPServiceChild*
 ContentChild::AllocPGMPServiceChild(mozilla::ipc::Transport* aTransport,
                                     base::ProcessId aOtherProcess)
 {
   return GMPServiceChild::Create(aTransport, aOtherProcess);
 }
 
-PAPZChild*
-ContentChild::AllocPAPZChild(const TabId& aTabId)
-{
-  return APZChild::Create(aTabId);
-}
-
-bool
-ContentChild::DeallocPAPZChild(PAPZChild* aActor)
-{
-  delete aActor;
-  return true;
-}
-
 bool
 ContentChild::RecvInitCompositor(Endpoint<PCompositorBridgeChild>&& aEndpoint)
 {
   return CompositorBridgeChild::InitForContent(Move(aEndpoint));
 }
 
 bool
 ContentChild::RecvInitImageBridge(Endpoint<PImageBridgeChild>&& aEndpoint)
@@ -1396,16 +1383,23 @@ ContentChild::RecvSetProcessSandbox(cons
 #endif /* XP_LINUX && !OS_ANDROID */
 #endif /* MOZ_CRASHREPORTER */
 #endif /* MOZ_CONTENT_SANDBOX */
 
   return true;
 }
 
 bool
+ContentChild::RecvNotifyLayerAllocated(const dom::TabId& aTabId, const uint64_t& aLayersId)
+{
+  APZChild* apz = APZChild::Create(aTabId);
+  return CompositorBridgeChild::Get()->SendPAPZConstructor(apz, aLayersId);
+}
+
+bool
 ContentChild::RecvSpeakerManagerNotify()
 {
 #ifdef MOZ_WIDGET_GONK
   // Only notify the process which has the SpeakerManager instance.
   RefPtr<SpeakerManagerService> service =
     SpeakerManagerService::GetSpeakerManagerService();
   if (service) {
     service->Notify();
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -153,21 +153,16 @@ public:
   PContentBridgeChild*
   AllocPContentBridgeChild(mozilla::ipc::Transport* transport,
                            base::ProcessId otherProcess) override;
 
   PGMPServiceChild*
   AllocPGMPServiceChild(mozilla::ipc::Transport* transport,
                         base::ProcessId otherProcess) override;
 
-  PAPZChild*
-  AllocPAPZChild(const TabId& aTabId) override;
-  bool
-  DeallocPAPZChild(PAPZChild* aActor) override;
-
   bool
   RecvInitCompositor(Endpoint<PCompositorBridgeChild>&& aEndpoint) override;
   bool
   RecvInitImageBridge(Endpoint<PImageBridgeChild>&& aEndpoint) override;
   bool
   RecvInitVRManager(Endpoint<PVRManagerChild>&& aEndpoint) override;
 
   PSharedBufferManagerChild*
@@ -407,16 +402,18 @@ public:
   virtual PRemoteSpellcheckEngineChild* AllocPRemoteSpellcheckEngineChild() override;
 
   virtual bool DeallocPRemoteSpellcheckEngineChild(PRemoteSpellcheckEngineChild*) override;
 
   virtual bool RecvSetOffline(const bool& offline) override;
 
   virtual bool RecvSetConnectivity(const bool& connectivity) override;
 
+  virtual bool RecvNotifyLayerAllocated(const dom::TabId& aTabId, const uint64_t& aLayersId) override;
+
   virtual bool RecvSpeakerManagerNotify() override;
 
   virtual bool RecvBidiKeyboardNotify(const bool& isLangRTL,
                                       const bool& haveBidiKeyboards) override;
 
   virtual bool RecvNotifyVisited(const URIParams& aURI) override;
 
   // auto remove when alertfinished is received.
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1711,17 +1711,17 @@ ContentParent::AllocateLayerTreeId(Conte
   if (!gfxPlatform::AsyncPanZoomEnabled()) {
     return true;
   }
 
   if (!aContent || !aTopLevel) {
     return false;
   }
 
-  return gpu->UpdateRemoteContentController(*aId, aContent, aTabId, aTopLevel);
+  return aContent->SendNotifyLayerAllocated(aTabId, *aId);
 }
 
 bool
 ContentParent::RecvAllocateLayerTreeId(const ContentParentId& aCpId,
                                        const TabId& aTabId, uint64_t* aId)
 {
   // Protect against spoofing by a compromised child. aCpId must either
   // correspond to the process that this ContentParent represents or be a
@@ -2892,31 +2892,16 @@ ContentParent::Observe(nsISupports* aSub
 
 PGMPServiceParent*
 ContentParent::AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport,
                                       base::ProcessId aOtherProcess)
 {
   return GMPServiceParent::Create(aTransport, aOtherProcess);
 }
 
-PAPZParent*
-ContentParent::AllocPAPZParent(const TabId& aTabId)
-{
-  // The PAPZParent should just be created in the main process and then an IPDL
-  // constructor message sent to hook it up.
-  MOZ_CRASH("This shouldn't be called");
-  return nullptr;
-}
-
-bool
-ContentParent::DeallocPAPZParent(PAPZParent* aActor)
-{
-  return true;
-}
-
 PBackgroundParent*
 ContentParent::AllocPBackgroundParent(Transport* aTransport,
                                       ProcessId aOtherProcess)
 {
   return BackgroundParent::Alloc(this, aTransport, aOtherProcess);
 }
 
 PProcessHangMonitorParent*
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -698,21 +698,16 @@ private:
   static bool AllocateLayerTreeId(ContentParent* aContent,
                                   TabParent* aTopLevel, const TabId& aTabId,
                                   uint64_t* aId);
 
   PGMPServiceParent*
   AllocPGMPServiceParent(mozilla::ipc::Transport* aTransport,
                          base::ProcessId aOtherProcess) override;
 
-  PAPZParent*
-  AllocPAPZParent(const TabId& aTabId) override;
-  bool
-  DeallocPAPZParent(PAPZParent* aActor) override;
-
   PSharedBufferManagerParent*
   AllocPSharedBufferManagerParent(mozilla::ipc::Transport* aTranport,
                                    base::ProcessId aOtherProcess) override;
 
   PBackgroundParent*
   AllocPBackgroundParent(Transport* aTransport, ProcessId aOtherProcess)
                          override;
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -1,15 +1,14 @@
 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8 -*- */
 /* vim: set sw=4 ts=8 et tw=80 ft=cpp : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-include protocol PAPZ;
 include protocol PBackground;
 include protocol PBlob;
 include protocol PBluetooth;
 include protocol PBrowser;
 include protocol PCellBroadcast;
 include protocol PCompositorBridge;
 include protocol PContentBridge;
 include protocol PContentPermissionRequest;
@@ -385,17 +384,16 @@ prio(normal upto urgent) sync protocol P
 {
     parent spawns PPluginModule;
 
     parent opens PProcessHangMonitor;
     parent opens PSharedBufferManager;
     parent opens PGMPService;
     child opens PBackground;
 
-    manages PAPZ;
     manages PBlob;
     manages PBluetooth;
     manages PBrowser;
     manages PCellBroadcast;
     manages PContentPermissionRequest;
     manages PCrashReporter;
     manages PCycleCollectWithLogs;
     manages PDeviceStorageRequest;
@@ -479,16 +477,21 @@ child:
      * usually only be performed zero or one times.  The child may
      * abnormally exit if this fails; the details are OS-specific.
      */
     async SetProcessSandbox(MaybeFileDesc aBroker);
 
     async PMemoryReportRequest(uint32_t generation, bool anonymize,
                                bool minimizeMemoryUsage, MaybeFileDesc DMDFile);
 
+    /**
+     * Sent to notify that aTabId has been allocated aLayersId
+     */
+    async NotifyLayerAllocated(TabId aTabId, uint64_t aLayersId);
+
     async SpeakerManagerNotify();
 
     /**
      * Communication between the PuppetBidiKeyboard and the actual
      * BidiKeyboard hosted by the parent
      */
     async BidiKeyboardNotify(bool isLangRTL, bool haveBidiKeyboards);
 
@@ -499,18 +502,16 @@ child:
      * nsIMemoryInfoDumper.idl
      */
     async PCycleCollectWithLogs(bool dumpAllTraces,
                                 FileDescriptor gcLog,
                                 FileDescriptor ccLog);
 
     async PTestShell();
 
-    async PAPZ(TabId tabId);
-
     async RegisterChrome(ChromePackage[] packages, SubstitutionMapping[] substitutions,
                          OverrideMapping[] overrides, nsCString locale, bool reset);
     async RegisterChromeItem(ChromeRegistryItem item);
 
     async ClearImageCache(bool privateLoader, bool chrome);
 
     async SetOffline(bool offline);
     async SetConnectivity(bool connectivity);
--- a/gfx/ipc/GPUProcessManager.cpp
+++ b/gfx/ipc/GPUProcessManager.cpp
@@ -560,29 +560,16 @@ GPUProcessManager::RequestNotifyLayerTre
 }
 
 void
 GPUProcessManager::SwapLayerTreeObservers(uint64_t aLayer, uint64_t aOtherLayer)
 {
   CompositorBridgeParent::SwapLayerTreeObservers(aLayer, aOtherLayer);
 }
 
-bool
-GPUProcessManager::UpdateRemoteContentController(uint64_t aLayersId,
-                                                 dom::ContentParent* aContentParent,
-                                                 const dom::TabId& aTabId,
-                                                 dom::TabParent* aBrowserParent)
-{
-  return CompositorBridgeParent::UpdateRemoteContentController(
-    aLayersId,
-    aContentParent,
-    aTabId,
-    aBrowserParent);
-}
-
 void
 GPUProcessManager::EnsureVsyncIOThread()
 {
   if (mVsyncIOThread) {
     return;
   }
 
   mVsyncIOThread = new VsyncIOThreadHolder();
--- a/gfx/ipc/GPUProcessManager.h
+++ b/gfx/ipc/GPUProcessManager.h
@@ -110,28 +110,16 @@ public:
   //
   // Must run on the content main thread.
   void DeallocateLayerTreeId(uint64_t aLayersId);
 
   void RequestNotifyLayerTreeReady(uint64_t aLayersId, CompositorUpdateObserver* aObserver);
   void RequestNotifyLayerTreeCleared(uint64_t aLayersId, CompositorUpdateObserver* aObserver);
   void SwapLayerTreeObservers(uint64_t aLayer, uint64_t aOtherLayer);
 
-  // Creates a new RemoteContentController for aTabId. Should only be called on
-  // the main thread.
-  //
-  // aLayersId      The layers id for the browser corresponding to aTabId.
-  // aContentParent The ContentParent for the process that the TabChild for
-  //                aTabId lives in.
-  // aBrowserParent The toplevel TabParent for aTabId.
-  bool UpdateRemoteContentController(uint64_t aLayersId,
-                                     dom::ContentParent* aContentParent,
-                                     const dom::TabId& aTabId,
-                                     dom::TabParent* aBrowserParent);
-
   void OnProcessLaunchComplete(GPUProcessHost* aHost) override;
   void OnProcessUnexpectedShutdown(GPUProcessHost* aHost) override;
 
   // Notify the GPUProcessManager that a top-level PGPU protocol has been
   // terminated. This may be called from any thread.
   void NotifyRemoteActorDestroyed(const uint64_t& aProcessToken);
 
   // Returns access to the PGPU protocol if a GPU process is present.
--- a/gfx/layers/apz/public/GeckoContentController.h
+++ b/gfx/layers/apz/public/GeckoContentController.h
@@ -7,33 +7,27 @@
 #ifndef mozilla_layers_GeckoContentController_h
 #define mozilla_layers_GeckoContentController_h
 
 #include "FrameMetrics.h"               // for FrameMetrics, etc
 #include "Units.h"                      // for CSSPoint, CSSRect, etc
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT_HELPER2
 #include "mozilla/EventForwards.h"      // for Modifiers
 #include "nsISupportsImpl.h"
-#include "ThreadSafeRefcountingWithMainThreadDestruction.h"
 
 namespace mozilla {
 
 class Runnable;
 
 namespace layers {
 
 class GeckoContentController
 {
 public:
-  /**
-   * At least one class deriving from GeckoContentController needs to do
-   * synchronous cleanup on the main thread, so we use
-   * NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION.
-   */
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_MAIN_THREAD_DESTRUCTION(GeckoContentController)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GeckoContentController)
 
   /**
    * Requests a paint of the given FrameMetrics |aFrameMetrics| from Gecko.
    * Implementations per-platform are responsible for actually handling this.
    * This method will always be called on the Gecko main thread.
    */
   virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) = 0;
 
@@ -67,16 +61,26 @@ public:
   /**
    * Schedules a runnable to run on the controller/UI thread at some time
    * in the future.
    * This method must always be called on the controller thread.
    */
   virtual void PostDelayedTask(already_AddRefed<Runnable> aRunnable, int aDelayMs) = 0;
 
   /**
+   * Returns true if we are currently on the thread that can send repaint requests.
+   */
+  virtual bool IsRepaintThread() = 0;
+
+  /**
+   * Runs the given task on the "repaint" thread.
+   */
+  virtual void DispatchToRepaintThread(already_AddRefed<Runnable> aTask) = 0;
+
+  /**
    * APZ uses |FrameMetrics::mCompositionBounds| for hit testing. Sometimes,
    * widget code has knowledge of a touch-sensitive region that should
    * additionally constrain hit testing for all frames associated with the
    * controller. This method allows APZ to query the controller for such a
    * region. A return value of true indicates that the controller has such a
    * region, and it is returned in |aOutRegion|.
    * This method needs to be called on the main thread.
    * TODO: once bug 928833 is implemented, this should be removed, as
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -625,18 +625,18 @@ APZCTreeManager::FlushApzRepaints(uint64
 {
   // Previously, paints were throttled and therefore this method was used to
   // ensure any pending paints were flushed. Now, paints are flushed
   // immediately, so it is safe to simply send a notification now.
   APZCTM_LOG("Flushing repaints for layers id %" PRIu64, aLayersId);
   const CompositorBridgeParent::LayerTreeState* state =
     CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
   MOZ_ASSERT(state && state->mController);
-  NS_DispatchToMainThread(NewRunnableMethod(
-    state->mController, &GeckoContentController::NotifyFlushComplete));
+  state->mController->DispatchToRepaintThread(NewRunnableMethod(
+     state->mController, &GeckoContentController::NotifyFlushComplete));
 }
 
 nsEventStatus
 APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
                                    ScrollableLayerGuid* aOutTargetGuid,
                                    uint64_t* aOutInputBlockId)
 {
   APZThreadUtils::AssertOnControllerThread();
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -2814,29 +2814,33 @@ bool AsyncPanZoomController::IsPannable(
 }
 
 int32_t AsyncPanZoomController::GetLastTouchIdentifier() const {
   RefPtr<GestureEventListener> listener = GetGestureEventListener();
   return listener ? listener->GetLastTouchIdentifier() : -1;
 }
 
 void AsyncPanZoomController::RequestContentRepaint(bool aUserAction) {
-  // Reinvoke this method on the main thread if it's not there already. It's
+  // Reinvoke this method on the repaint thread if it's not there already. It's
   // important to do this before the call to CalculatePendingDisplayPort, so
   // that CalculatePendingDisplayPort uses the most recent available version of
   // mFrameMetrics, just before the paint request is dispatched to content.
-  if (!NS_IsMainThread()) {
+  RefPtr<GeckoContentController> controller = GetGeckoContentController();
+  if (!controller) {
+    return;
+  }
+  if (!controller->IsRepaintThread()) {
     // use the local variable to resolve the function overload.
     auto func = static_cast<void (AsyncPanZoomController::*)(bool)>
         (&AsyncPanZoomController::RequestContentRepaint);
-    NS_DispatchToMainThread(NewRunnableMethod<bool>(this, func, aUserAction));
+    controller->DispatchToRepaintThread(NewRunnableMethod<bool>(this, func, aUserAction));
     return;
   }
 
-  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(controller->IsRepaintThread());
 
   ReentrantMonitorAutoEnter lock(mMonitor);
   ParentLayerPoint velocity = GetVelocityVector();
   mFrameMetrics.SetDisplayPortMargins(CalculatePendingDisplayPort(mFrameMetrics, velocity));
   mFrameMetrics.SetUseDisplayPortMargins(true);
   mFrameMetrics.SetPaintRequestTime(TimeStamp::Now());
   mFrameMetrics.SetRepaintDrivenByUserAction(aUserAction);
   RequestContentRepaint(mFrameMetrics, velocity);
@@ -2852,17 +2856,21 @@ GetDisplayPortRect(const FrameMetrics& a
   baseRect.Inflate(aFrameMetrics.GetDisplayPortMargins() / aFrameMetrics.DisplayportPixelsPerCSSPixel());
   return baseRect;
 }
 
 void
 AsyncPanZoomController::RequestContentRepaint(const FrameMetrics& aFrameMetrics,
                                               const ParentLayerPoint& aVelocity)
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  RefPtr<GeckoContentController> controller = GetGeckoContentController();
+  if (!controller) {
+    return;
+  }
+  MOZ_ASSERT(controller->IsRepaintThread());
 
   // If we're trying to paint what we already think is painted, discard this
   // request since it's a pointless paint.
   ScreenMargin marginDelta = (mLastPaintRequestMetrics.GetDisplayPortMargins()
                            - aFrameMetrics.GetDisplayPortMargins());
   if (fabsf(marginDelta.left) < EPSILON &&
       fabsf(marginDelta.top) < EPSILON &&
       fabsf(marginDelta.right) < EPSILON &&
@@ -2876,21 +2884,16 @@ AsyncPanZoomController::RequestContentRe
       fabsf(aFrameMetrics.GetViewport().width -
             mLastPaintRequestMetrics.GetViewport().width) < EPSILON &&
       fabsf(aFrameMetrics.GetViewport().height -
             mLastPaintRequestMetrics.GetViewport().height) < EPSILON &&
       aFrameMetrics.GetScrollGeneration() == mLastPaintRequestMetrics.GetScrollGeneration()) {
     return;
   }
 
-  RefPtr<GeckoContentController> controller = GetGeckoContentController();
-  if (!controller) {
-    return;
-  }
-
   APZC_LOG_FM(aFrameMetrics, "%p requesting content repaint", this);
   { // scope lock
     MutexAutoLock lock(mCheckerboardEventLock);
     if (mCheckerboardEvent && mCheckerboardEvent->IsRecordingTrace()) {
       std::stringstream info;
       info << " velocity " << aVelocity;
       std::string str = info.str();
       mCheckerboardEvent->UpdateRendertraceProperty(
@@ -3581,23 +3584,28 @@ void AsyncPanZoomController::ZoomToRect(
     // Schedule a repaint now, so the new displayport will be painted before the
     // animation finishes.
     ParentLayerPoint velocity(0, 0);
     endZoomToMetrics.SetDisplayPortMargins(
       CalculatePendingDisplayPort(endZoomToMetrics, velocity));
     endZoomToMetrics.SetUseDisplayPortMargins(true);
     endZoomToMetrics.SetPaintRequestTime(TimeStamp::Now());
     endZoomToMetrics.SetRepaintDrivenByUserAction(true);
-    if (NS_IsMainThread()) {
+
+    RefPtr<GeckoContentController> controller = GetGeckoContentController();
+    if (!controller) {
+      return;
+    }
+    if (controller->IsRepaintThread()) {
       RequestContentRepaint(endZoomToMetrics, velocity);
     } else {
       // use a local var to resolve the function overload
       auto func = static_cast<void (AsyncPanZoomController::*)(const FrameMetrics&, const ParentLayerPoint&)>
           (&AsyncPanZoomController::RequestContentRepaint);
-      NS_DispatchToMainThread(
+      controller->DispatchToRepaintThread(
           NewRunnableMethod<FrameMetrics, ParentLayerPoint>(
               this, func, endZoomToMetrics, velocity));
     }
   }
 }
 
 CancelableBlockState*
 AsyncPanZoomController::CurrentInputBlock() const
--- a/gfx/layers/apz/test/gtest/APZTestCommon.h
+++ b/gfx/layers/apz/test/gtest/APZTestCommon.h
@@ -77,16 +77,22 @@ public:
   MOCK_METHOD1(RequestContentRepaint, void(const FrameMetrics&));
   MOCK_METHOD2(RequestFlingSnap, void(const FrameMetrics::ViewID& aScrollId, const mozilla::CSSPoint& aDestination));
   MOCK_METHOD2(AcknowledgeScrollUpdate, void(const FrameMetrics::ViewID&, const uint32_t& aScrollGeneration));
   MOCK_METHOD5(HandleTap, void(TapType, const LayoutDevicePoint&, Modifiers, const ScrollableLayerGuid&, uint64_t));
   // Can't use the macros with already_AddRefed :(
   void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) {
     RefPtr<Runnable> task = aTask;
   }
+  bool IsRepaintThread() {
+    return NS_IsMainThread();
+  }
+  void DispatchToRepaintThread(already_AddRefed<Runnable> aTask) {
+    NS_DispatchToMainThread(Move(aTask));
+  }
   MOCK_METHOD3(NotifyAPZStateChange, void(const ScrollableLayerGuid& aGuid, APZStateChange aChange, int aArg));
   MOCK_METHOD0(NotifyFlushComplete, void());
 };
 
 class MockContentControllerDelayed : public MockContentController {
 public:
   MockContentControllerDelayed()
     : mTime(GetStartupTime())
--- a/gfx/layers/apz/util/ChromeProcessController.cpp
+++ b/gfx/layers/apz/util/ChromeProcessController.cpp
@@ -45,32 +45,44 @@ void
 ChromeProcessController::InitializeRoot()
 {
   APZCCallbackHelper::InitializeRootDisplayport(GetPresShell());
 }
 
 void
 ChromeProcessController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(IsRepaintThread());
 
   FrameMetrics metrics = aFrameMetrics;
   if (metrics.IsRootContent()) {
     APZCCallbackHelper::UpdateRootFrame(metrics);
   } else {
     APZCCallbackHelper::UpdateSubFrame(metrics);
   }
 }
 
 void
 ChromeProcessController::PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs)
 {
   MessageLoop::current()->PostDelayedTask(Move(aTask), aDelayMs);
 }
 
+bool
+ChromeProcessController::IsRepaintThread()
+{
+  return NS_IsMainThread();
+}
+
+void
+ChromeProcessController::DispatchToRepaintThread(already_AddRefed<Runnable> aTask)
+{
+  NS_DispatchToMainThread(Move(aTask));
+}
+
 void
 ChromeProcessController::Destroy()
 {
   if (MessageLoop::current() != mUILoop) {
     mUILoop->PostTask(NewRunnableMethod(this, &ChromeProcessController::Destroy));
     return;
   }
 
@@ -219,11 +231,12 @@ ChromeProcessController::NotifyMozMouseS
   }
 
   APZCCallbackHelper::NotifyMozMouseScrollEvent(aScrollId, aEvent);
 }
 
 void
 ChromeProcessController::NotifyFlushComplete()
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(IsRepaintThread());
+
   APZCCallbackHelper::NotifyFlushComplete(GetPresShell());
 }
--- a/gfx/layers/apz/util/ChromeProcessController.h
+++ b/gfx/layers/apz/util/ChromeProcessController.h
@@ -35,16 +35,18 @@ protected:
 public:
   explicit ChromeProcessController(nsIWidget* aWidget, APZEventState* aAPZEventState, IAPZCTreeManager* aAPZCTreeManager);
   ~ChromeProcessController();
   virtual void Destroy() override;
 
   // GeckoContentController interface
   virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) override;
   virtual void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) override;
+  virtual bool IsRepaintThread() override;
+  virtual void DispatchToRepaintThread(already_AddRefed<Runnable> aTask) override;
   virtual void HandleTap(TapType aType,
                          const mozilla::LayoutDevicePoint& aPoint,
                          Modifiers aModifiers,
                          const ScrollableLayerGuid& aGuid,
                          uint64_t aInputBlockId) override;
   virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
                                     APZStateChange aChange,
                                     int aArg) override;
--- a/gfx/layers/ipc/APZChild.cpp
+++ b/gfx/layers/ipc/APZChild.cpp
@@ -102,22 +102,33 @@ APZChild::RecvRequestContentRepaint(cons
 bool
 APZChild::RecvHandleTap(const TapType& aType,
                         const LayoutDevicePoint& aPoint,
                         const Modifiers& aModifiers,
                         const ScrollableLayerGuid& aGuid,
                         const uint64_t& aInputBlockId,
                         const bool& aCallTakeFocusForClickFromTap)
 {
-  mBrowser->HandleTap(aType, aPoint, aModifiers, aGuid,
+  mBrowser->HandleTap(aType, aPoint - mBrowser->GetChromeDisplacement(), aModifiers, aGuid,
       aInputBlockId, aCallTakeFocusForClickFromTap);
   return true;
 }
 
 bool
+APZChild::RecvNotifyMozMouseScrollEvent(const uint64_t& aLayersId,
+                                        const ViewID& aScrollId,
+                                        const nsString& aEvent)
+{
+  if (mBrowser) {
+    mBrowser->RecvMouseScrollTestEvent(aLayersId, aScrollId, aEvent);
+  }
+  return true;
+}
+
+bool
 APZChild::RecvNotifyAPZStateChange(const ViewID& aViewId,
                                    const APZStateChange& aChange,
                                    const int& aArg)
 {
   return mBrowser->NotifyAPZStateChange(aViewId, aChange, aArg);
 }
 
 bool
@@ -134,17 +145,16 @@ APZChild::RecvNotifyFlushComplete()
 bool
 APZChild::RecvDestroy()
 {
   mDestroyed = true;
   if (mBrowser) {
     mBrowser->SetAPZChild(nullptr);
     mBrowser = nullptr;
   }
-  PAPZChild::Send__delete__(this);
   return true;
 }
 
 void
 APZChild::SetObserver(nsIObserver* aObserver)
 {
   MOZ_ASSERT(!mBrowser);
   mObserver = aObserver;
--- a/gfx/layers/ipc/APZChild.h
+++ b/gfx/layers/ipc/APZChild.h
@@ -32,16 +32,20 @@ public:
 
   bool RecvHandleTap(const TapType& aType,
                      const LayoutDevicePoint& aPoint,
                      const Modifiers& aModifiers,
                      const ScrollableLayerGuid& aGuid,
                      const uint64_t& aInputBlockId,
                      const bool& aCallTakeFocusForClickFromTap) override;
 
+  bool RecvNotifyMozMouseScrollEvent(const uint64_t& aLayersId,
+                                     const ViewID& aScrollId,
+                                     const nsString& aEvent) override;
+
   bool RecvNotifyAPZStateChange(const ViewID& aViewId,
                                 const APZStateChange& aChange,
                                 const int& aArg) override;
 
   bool RecvNotifyFlushComplete() override;
 
   bool RecvDestroy() override;
 
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -8,16 +8,17 @@
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "mozilla/layers/CompositorThread.h"
 #include <stddef.h>                     // for size_t
 #include "ClientLayerManager.h"         // for ClientLayerManager
 #include "base/message_loop.h"          // for MessageLoop
 #include "base/task.h"                  // for NewRunnableMethod, etc
 #include "gfxPrefs.h"
 #include "mozilla/layers/ImageBridgeChild.h"
+#include "mozilla/layers/APZChild.h"
 #include "mozilla/layers/IAPZCTreeManager.h"
 #include "mozilla/layers/APZCTreeManagerChild.h"
 #include "mozilla/layers/LayerTransactionChild.h"
 #include "mozilla/layers/PLayerTransactionChild.h"
 #include "mozilla/layers/TextureClient.h"// for TextureClient
 #include "mozilla/layers/TextureClientPool.h"// for TextureClientPool
 #include "mozilla/gfx/gfxVars.h"
 #include "mozilla/gfx/GPUProcessManager.h"
@@ -1031,16 +1032,31 @@ CompositorBridgeChild::GetAPZCTreeManage
 PAPZCTreeManagerChild*
 CompositorBridgeChild::AllocPAPZCTreeManagerChild(const uint64_t& aLayersId)
 {
   APZCTreeManagerChild* child = new APZCTreeManagerChild();
   child->AddRef();
   return child;
 }
 
+PAPZChild*
+CompositorBridgeChild::AllocPAPZChild(const uint64_t& aLayersId)
+{
+  // We send the constructor manually.
+  MOZ_CRASH("Should not be called");
+  return nullptr;
+}
+
+bool
+CompositorBridgeChild::DeallocPAPZChild(PAPZChild* aActor)
+{
+  delete aActor;
+  return true;
+}
+
 bool
 CompositorBridgeChild::DeallocPAPZCTreeManagerChild(PAPZCTreeManagerChild* aActor)
 {
   APZCTreeManagerChild* parent = static_cast<APZCTreeManagerChild*>(aActor);
   parent->Release();
   return true;
 }
 
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -211,16 +211,19 @@ public:
   PCompositorWidgetChild* AllocPCompositorWidgetChild(const CompositorWidgetInitData& aInitData) override;
   bool DeallocPCompositorWidgetChild(PCompositorWidgetChild* aActor) override;
 
   RefPtr<IAPZCTreeManager> GetAPZCTreeManager(uint64_t aLayerTreeId);
 
   PAPZCTreeManagerChild* AllocPAPZCTreeManagerChild(const uint64_t& aLayersId) override;
   bool DeallocPAPZCTreeManagerChild(PAPZCTreeManagerChild* aActor) override;
 
+  PAPZChild* AllocPAPZChild(const uint64_t& aLayersId) override;
+  bool DeallocPAPZChild(PAPZChild* aActor) override;
+
   virtual ShmemAllocator* AsShmemAllocator() override { return this; }
 
   void ProcessingError(Result aCode, const char* aReason) override;
 
 private:
   // Private destructor, to discourage deletion outside of Release():
   virtual ~CompositorBridgeChild();
 
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -20,17 +20,17 @@
 #include "TreeTraversal.h"              // for ForEachNode
 #ifdef MOZ_WIDGET_GTK
 #include "gfxPlatformGtk.h"             // for gfxPlatform
 #endif
 #include "gfxPrefs.h"                   // for gfxPrefs
 #include "mozilla/AutoRestore.h"        // for AutoRestore
 #include "mozilla/ClearOnShutdown.h"    // for ClearOnShutdown
 #include "mozilla/DebugOnly.h"          // for DebugOnly
-#include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/TabParent.h"
 #include "mozilla/gfx/2D.h"          // for DrawTarget
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/gfx/Rect.h"          // for IntSize
 #include "VRManager.h"                  // for VRManager
 #include "mozilla/ipc/Transport.h"      // for Transport
 #include "mozilla/layers/APZCTreeManager.h"  // for APZCTreeManager
 #include "mozilla/layers/APZCTreeManagerParent.h"  // for APZCTreeManagerParent
 #include "mozilla/layers/APZThreadUtils.h"  // for APZCTreeManager
@@ -1360,16 +1360,28 @@ CompositorBridgeParent::AllocPAPZCTreeMa
 }
 
 bool
 CompositorBridgeParent::DeallocPAPZCTreeManagerParent(PAPZCTreeManagerParent* aActor)
 {
   return false;
 }
 
+PAPZParent*
+CompositorBridgeParent::AllocPAPZParent(const uint64_t& aLayersId)
+{
+  return nullptr;
+}
+
+bool
+CompositorBridgeParent::DeallocPAPZParent(PAPZParent* aActor)
+{
+  return false;
+}
+
 bool
 CompositorBridgeParent::RecvAsyncPanZoomEnabled(const uint64_t& aLayersId, bool* aHasAPZ)
 {
   return false;
 }
 
 RefPtr<APZCTreeManager>
 CompositorBridgeParent::GetAPZCTreeManager()
@@ -1771,39 +1783,16 @@ CompositorBridgeParent::RecvNotifyChildC
 void
 CompositorBridgeParent::NotifyChildCreated(uint64_t aChild)
 {
   sIndirectLayerTreesLock->AssertCurrentThreadOwns();
   sIndirectLayerTrees[aChild].mParent = this;
   sIndirectLayerTrees[aChild].mLayerManager = mLayerManager;
 }
 
-/* static */ bool
-CompositorBridgeParent::UpdateRemoteContentController(uint64_t aLayersId,
-                                                      dom::ContentParent* aContent,
-                                                      const dom::TabId& aTabId,
-                                                      dom::TabParent* aTopLevel)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  MonitorAutoLock lock(*sIndirectLayerTreesLock);
-  LayerTreeState& state = sIndirectLayerTrees[aLayersId];
-  // RemoteContentController needs to know the layers id and the top level
-  // TabParent, so we pass that to its constructor here and then set up the
-  // PAPZ protocol by calling SendPAPZConstructor (and pass in the tab id for
-  // the PBrowser that it corresponds to).
-  RefPtr<RemoteContentController> controller =
-    new RemoteContentController(aLayersId, aTopLevel);
-  if (!aContent->SendPAPZConstructor(controller, aTabId)) {
-    return false;
-  }
-  state.mController = controller;
-  return true;
-}
-
 bool
 CompositorBridgeParent::RecvAdoptChild(const uint64_t& child)
 {
   APZCTreeManagerParent* parent;
   {
     MonitorAutoLock lock(*sIndirectLayerTreesLock);
     NotifyChildCreated(child);
     if (sIndirectLayerTrees[child].mLayerTree) {
@@ -2193,16 +2182,19 @@ public:
     return false;
   }
 
   virtual bool RecvAsyncPanZoomEnabled(const uint64_t& aLayersId, bool* aHasAPZ) override;
 
   virtual PAPZCTreeManagerParent* AllocPAPZCTreeManagerParent(const uint64_t& aLayersId) override;
   virtual bool DeallocPAPZCTreeManagerParent(PAPZCTreeManagerParent* aActor) override;
 
+  virtual PAPZParent* AllocPAPZParent(const uint64_t& aLayersId) override;
+  virtual bool DeallocPAPZParent(PAPZParent* aActor) override;
+
   virtual CompositorBridgeParentIPCAllocator* AsCompositorBridgeParentIPCAllocator() override { return this; }
 
   virtual void UpdatePaintTime(LayerTransactionParent* aLayerTree, const TimeDuration& aPaintTime) override {
     uint64_t id = aLayerTree->GetId();
     MOZ_ASSERT(id != 0);
 
     CompositorBridgeParent::LayerTreeState* state =
       CompositorBridgeParent::GetIndirectShadowTree(id);
@@ -2578,16 +2570,41 @@ CrossProcessCompositorBridgeParent::Deal
     state.mApzcTreeManagerParent = nullptr;
   }
 
   delete parent;
 
   return true;
 }
 
+PAPZParent*
+CrossProcessCompositorBridgeParent::AllocPAPZParent(const uint64_t& aLayersId)
+{
+  // Check to see if this child process has access to this layer tree.
+  if (!LayerTreeOwnerTracker::Get()->IsMapped(aLayersId, OtherPid())) {
+    NS_ERROR("Unexpected layers id in AllocPAPZParent; dropping message...");
+    return nullptr;
+  }
+
+  RefPtr<RemoteContentController> controller = new RemoteContentController(aLayersId);
+
+  MonitorAutoLock lock(*sIndirectLayerTreesLock);
+  CompositorBridgeParent::LayerTreeState& state = sIndirectLayerTrees[aLayersId];
+  MOZ_ASSERT(!state.mController);
+  state.mController = controller;
+
+  return controller;
+}
+
+bool
+CrossProcessCompositorBridgeParent::DeallocPAPZParent(PAPZParent* aActor)
+{
+  return true;
+}
+
 bool
 CrossProcessCompositorBridgeParent::RecvNotifyChildCreated(const uint64_t& child)
 {
   MonitorAutoLock lock(*sIndirectLayerTreesLock);
   for (LayerTreeMap::iterator it = sIndirectLayerTrees.begin();
        it != sIndirectLayerTrees.end(); it++) {
     CompositorBridgeParent::LayerTreeState* lts = &it->second;
     if (lts->mParent && lts->mCrossProcessParent == this) {
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -489,16 +489,19 @@ public:
 
   widget::CompositorWidget* GetWidget() { return mWidget; }
 
   void ForceComposeToTarget(gfx::DrawTarget* aTarget, const gfx::IntRect* aRect = nullptr);
 
   PAPZCTreeManagerParent* AllocPAPZCTreeManagerParent(const uint64_t& aLayersId) override;
   bool DeallocPAPZCTreeManagerParent(PAPZCTreeManagerParent* aActor) override;
 
+  PAPZParent* AllocPAPZParent(const uint64_t& aLayersId) override;
+  bool DeallocPAPZParent(PAPZParent* aActor) override;
+
   bool RecvAsyncPanZoomEnabled(const uint64_t& aLayersId, bool* aHasAPZ) override;
 
   RefPtr<APZCTreeManager> GetAPZCTreeManager();
 
   bool AsyncPanZoomEnabled() const {
     return !!mApzcTreeManager;
   }
 
@@ -523,30 +526,16 @@ private:
    * Must run on the content main thread.
    */
   static void DeallocateLayerTreeId(uint64_t aId);
 
   static void RequestNotifyLayerTreeReady(uint64_t aLayersId, CompositorUpdateObserver* aObserver);
   static void RequestNotifyLayerTreeCleared(uint64_t aLayersId, CompositorUpdateObserver* aObserver);
   static void SwapLayerTreeObservers(uint64_t aLayer, uint64_t aOtherLayer);
 
-  /**
-   * Creates a new RemoteContentController for aTabId. Should only be called on
-   * the main thread.
-   *
-   * aLayersId The layers id for the browser corresponding to aTabId.
-   * aContentParent The ContentParent for the process that the TabChild for
-   *                aTabId lives in.
-   * aBrowserParent The toplevel TabParent for aTabId.
-   */
-  static bool UpdateRemoteContentController(uint64_t aLayersId,
-                                            dom::ContentParent* aContentParent,
-                                            const dom::TabId& aTabId,
-                                            dom::TabParent* aBrowserParent);
-
 protected:
   // Protected destructor, to discourage deletion outside of Release():
   virtual ~CompositorBridgeParent();
 
   void DeferredDestroy();
 
   virtual PLayerTransactionParent*
     AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
--- a/gfx/layers/ipc/PAPZ.ipdl
+++ b/gfx/layers/ipc/PAPZ.ipdl
@@ -2,17 +2,17 @@
  * vim: sw=2 ts=8 et :
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include "mozilla/GfxMessageUtils.h";
 
-include protocol PContent;
+include protocol PCompositorBridge;
 
 using mozilla::LayoutDevicePoint from "Units.h";
 using CSSRect from "Units.h";
 using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
 using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
 using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
 using mozilla::layers::MaybeZoomConstraints from "FrameMetrics.h";
 using mozilla::layers::TouchBehaviorFlags from "mozilla/layers/APZUtils.h";
@@ -34,17 +34,17 @@ namespace layers {
  * PBrowser parent actor doesn't necessarily live in the main process, for
  * example with nested browsers). This will typically be set up when the layers
  * id is allocated for the PBrowser.
  *
  * Opened through PContent and runs on the main thread in both parent and child.
  */
 sync protocol PAPZ
 {
-  manager PContent;
+  manager PCompositorBridge;
 
 parent:
 
   async UpdateHitRegion(nsRegion aRegion);
 
   async __delete__();
 
 child:
@@ -52,16 +52,18 @@ child:
 
   // The aCallTakeFocusForClickFromTap argument is used for eSingleTap types,
   // to request that the child take focus before dispatching the mouse events
   // for the tap (otherwise the resulting focus behaviour is incorrect).
   async HandleTap(TapType aType, LayoutDevicePoint point, Modifiers aModifiers,
                   ScrollableLayerGuid aGuid, uint64_t aInputBlockId,
                   bool aCallTakeFocusForClickFromTap);
 
+  async NotifyMozMouseScrollEvent(uint64_t aLayersId, ViewID aScrollId, nsString aEvent);
+
   async NotifyAPZStateChange(ViewID aViewId, APZStateChange aChange, int aArg);
 
   async NotifyFlushComplete();
 
   async Destroy();
 };
 
 } // layers
--- a/gfx/layers/ipc/PCompositorBridge.ipdl
+++ b/gfx/layers/ipc/PCompositorBridge.ipdl
@@ -3,16 +3,17 @@
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include LayersSurfaces;
 include LayersMessages;
 include PlatformWidgetTypes;
+include protocol PAPZ;
 include protocol PAPZCTreeManager;
 include protocol PBrowser;
 include protocol PCompositable;
 include protocol PCompositorWidget;
 include protocol PImageContainer;
 include protocol PLayer;
 include protocol PLayerTransaction;
 include protocol PTexture;
@@ -42,16 +43,17 @@ namespace layers {
 
 /**
  * The PCompositorBridge protocol is used to manage communication between
  * the main thread and the compositor thread context. It's primary
  * purpose is to manage the PLayerTransaction sub protocol.
  */
 sync protocol PCompositorBridge
 {
+  manages PAPZ;
   manages PAPZCTreeManager;
   // A Compositor manages a single Layer Manager (PLayerTransaction)
   manages PLayerTransaction;
   manages PTexture;
   manages PCompositorWidget;
 
 child:
   // The child should invalidate retained layers. This is used for local
@@ -120,16 +122,17 @@ parent:
 
   // When out-of-process, this must be called to finish initialization.
   sync Initialize(uint64_t rootLayerTreeId);
 
   // Returns whether this Compositor has APZ enabled or not.
   sync AsyncPanZoomEnabled(uint64_t layersId) returns (bool aHasAPZ);
 
   // Must be called after Initialize(), and only succeeds if AsyncPanZoomEnabled() is true.
+  async PAPZ(uint64_t layersId);
   async PAPZCTreeManager(uint64_t layersId);
 
   /**
    * Confirmation callback for UpdatePluginConfigurations and HideAllPlugins.
    */
   async RemotePluginsReady();
 
   // Confirmation that the child has invalidated all its layers, and will not
--- a/gfx/layers/ipc/RemoteContentController.cpp
+++ b/gfx/layers/ipc/RemoteContentController.cpp
@@ -23,175 +23,173 @@
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 
 static std::map<uint64_t, RefPtr<RemoteContentController>> sDestroyedControllers;
 
-RemoteContentController::RemoteContentController(uint64_t aLayersId,
-                                                 dom::TabParent* aBrowserParent)
-  : mUILoop(MessageLoop::current())
+RemoteContentController::RemoteContentController(uint64_t aLayersId)
+  : mCompositorThread(MessageLoop::current())
   , mLayersId(aLayersId)
-  , mBrowserParent(aBrowserParent)
+  , mCanSend(true)
   , mMutex("RemoteContentController")
 {
-  MOZ_ASSERT(NS_IsMainThread());
 }
 
 RemoteContentController::~RemoteContentController()
 {
 }
 
 void
 RemoteContentController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  if (CanSend()) {
+  MOZ_ASSERT(IsRepaintThread());
+
+  if (mCanSend) {
     Unused << SendRequestContentRepaint(aFrameMetrics);
   }
 }
 
 void
 RemoteContentController::HandleTap(TapType aTapType,
                                    const LayoutDevicePoint& aPoint,
                                    Modifiers aModifiers,
                                    const ScrollableLayerGuid& aGuid,
                                    uint64_t aInputBlockId)
 {
-  if (MessageLoop::current() != mUILoop) {
-    // We have to send this message from the "UI thread" (main
-    // thread).
-    mUILoop->PostTask(NewRunnableMethod<TapType, LayoutDevicePoint, Modifiers,
+  if (MessageLoop::current() != mCompositorThread) {
+    // We have to send messages from the compositor thread
+    mCompositorThread->PostTask(NewRunnableMethod<TapType, LayoutDevicePoint, Modifiers,
                                         ScrollableLayerGuid, uint64_t>(this,
                                           &RemoteContentController::HandleTap,
                                           aTapType, aPoint, aModifiers, aGuid,
                                           aInputBlockId));
     return;
   }
 
   bool callTakeFocusForClickFromTap = (aTapType == TapType::eSingleTap);
-  if (callTakeFocusForClickFromTap && mBrowserParent) {
-    layout::RenderFrameParent* frame = mBrowserParent->GetRenderFrame();
-    if (frame && mLayersId == frame->GetLayersId()) {
-      // Avoid going over IPC and back for calling TakeFocusForClickFromTap,
-      // since the right RenderFrameParent is living in this process.
-      frame->TakeFocusForClickFromTap();
-      callTakeFocusForClickFromTap = false;
-    }
-  }
 
-  if (CanSend()) {
-    Unused << SendHandleTap(aTapType, mBrowserParent->AdjustTapToChildWidget(aPoint),
+  if (mCanSend) {
+    Unused << SendHandleTap(aTapType, aPoint,
             aModifiers, aGuid, aInputBlockId, callTakeFocusForClickFromTap);
   }
 }
 
 void
 RemoteContentController::PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs)
 {
 #ifdef MOZ_WIDGET_ANDROID
   AndroidBridge::Bridge()->PostTaskToUiThread(Move(aTask), aDelayMs);
 #else
-  (MessageLoop::current() ? MessageLoop::current() : mUILoop)->
+  (MessageLoop::current() ? MessageLoop::current() : mCompositorThread)->
     PostDelayedTask(Move(aTask), aDelayMs);
 #endif
 }
 
 bool
+RemoteContentController::IsRepaintThread()
+{
+  return MessageLoop::current() == mCompositorThread;
+}
+
+void
+RemoteContentController::DispatchToRepaintThread(already_AddRefed<Runnable> aTask)
+{
+  mCompositorThread->PostTask(Move(aTask));
+}
+
+bool
 RemoteContentController::GetTouchSensitiveRegion(CSSRect* aOutRegion)
 {
   MutexAutoLock lock(mMutex);
   if (mTouchSensitiveRegion.IsEmpty()) {
     return false;
   }
 
   *aOutRegion = CSSRect::FromAppUnits(mTouchSensitiveRegion.GetBounds());
   return true;
 }
 
 void
 RemoteContentController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
                                               APZStateChange aChange,
                                               int aArg)
 {
-  if (MessageLoop::current() != mUILoop) {
-    mUILoop->PostTask(NewRunnableMethod<ScrollableLayerGuid,
+  if (MessageLoop::current() != mCompositorThread) {
+    // We have to send messages from the compositor thread
+    mCompositorThread->PostTask(NewRunnableMethod<ScrollableLayerGuid,
                                         APZStateChange,
                                         int>(this,
                                              &RemoteContentController::NotifyAPZStateChange,
                                              aGuid, aChange, aArg));
     return;
   }
-  if (CanSend()) {
+
+  if (mCanSend) {
     Unused << SendNotifyAPZStateChange(aGuid.mScrollId, aChange, aArg);
   }
 }
 
 void
 RemoteContentController::NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId,
                                                    const nsString& aEvent)
 {
-  if (MessageLoop::current() != mUILoop) {
-    mUILoop->PostTask(NewRunnableMethod<FrameMetrics::ViewID,
+  if (MessageLoop::current() != mCompositorThread) {
+    // We have to send messages from the compositor thread
+    mCompositorThread->PostTask(NewRunnableMethod<FrameMetrics::ViewID,
                                         nsString>(this,
                                                   &RemoteContentController::NotifyMozMouseScrollEvent,
                                                   aScrollId, aEvent));
     return;
   }
 
-  if (mBrowserParent) {
-    Unused << mBrowserParent->SendMouseScrollTestEvent(mLayersId, aScrollId, aEvent);
+  if (mCanSend) {
+    Unused << SendNotifyMozMouseScrollEvent(mLayersId, aScrollId, aEvent);
   }
 }
 
 void
 RemoteContentController::NotifyFlushComplete()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-  if (CanSend()) {
+  MOZ_ASSERT(IsRepaintThread());
+
+  if (mCanSend) {
     Unused << SendNotifyFlushComplete();
   }
 }
 
 bool
 RemoteContentController::RecvUpdateHitRegion(const nsRegion& aRegion)
 {
   MutexAutoLock lock(mMutex);
   mTouchSensitiveRegion = aRegion;
   return true;
 }
 
 void
 RemoteContentController::ActorDestroy(ActorDestroyReason aWhy)
 {
-  mBrowserParent = nullptr;
+  mCanSend = false;
 
-  uint64_t key = mLayersId;
-  NS_DispatchToMainThread(NS_NewRunnableFunction([key]() {
-    // sDestroyedControllers may or may not contain the key, depending on
-    // whether or not SendDestroy() was successfully sent out or not.
-    sDestroyedControllers.erase(key);
-  }));
+  // sDestroyedControllers may or may not contain the key, depending on
+  // whether or not SendDestroy() was successfully sent out or not.
+  sDestroyedControllers.erase(mLayersId);
 }
 
 void
 RemoteContentController::Destroy()
 {
-  RefPtr<RemoteContentController> controller = this;
-  NS_DispatchToMainThread(NS_NewRunnableFunction([controller] {
-    if (controller->CanSend()) {
-      // Gfx code is done with this object, and it will probably get destroyed
-      // soon. However, if CanSend() is true, ActorDestroy has not yet been
-      // called, which means IPC code still has a handle to this object. We need
-      // to keep it alive until we get the ActorDestroy call, either via the
-      // __delete__ message or via IPC shutdown on our end.
-      uint64_t key = controller->mLayersId;
-      MOZ_ASSERT(sDestroyedControllers.find(key) == sDestroyedControllers.end());
-      sDestroyedControllers[key] = controller;
-      Unused << controller->SendDestroy();
-    }
-  }));
+  if (mCanSend) {
+    // Gfx code is done with this object, and it will probably get destroyed
+    // soon. However, if mCanSend is true, ActorDestroy has not yet been
+    // called, which means IPC code still has a handle to this object. We need
+    // to keep it alive until we get the ActorDestroy call, either via the
+    // __delete__ message or via IPC shutdown on our end.
+    MOZ_ASSERT(sDestroyedControllers.find(mLayersId) == sDestroyedControllers.end());
+    sDestroyedControllers[mLayersId] = this;
+    Unused << SendDestroy();
+  }
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/RemoteContentController.h
+++ b/gfx/layers/ipc/RemoteContentController.h
@@ -28,60 +28,55 @@ namespace layers {
  */
 class RemoteContentController : public GeckoContentController
                               , public PAPZParent
 {
   using GeckoContentController::TapType;
   using GeckoContentController::APZStateChange;
 
 public:
-  explicit RemoteContentController(uint64_t aLayersId,
-                                   dom::TabParent* aBrowserParent);
+  explicit RemoteContentController(uint64_t aLayersId);
 
   virtual ~RemoteContentController();
 
-  // Needs to be called on the main thread.
   virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) override;
 
   virtual void HandleTap(TapType aTapType,
                          const LayoutDevicePoint& aPoint,
                          Modifiers aModifiers,
                          const ScrollableLayerGuid& aGuid,
                          uint64_t aInputBlockId) override;
 
   virtual void PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs) override;
 
+  virtual bool IsRepaintThread() override;
+
+  virtual void DispatchToRepaintThread(already_AddRefed<Runnable> aTask) override;
+
   virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion) override;
 
   virtual void NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
                                     APZStateChange aChange,
                                     int aArg) override;
 
   virtual void NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId,
                                          const nsString& aEvent) override;
 
-  // Needs to be called on the main thread.
   virtual void NotifyFlushComplete() override;
 
   virtual bool RecvUpdateHitRegion(const nsRegion& aRegion) override;
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   virtual void Destroy() override;
 
 private:
-  bool CanSend()
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-    return !!mBrowserParent;
-  }
-
-  MessageLoop* mUILoop;
+  MessageLoop* mCompositorThread;
   uint64_t mLayersId;
-  RefPtr<dom::TabParent> mBrowserParent;
+  bool mCanSend;
 
   // Mutex protecting members below accessed from multiple threads.
   mozilla::Mutex mMutex;
   nsRegion mTouchSensitiveRegion;
 };
 
 } // namespace layers