Bug 1264161 - Ensure we null out APZ pointers to the widget when it gets destroyed. r=botond a=ritu
authorKartikaya Gupta <kgupta@mozilla.com>
Fri, 22 Apr 2016 16:01:30 -0400
changeset 326087 c70884434329840e438734d1d35d69e77a9092c6
parent 326086 5eabfc6b184e07a730a51ccc0f49f3726eb13da5
child 326088 c39733f05f38488db24f5604238e96c80fbbd512
push id1128
push userjlund@mozilla.com
push dateWed, 01 Jun 2016 01:31:59 +0000
treeherdermozilla-release@fe0d30de989d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond, ritu
bugs1264161
milestone47.0
Bug 1264161 - Ensure we null out APZ pointers to the widget when it gets destroyed. r=botond a=ritu MozReview-Commit-ID: HccKXqU3Z6H
gfx/layers/apz/util/ChromeProcessController.cpp
gfx/layers/ipc/CompositorParent.cpp
widget/cocoa/nsChildView.mm
widget/nsBaseWidget.cpp
widget/nsBaseWidget.h
--- a/gfx/layers/apz/util/ChromeProcessController.cpp
+++ b/gfx/layers/apz/util/ChromeProcessController.cpp
@@ -94,16 +94,19 @@ ChromeProcessController::Destroy()
 
   MOZ_ASSERT(MessageLoop::current() == mUILoop);
   mWidget = nullptr;
 }
 
 nsIPresShell*
 ChromeProcessController::GetPresShell() const
 {
+  if (!mWidget) {
+    return nullptr;
+  }
   if (nsView* view = nsView::GetViewFor(mWidget)) {
     return view->GetPresShell();
   }
   return nullptr;
 }
 
 nsIDocument*
 ChromeProcessController::GetRootDocument() const
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -947,23 +947,23 @@ CompositorParent::ActorDestroy(ActorDest
     mForceCompositionTask = nullptr;
   }
   mPaused = true;
   RemoveCompositor(mCompositorID);
 
   if (mLayerManager) {
     mLayerManager->Destroy();
     mLayerManager = nullptr;
-    { // scope lock
-      MonitorAutoLock lock(*sIndirectLayerTreesLock);
-      sIndirectLayerTrees[mRootLayerTreeID].mLayerManager = nullptr;
-    }
     mCompositionManager = nullptr;
     mCompositor = nullptr;
   }
+  { // scope lock
+    MonitorAutoLock lock(*sIndirectLayerTreesLock);
+    sIndirectLayerTrees[mRootLayerTreeID].mLayerManager = nullptr;
+  }
 }
 
 
 void
 CompositorParent::ScheduleRenderOnCompositorThread()
 {
   CancelableTask *renderTask = NewRunnableMethod(this, &CompositorParent::ScheduleComposition);
   MOZ_ASSERT(CompositorLoop());
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -624,16 +624,19 @@ NS_IMETHODIMP nsChildView::Destroy()
   // Make sure that no composition is in progress while disconnecting
   // ourselves from the view.
   MutexAutoLock lock(mViewTearDownLock);
 
   if (mOnDestroyCalled)
     return NS_OK;
   mOnDestroyCalled = true;
 
+  // Stuff below may delete the last ref to this
+  nsCOMPtr<nsIWidget> kungFuDeathGrip(this);
+
   [mView widgetDestroyed];
 
   nsBaseWidget::Destroy();
 
   NotifyWindowDestroyed();
   mParentWidget = nil;
 
   TearDownView();
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -970,20 +970,20 @@ void nsBaseWidget::ConfigureAPZCTreeMana
                                                    const nsTArray<TouchBehaviorFlags>& aFlags)
   {
     MOZ_ASSERT(NS_IsMainThread());
     APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
         treeManager.get(), &APZCTreeManager::SetAllowedTouchBehavior,
         aInputBlockId, aFlags));
   };
 
-  RefPtr<GeckoContentController> controller = CreateRootContentController();
-  if (controller) {
+  mRootContentController = CreateRootContentController();
+  if (mRootContentController) {
     uint64_t rootLayerTreeId = mCompositorParent->RootLayerTreeId();
-    CompositorParent::SetControllerForLayerTree(rootLayerTreeId, controller);
+    CompositorParent::SetControllerForLayerTree(rootLayerTreeId, mRootContentController);
   }
 
   // When APZ is enabled, we can actually enable raw touch events because we
   // have code that can deal with them properly. If APZ is not enabled, this
   // function doesn't get called.
   if (Preferences::GetInt("dom.w3c_touch_events.enabled", 0) ||
       Preferences::GetBool("dom.w3c_pointer_events.enabled", false)) {
     RegisterTouchWindow();
@@ -1294,16 +1294,21 @@ void nsBaseWidget::CreateCompositor(int 
     shadowManager = mCompositorChild->SendPLayerTransactionConstructor(
       backendHints, 0, &textureFactoryIdentifier, &success);
   }
 
   ShadowLayerForwarder* lf = lm->AsShadowForwarder();
 
   if (!success || !lf) {
     NS_WARNING("Failed to create an OMT compositor.");
+    mAPZC = nullptr;
+    if (mRootContentController) {
+      mRootContentController->Destroy();
+      mRootContentController = nullptr;
+    }
     DestroyCompositor();
     mLayerManager = nullptr;
     mCompositorChild = nullptr;
     mCompositorParent = nullptr;
     mCompositorVsyncDispatcher = nullptr;
     return;
   }
 
@@ -1376,16 +1381,24 @@ already_AddRefed<mozilla::gfx::DrawTarge
 //-------------------------------------------------------------------------
 void nsBaseWidget::OnDestroy()
 {
   if (mTextEventDispatcher) {
     mTextEventDispatcher->OnDestroyWidget();
     // Don't release it until this widget actually released because after this
     // is called, TextEventDispatcher() may create it again.
   }
+
+  // If this widget is being destroyed, let the APZ code know to drop references
+  // to this widget. Callers of this function all should be holding a deathgrip
+  // on this widget already.
+  if (mRootContentController) {
+    mRootContentController->Destroy();
+    mRootContentController = nullptr;
+  }
 }
 
 NS_METHOD nsBaseWidget::SetWindowClass(const nsAString& xulWinType)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_METHOD nsBaseWidget::MoveClient(double aX, double aY)
--- a/widget/nsBaseWidget.h
+++ b/widget/nsBaseWidget.h
@@ -508,16 +508,17 @@ protected:
   nsIWidgetListener* mWidgetListener;
   nsIWidgetListener* mAttachedWidgetListener;
   nsIWidgetListener* mPreviouslyAttachedWidgetListener;
   RefPtr<LayerManager> mLayerManager;
   RefPtr<CompositorChild> mCompositorChild;
   RefPtr<CompositorParent> mCompositorParent;
   RefPtr<mozilla::CompositorVsyncDispatcher> mCompositorVsyncDispatcher;
   RefPtr<APZCTreeManager> mAPZC;
+  RefPtr<GeckoContentController> mRootContentController;
   RefPtr<APZEventState> mAPZEventState;
   SetAllowedTouchBehaviorCallback mSetAllowedTouchBehaviorCallback;
   RefPtr<WidgetShutdownObserver> mShutdownObserver;
   RefPtr<TextEventDispatcher> mTextEventDispatcher;
   nsCursor          mCursor;
   nsBorderStyle     mBorderStyle;
   LayoutDeviceIntRect mBounds;
   LayoutDeviceIntRect* mOriginalBounds;