Bug 1445662 - Ensure ZoomToRect runs on the controller thread. r?rhunt draft
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 15 Mar 2018 15:10:39 -0400
changeset 768172 1fa1f0083c07a6722dd26cde20b0821bfa57b501
parent 768171 c59901b38d26d325c8736272d9e45f5f0351f73d
child 768173 2ed455f5acc857a0dd05b554ab8b569ed6c2ecd7
push id102813
push userkgupta@mozilla.com
push dateThu, 15 Mar 2018 19:11:06 +0000
reviewersrhunt
bugs1445662
milestone61.0a1
Bug 1445662 - Ensure ZoomToRect runs on the controller thread. r?rhunt Currently the ZoomToRect function is only ever called on Android, on the UI process main thread, which is neither the controller nor the sampler thread. Instead of allowing "random" threads to run inside APZ, we ensure that callers run it on the controller thread. MozReview-Commit-ID: CobWILLUFTw
gfx/layers/apz/src/APZCTreeManager.cpp
gfx/layers/apz/util/ChromeProcessController.cpp
gfx/layers/ipc/APZCTreeManagerParent.cpp
widget/nsBaseWidget.cpp
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -1886,16 +1886,21 @@ APZCTreeManager::SetKeyboardMap(const Ke
   mKeyboardMap = aKeyboardMap;
 }
 
 void
 APZCTreeManager::ZoomToRect(const ScrollableLayerGuid& aGuid,
                             const CSSRect& aRect,
                             const uint32_t aFlags)
 {
+  // We could probably move this to run on the sampler thread if needed, but
+  // either way we should restrict it to a single thread. For now let's use the
+  // controller thread.
+  APZThreadUtils::AssertOnControllerThread();
+
   RefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
   if (apzc) {
     apzc->ZoomToRect(aRect, aFlags);
   }
 }
 
 void
 APZCTreeManager::ContentReceivedInputBlock(uint64_t aInputBlockId, bool aPreventDefault)
--- a/gfx/layers/apz/util/ChromeProcessController.cpp
+++ b/gfx/layers/apz/util/ChromeProcessController.cpp
@@ -7,16 +7,17 @@
 #include "ChromeProcessController.h"
 
 #include "MainThreadUtils.h"    // for NS_IsMainThread()
 #include "base/message_loop.h"  // for MessageLoop
 #include "mozilla/dom/Element.h"
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "mozilla/layers/APZCCallbackHelper.h"
 #include "mozilla/layers/APZEventState.h"
+#include "mozilla/layers/APZThreadUtils.h"
 #include "mozilla/layers/IAPZCTreeManager.h"
 #include "mozilla/layers/DoubleTapToZoom.h"
 #include "nsIDocument.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIPresShell.h"
 #include "nsLayoutUtils.h"
 #include "nsView.h"
 
@@ -153,18 +154,24 @@ ChromeProcessController::HandleDoubleTap
   const float resolution = presShell->ScaleToResolution() ? presShell->GetResolution () : 1.0f;
   CSSPoint point(aPoint.x / resolution, aPoint.y / resolution);
   CSSRect zoomToRect = CalculateRectToZoomTo(document, point);
 
   uint32_t presShellId;
   FrameMetrics::ViewID viewId;
   if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(
       document->GetDocumentElement(), &presShellId, &viewId)) {
-    mAPZCTreeManager->ZoomToRect(
-      ScrollableLayerGuid(aGuid.mLayersId, presShellId, viewId), zoomToRect);
+    APZThreadUtils::RunOnControllerThread(
+      NewRunnableMethod<ScrollableLayerGuid, CSSRect, uint32_t>(
+        "IAPZCTreeManager::ZoomToRect",
+        mAPZCTreeManager,
+        &IAPZCTreeManager::ZoomToRect,
+        ScrollableLayerGuid(aGuid.mLayersId, presShellId, viewId),
+        zoomToRect,
+        ZoomToRectBehavior::DEFAULT_BEHAVIOR));
   }
 }
 
 void
 ChromeProcessController::HandleTap(TapType aType,
                                    const mozilla::LayoutDevicePoint& aPoint,
                                    Modifiers aModifiers,
                                    const ScrollableLayerGuid& aGuid,
--- a/gfx/layers/ipc/APZCTreeManagerParent.cpp
+++ b/gfx/layers/ipc/APZCTreeManagerParent.cpp
@@ -182,17 +182,22 @@ APZCTreeManagerParent::RecvZoomToRect(
     const uint32_t& aFlags)
 {
   if (aGuid.mLayersId != mLayersId) {
     // Guard against bad data from hijacked child processes
     NS_ERROR("Unexpected layers id in RecvZoomToRect; dropping message...");
     return IPC_FAIL_NO_REASON(this);
   }
 
-  mTreeManager->ZoomToRect(aGuid, aRect, aFlags);
+  APZThreadUtils::RunOnControllerThread(
+    NewRunnableMethod<ScrollableLayerGuid, CSSRect, uint32_t>(
+      "layers::IAPZCTreeManager::ZoomToRect",
+      mTreeManager,
+      &IAPZCTreeManager::ZoomToRect,
+      aGuid, aRect, aFlags));
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 APZCTreeManagerParent::RecvContentReceivedInputBlock(
     const uint64_t& aInputBlockId,
     const bool& aPreventDefault)
 {
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -1928,17 +1928,24 @@ nsBaseWidget::ZoomToRect(const uint32_t&
                          const FrameMetrics::ViewID& aViewId,
                          const CSSRect& aRect,
                          const uint32_t& aFlags)
 {
   if (!mCompositorSession || !mAPZC) {
     return;
   }
   uint64_t layerId = mCompositorSession->RootLayerTreeId();
-  mAPZC->ZoomToRect(ScrollableLayerGuid(layerId, aPresShellId, aViewId), aRect, aFlags);
+  APZThreadUtils::RunOnControllerThread(
+    NewRunnableMethod<ScrollableLayerGuid, CSSRect, uint32_t>(
+      "layers::IAPZCTreeManager::ZoomToRect",
+      mAPZC,
+      &IAPZCTreeManager::ZoomToRect,
+      ScrollableLayerGuid(layerId, aPresShellId, aViewId),
+      aRect,
+      aFlags));
 }
 
 #ifdef ACCESSIBILITY
 
 a11y::Accessible*
 nsBaseWidget::GetRootAccessible()
 {
   NS_ENSURE_TRUE(mWidgetListener, nullptr);