Bug 1264161 - Ensure we null out APZ pointers to the widget when it gets destroyed. r=botond
authorKartikaya Gupta <kgupta@mozilla.com>
Fri, 22 Apr 2016 16:01:30 -0400
changeset 294545 3d22a2e2a5948493a0ced8568b8c98a8486ecb37
parent 294544 7e8778ca64825cf31d106be737fd31d36a29b13c
child 294546 8ba674386af9c363f7bde96613abdc7ac6207f0f
push id75586
push userkgupta@mozilla.com
push dateFri, 22 Apr 2016 20:04:34 +0000
treeherdermozilla-inbound@3d22a2e2a594 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1264161
milestone48.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 1264161 - Ensure we null out APZ pointers to the widget when it gets destroyed. r=botond MozReview-Commit-ID: HccKXqU3Z6H
gfx/layers/apz/util/ChromeProcessController.cpp
gfx/layers/ipc/CompositorBridgeParent.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
@@ -87,16 +87,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/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -947,20 +947,21 @@ CompositorBridgeParent::ActorDestroy(Act
     mForceCompositionTask = nullptr;
   }
   mPaused = true;
   RemoveCompositor(mCompositorID);
 
   if (mLayerManager) {
     mLayerManager->Destroy();
     mLayerManager = nullptr;
-    { // scope lock
-      MonitorAutoLock lock(*sIndirectLayerTreesLock);
-      sIndirectLayerTrees.erase(mRootLayerTreeID);
-    }
+  }
+
+  { // scope lock
+    MonitorAutoLock lock(*sIndirectLayerTreesLock);
+    sIndirectLayerTrees.erase(mRootLayerTreeID);
   }
 
   if (mCompositor) {
     mCompositor->Destroy();
     mCompositor = nullptr;
   }
 
   mCompositionManager = nullptr;
--- 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
@@ -974,20 +974,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 = mCompositorBridgeParent->RootLayerTreeId();
-    CompositorBridgeParent::SetControllerForLayerTree(rootLayerTreeId, controller);
+    CompositorBridgeParent::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();
@@ -1295,16 +1295,20 @@ void nsBaseWidget::CreateCompositor(int 
       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;
     mCompositorBridgeChild = nullptr;
     mCompositorBridgeParent = nullptr;
     mCompositorVsyncDispatcher = nullptr;
     return;
   }
 
@@ -1414,16 +1418,24 @@ nsBaseWidget::CreateBackBufferDrawTarget
 //-------------------------------------------------------------------------
 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
@@ -520,16 +520,17 @@ protected:
   nsIWidgetListener* mWidgetListener;
   nsIWidgetListener* mAttachedWidgetListener;
   nsIWidgetListener* mPreviouslyAttachedWidgetListener;
   RefPtr<LayerManager> mLayerManager;
   RefPtr<CompositorBridgeChild> mCompositorBridgeChild;
   RefPtr<CompositorBridgeParent> mCompositorBridgeParent;
   RefPtr<mozilla::CompositorVsyncDispatcher> mCompositorVsyncDispatcher;
   RefPtr<APZCTreeManager> mAPZC;
+  RefPtr<GeckoContentController> mRootContentController;
   RefPtr<APZEventState> mAPZEventState;
   // Back buffer of BasicCompositor
   RefPtr<DrawTarget> mLastBackBuffer;
   SetAllowedTouchBehaviorCallback mSetAllowedTouchBehaviorCallback;
   RefPtr<WidgetShutdownObserver> mShutdownObserver;
   RefPtr<TextEventDispatcher> mTextEventDispatcher;
   nsCursor          mCursor;
   nsBorderStyle     mBorderStyle;