Bug 1298704 - Use flag to avoid calling AccessibleCaretEventHub::Reflow() recursively. r=mats draft
authorTing-Yu Lin <tlin@mozilla.com>
Mon, 29 Aug 2016 15:36:45 +0800
changeset 407241 839b483e8489cf02dbefad181f22baba85068542
parent 406450 1a5b53a831e5a6c20de1b081c774feb3ff76756c
child 529826 563650189184f6d9df5c6c6274d453c15fb80ee5
push id27910
push userbmo:tlin@mozilla.com
push dateTue, 30 Aug 2016 05:36:46 +0000
reviewersmats
bugs1298704
milestone51.0a1
Bug 1298704 - Use flag to avoid calling AccessibleCaretEventHub::Reflow() recursively. r=mats MozReview-Commit-ID: Jkf7sSqxG2d
layout/base/AccessibleCaretEventHub.cpp
layout/base/AccessibleCaretEventHub.h
--- a/layout/base/AccessibleCaretEventHub.cpp
+++ b/layout/base/AccessibleCaretEventHub.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AccessibleCaretEventHub.h"
 
 #include "AccessibleCaretLogger.h"
 #include "AccessibleCaretManager.h"
 #include "Layers.h"
 #include "gfxPrefs.h"
+#include "mozilla/AutoRestore.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TouchEvents.h"
 #include "mozilla/Preferences.h"
 #include "nsCanvasFrame.h"
 #include "nsDocShell.h"
 #include "nsFocusManager.h"
 #include "nsFrameSelection.h"
@@ -661,31 +662,33 @@ AccessibleCaretEventHub::Reflow(DOMHighR
                                 DOMHighResTimeStamp aEnd)
 {
   if (!mInitialized) {
     return NS_OK;
   }
 
   MOZ_ASSERT(mRefCnt.get() > 1, "Expect caller holds us as well!");
 
+  if (mIsInReflowCallback) {
+    return NS_OK;
+  }
+
+  AutoRestore<bool> autoRestoreIsInReflowCallback(mIsInReflowCallback);
+  mIsInReflowCallback = true;
+
   AC_LOG("%s, state: %s", __FUNCTION__, mState->Name());
   mState->OnReflow(this);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 AccessibleCaretEventHub::ReflowInterruptible(DOMHighResTimeStamp aStart,
                                              DOMHighResTimeStamp aEnd)
 {
-  if (!mInitialized) {
-    return NS_OK;
-  }
-
-  MOZ_ASSERT(mRefCnt.get() > 1, "Expect caller holds us as well!");
-
+  // Defer the error checking to Reflow().
   return Reflow(aStart, aEnd);
 }
 
 void
 AccessibleCaretEventHub::AsyncPanZoomStarted()
 {
   if (!mInitialized) {
     return;
--- a/layout/base/AccessibleCaretEventHub.h
+++ b/layout/base/AccessibleCaretEventHub.h
@@ -127,18 +127,16 @@ protected:
   void CancelLongTapInjector();
   static void FireLongTap(nsITimer* aTimer, void* aAccessibleCaretEventHub);
 
   void LaunchScrollEndInjector();
   void CancelScrollEndInjector();
   static void FireScrollEnd(nsITimer* aTimer, void* aAccessibleCaretEventHub);
 
   // Member variables
-  bool mInitialized = false;
-
   State* mState = NoActionState();
 
   // Will be set to nullptr in Terminate().
   nsIPresShell* MOZ_NON_OWNING_REF mPresShell = nullptr;
 
   UniquePtr<AccessibleCaretManager> mManager;
 
   WeakPtr<nsDocShell> mDocShell;
@@ -151,16 +149,22 @@ protected:
   nsCOMPtr<nsITimer> mScrollEndInjectorTimer;
 
   // Last mouse button down event or touch start event point.
   nsPoint mPressPoint{ NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE };
 
   // For filter multitouch event
   int32_t mActiveTouchId = kInvalidTouchId;
 
+  // Flag to indicate the class has been initialized.
+  bool mInitialized = false;
+
+  // Flag to avoid calling Reflow() callback recursively.
+  bool mIsInReflowCallback = false;
+
   // Simulate long tap if the platform does not support eMouseLongTap events.
   static bool sUseLongTapInjector;
 
   static const int32_t kScrollEndTimerDelay = 300;
   static const int32_t kMoveStartToleranceInPixel = 5;
   static const int32_t kInvalidTouchId = -1;
   static const int32_t kDefaultTouchId = 0; // For mouse event
 };