Bug 1304620 part.2 ContentCacheInParent should manage if there is pending composition in the remote process r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 12 Oct 2016 17:09:02 +0900
changeset 362882 97cb51652c868d8698c966ad0483f1421be1d449
parent 362881 8bea9647dc86865e874f346a3fccc14565ce3f65
child 362883 64f030acc66bae6f210b5d8a2d82e38993bde2cf
push id1369
push userjlorenzo@mozilla.com
push dateMon, 27 Feb 2017 14:59:41 +0000
treeherdermozilla-release@d75a1dba431f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1304620
milestone52.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 1304620 part.2 ContentCacheInParent should manage if there is pending composition in the remote process r=m_kato If the remote process is busy or user restarts composition too quickly, there could be 2 or more compositions in ContentCache. For managing such case, ContentCacheInParent should manage the pending composition count which is increased at dispatching eCompositionStart event to the remote process and decreased at receiving eCompositionCommit(AsIs) event from the remote process. MozReview-Commit-ID: KbTsK20NEZD
widget/ContentCache.cpp
widget/ContentCache.h
widget/TextEvents.h
--- a/widget/ContentCache.cpp
+++ b/widget/ContentCache.cpp
@@ -505,16 +505,17 @@ ContentCacheInChild::SetSelection(nsIWid
 /*****************************************************************************
  * mozilla::ContentCacheInParent
  *****************************************************************************/
 
 ContentCacheInParent::ContentCacheInParent()
   : ContentCache()
   , mCommitStringByRequest(nullptr)
   , mPendingEventsNeedingAck(0)
+  , mPendingCompositionCount(0)
   , mWidgetHasComposition(false)
 {
 }
 
 void
 ContentCacheInParent::AssignContent(const ContentCache& aOther,
                                     nsIWidget* aWidget,
                                     const IMENotification* aNotification)
@@ -1054,31 +1055,35 @@ ContentCacheInParent::GetCaretRect(uint3
 
 bool
 ContentCacheInParent::OnCompositionEvent(const WidgetCompositionEvent& aEvent)
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
     ("0x%p OnCompositionEvent(aEvent={ "
      "mMessage=%s, mData=\"%s\" (Length()=%u), mRanges->Length()=%u }), "
      "mPendingEventsNeedingAck=%u, mWidgetHasComposition=%s, "
-     "mCommitStringByRequest=0x%p",
+     "mPendingCompositionCount=%u, mCommitStringByRequest=0x%p",
      this, ToChar(aEvent.mMessage),
      GetEscapedUTF8String(aEvent.mData).get(), aEvent.mData.Length(),
      aEvent.mRanges ? aEvent.mRanges->Length() : 0, mPendingEventsNeedingAck,
-     GetBoolName(mWidgetHasComposition), mCommitStringByRequest));
+     GetBoolName(mWidgetHasComposition), mPendingCompositionCount,
+     mCommitStringByRequest));
 
   // We must be able to simulate the selection because
   // we might not receive selection updates in time
   if (!mWidgetHasComposition) {
     if (aEvent.mWidget && aEvent.mWidget->PluginHasFocus()) {
       // If focus is on plugin, we cannot get selection range
       mCompositionStart = 0;
     } else {
       mCompositionStart = mSelection.StartOffset();
     }
+    MOZ_ASSERT(aEvent.mMessage == eCompositionStart);
+    MOZ_RELEASE_ASSERT(mPendingCompositionCount < UINT8_MAX);
+    mPendingCompositionCount++;
   }
 
   mWidgetHasComposition = !aEvent.CausesDOMCompositionEndEvent();
 
   if (!mWidgetHasComposition) {
     mCompositionStart = UINT32_MAX;
   }
 
@@ -1103,39 +1108,45 @@ ContentCacheInParent::OnCompositionEvent
 void
 ContentCacheInParent::OnSelectionEvent(
                         const WidgetSelectionEvent& aSelectionEvent)
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
     ("0x%p OnSelectionEvent(aEvent={ "
      "mMessage=%s, mOffset=%u, mLength=%u, mReversed=%s, "
      "mExpandToClusterBoundary=%s, mUseNativeLineBreak=%s }), "
-     "mPendingEventsNeedingAck=%u, mWidgetHasComposition=%s",
+     "mPendingEventsNeedingAck=%u, mWidgetHasComposition=%s, "
+     "mPendingCompositionCount=%u",
      this, ToChar(aSelectionEvent.mMessage),
      aSelectionEvent.mOffset, aSelectionEvent.mLength,
      GetBoolName(aSelectionEvent.mReversed),
      GetBoolName(aSelectionEvent.mExpandToClusterBoundary),
      GetBoolName(aSelectionEvent.mUseNativeLineBreak), mPendingEventsNeedingAck,
-     GetBoolName(mWidgetHasComposition)));
+     GetBoolName(mWidgetHasComposition), mPendingCompositionCount));
 
   mPendingEventsNeedingAck++;
 }
 
 void
 ContentCacheInParent::OnEventNeedingAckHandled(nsIWidget* aWidget,
                                                 EventMessage aMessage)
 {
   // This is called when the child process receives WidgetCompositionEvent or
   // WidgetSelectionEvent.
 
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
     ("0x%p OnEventNeedingAckHandled(aWidget=0x%p, "
-     "aMessage=%s), mPendingEventsNeedingAck=%u",
+     "aMessage=%s), mPendingEventsNeedingAck=%u, mPendingCompositionCount=%u",
      this, aWidget, ToChar(aMessage), mPendingEventsNeedingAck));
 
+  if (WidgetCompositionEvent::IsFollowedByCompositionEnd(aMessage)) {
+    MOZ_RELEASE_ASSERT(mPendingCompositionCount > 0);
+    mPendingCompositionCount--;
+  }
+
   MOZ_RELEASE_ASSERT(mPendingEventsNeedingAck > 0);
   if (--mPendingEventsNeedingAck) {
     return;
   }
 
   FlushPendingNotifications(aWidget);
 }
 
--- a/widget/ContentCache.h
+++ b/widget/ContentCache.h
@@ -409,17 +409,19 @@ private:
   // This is not nullptr only while the instance is requesting IME to
   // composition.  Then, data value of dispatched composition events should
   // be stored into the instance.
   nsAString* mCommitStringByRequest;
   // mPendingEventsNeedingAck is increased before sending a composition event or
   // a selection event and decreased after they are received in the child
   // process.
   uint32_t mPendingEventsNeedingAck;
-
+  // mPendingCompositionCount is number of compositions which started in widget
+  // but not yet handled in the child process.
+  uint8_t mPendingCompositionCount;
   // mWidgetHasComposition is true when the widget in this process thinks that
   // IME has composition.  So, this is set to true when eCompositionStart is
   // dispatched and set to false when eCompositionCommit(AsIs) is dispatched.
   bool mWidgetHasComposition;
 
   /**
    * When following methods' aRoundToExistingOffset is true, even if specified
    * offset or range is out of bounds, the result is computed with the existing
--- a/widget/TextEvents.h
+++ b/widget/TextEvents.h
@@ -590,18 +590,23 @@ public:
   {
     return mMessage == eCompositionEnd ||
            mMessage == eCompositionCommit ||
            mMessage == eCompositionCommitAsIs;
   }
 
   bool IsFollowedByCompositionEnd() const
   {
-    return mOriginalMessage == eCompositionCommit ||
-           mOriginalMessage == eCompositionCommitAsIs;
+    return IsFollowedByCompositionEnd(mOriginalMessage);
+  }
+
+  static bool IsFollowedByCompositionEnd(EventMessage aEventMessage)
+  {
+    return aEventMessage == eCompositionCommit ||
+           aEventMessage == eCompositionCommitAsIs;
   }
 };
 
 /******************************************************************************
  * mozilla::WidgetQueryContentEvent
  ******************************************************************************/
 
 class WidgetQueryContentEvent : public WidgetGUIEvent