Bug 1203381 part.2 Merge all IME notification sending events of IMEContentObserver to a runnable class r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 16 Sep 2015 17:48:24 +0900
changeset 295371 6b69a6cadbe1fca58a29edbf7db28975433a2abc
parent 295370 bcfee08450fc95eceb46f2fbf60bec97d4c08b50
child 295372 11944d579d682697ed8ec9a3dd721c2280d29c99
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1203381
milestone43.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 1203381 part.2 Merge all IME notification sending events of IMEContentObserver to a runnable class r=smaug
dom/events/IMEContentObserver.cpp
dom/events/IMEContentObserver.h
--- a/dom/events/IMEContentObserver.cpp
+++ b/dom/events/IMEContentObserver.cpp
@@ -1192,325 +1192,331 @@ IMEContentObserver::FlushMergeableNotifi
   if (mIsFlushingPendingNotifications) {
     // So, if this is already called, this should do nothing.
     MOZ_LOG(sIMECOLog, LogLevel::Debug,
       ("IMECO: 0x%p   IMEContentObserver::FlushMergeableNotifications(), "
        "FAILED, due to already flushing pending notifications", this));
     return;
   }
 
+  if (!mIsFocusEventPending && !mIsTextChangeEventPending &&
+      !mIsSelectionChangeEventPending && !mIsPositionChangeEventPending) {
+    MOZ_LOG(sIMECOLog, LogLevel::Debug,
+      ("IMECO: 0x%p   IMEContentObserver::FlushMergeableNotifications(), "
+       "FAILED, due to no pending notifications", this));
+    return;
+  }
+
   AutoRestore<bool> flusing(mIsFlushingPendingNotifications);
   mIsFlushingPendingNotifications = true;
 
   // NOTE: Reset each pending flag because sending notification may cause
   //       another change.
 
-  if (mIsFocusEventPending) {
-    MOZ_LOG(sIMECOLog, LogLevel::Debug,
-      ("IMECO: 0x%p IMEContentObserver::FlushMergeableNotifications(), "
-       "creating FocusSetEvent...", this));
-    mIsFocusEventPending = false;
-    nsContentUtils::AddScriptRunner(new FocusSetEvent(this));
-    // This is the first notification to IME. So, we don't need to notify any
-    // more since IME starts to query content after it gets focus.
-    ClearPendingNotifications();
-    return;
-  }
-
-  if (mIsTextChangeEventPending) {
-    MOZ_LOG(sIMECOLog, LogLevel::Debug,
-      ("IMECO: 0x%p IMEContentObserver::FlushMergeableNotifications(), "
-       "creating TextChangeEvent...", this));
-    mIsTextChangeEventPending = false;
-    nsContentUtils::AddScriptRunner(new TextChangeEvent(this));
-  }
+  MOZ_LOG(sIMECOLog, LogLevel::Debug,
+    ("IMECO: 0x%p IMEContentObserver::FlushMergeableNotifications(), "
+     "creating IMENotificationSender...", this));
 
-  // Be aware, PuppetWidget depends on the order of this. A selection change
-  // notification should not be sent before a text change notification because
-  // PuppetWidget shouldn't query new text content every selection change.
-  if (mIsSelectionChangeEventPending) {
-    MOZ_LOG(sIMECOLog, LogLevel::Debug,
-      ("IMECO: 0x%p IMEContentObserver::FlushMergeableNotifications(), "
-       "creating SelectionChangeEvent...", this));
-    mIsSelectionChangeEventPending = false;
-    nsContentUtils::AddScriptRunner(new SelectionChangeEvent(this));
-  }
-
-  if (mIsPositionChangeEventPending) {
-    MOZ_LOG(sIMECOLog, LogLevel::Debug,
-      ("IMECO: 0x%p IMEContentObserver::FlushMergeableNotifications(), "
-       "creating PositionChangeEvent...", this));
-    mIsPositionChangeEventPending = false;
-    nsContentUtils::AddScriptRunner(new PositionChangeEvent(this));
-  }
-
-  // If notifications may cause new change, we should notify them now.
-  if (mIsTextChangeEventPending ||
-      mIsSelectionChangeEventPending ||
-      mIsPositionChangeEventPending) {
-    MOZ_LOG(sIMECOLog, LogLevel::Debug,
-      ("IMECO: 0x%p IMEContentObserver::FlushMergeableNotifications(), "
-       "posting AsyncMergeableNotificationsFlusher to current thread", this));
-    nsRefPtr<AsyncMergeableNotificationsFlusher> asyncFlusher =
-      new AsyncMergeableNotificationsFlusher(this);
-    NS_DispatchToCurrentThread(asyncFlusher);
-  }
+  nsContentUtils::AddScriptRunner(new IMENotificationSender(this));
 
   MOZ_LOG(sIMECOLog, LogLevel::Debug,
     ("IMECO: 0x%p IMEContentObserver::FlushMergeableNotifications(), "
      "finished", this));
 }
 
 /******************************************************************************
  * mozilla::IMEContentObserver::AChangeEvent
  ******************************************************************************/
 
 bool
-IMEContentObserver::AChangeEvent::CanNotifyIME() const
+IMEContentObserver::AChangeEvent::CanNotifyIME(
+                                    ChangeEventType aChangeEventType) const
 {
   if (NS_WARN_IF(!mIMEContentObserver)) {
     return false;
   }
   State state = mIMEContentObserver->GetState();
   // If it's not initialized, we should do nothing.
   if (state == eState_NotObserving) {
     return false;
   }
   // If setting focus, just check the state.
-  if (mChangeEventType == eChangeEventType_Focus) {
+  if (aChangeEventType == eChangeEventType_Focus) {
     return !NS_WARN_IF(mIMEContentObserver->mIMEHasFocus);
   }
   // If we've not notified IME of focus yet, we shouldn't notify anything.
   if (!mIMEContentObserver->mIMEHasFocus) {
     return false;
   }
 
   // If IME has focus, IMEContentObserver must hold the widget.
   MOZ_ASSERT(mIMEContentObserver->mWidget);
 
   return true;
 }
 
 bool
-IMEContentObserver::AChangeEvent::IsSafeToNotifyIME() const
+IMEContentObserver::AChangeEvent::IsSafeToNotifyIME(
+                                    ChangeEventType aChangeEventType) const
 {
   if (NS_WARN_IF(!nsContentUtils::IsSafeToRunScript())) {
     return false;
   }
   State state = mIMEContentObserver->GetState();
-  if (mChangeEventType == eChangeEventType_Focus) {
+  if (aChangeEventType == eChangeEventType_Focus) {
     if (NS_WARN_IF(state != eState_Initializing && state != eState_Observing)) {
       return false;
     }
   } else if (state != eState_Observing) {
     return false;
   }
   return mIMEContentObserver->IsSafeToNotifyIME();
 }
 
 /******************************************************************************
- * mozilla::IMEContentObserver::FocusSetEvent
+ * mozilla::IMEContentObserver::IMENotificationSender
  ******************************************************************************/
-
+ 
 NS_IMETHODIMP
-IMEContentObserver::FocusSetEvent::Run()
+IMEContentObserver::IMENotificationSender::Run()
 {
-  if (!CanNotifyIME()) {
-    // If IMEContentObserver has already gone, we don't need to notify IME of
-    // focus.
-    MOZ_LOG(sIMECOLog, LogLevel::Debug,
-      ("IMECO: 0x%p IMEContentObserver::FocusSetEvent::Run(), FAILED, due to "
-       "impossible to notify IME of focus", this));
+  // NOTE: Reset each pending flag because sending notification may cause
+  //       another change.
+
+  if (mIMEContentObserver->mIsFocusEventPending) {
+    mIMEContentObserver->mIsFocusEventPending = false;
+    SendFocusSet();
+    // This is the first notification to IME. So, we don't need to notify
+    // anymore since IME starts to query content after it gets focus.
     mIMEContentObserver->ClearPendingNotifications();
     return NS_OK;
   }
 
-  if (!IsSafeToNotifyIME()) {
+  if (mIMEContentObserver->mIsTextChangeEventPending) {
+    mIMEContentObserver->mIsTextChangeEventPending = false;
+    SendTextChange();
+  }
+
+  // Be aware, PuppetWidget depends on the order of this. A selection change
+  // notification should not be sent before a text change notification because
+  // PuppetWidget shouldn't query new text content every selection change.
+  if (mIMEContentObserver->mIsSelectionChangeEventPending) {
+    mIMEContentObserver->mIsSelectionChangeEventPending = false;
+    SendSelectionChange();
+  }
+
+  if (mIMEContentObserver->mIsPositionChangeEventPending) {
+    mIMEContentObserver->mIsPositionChangeEventPending = false;
+    SendPositionChange();
+  }
+
+  // If notifications may cause new change, we should notify them now.
+  if (mIMEContentObserver->mIsTextChangeEventPending ||
+      mIMEContentObserver->mIsSelectionChangeEventPending ||
+      mIMEContentObserver->mIsPositionChangeEventPending) {
     MOZ_LOG(sIMECOLog, LogLevel::Debug,
-      ("IMECO: 0x%p   IMEContentObserver::FocusSetEvent::Run(), retrying to "
-       "send NOTIFY_IME_OF_FOCUS...", this));
+      ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::Run(), "
+       "posting AsyncMergeableNotificationsFlusher to current thread", this));
+    nsRefPtr<AsyncMergeableNotificationsFlusher> asyncFlusher =
+      new AsyncMergeableNotificationsFlusher(mIMEContentObserver);
+    NS_DispatchToCurrentThread(asyncFlusher);
+  }
+  return NS_OK;
+}
+
+void
+IMEContentObserver::IMENotificationSender::SendFocusSet()
+{
+  if (!CanNotifyIME(eChangeEventType_Focus)) {
+    // If IMEContentObserver has already gone, we don't need to notify IME of
+    // focus.
+    MOZ_LOG(sIMECOLog, LogLevel::Debug,
+      ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::"
+       "SendFocusSet(), FAILED, due to impossible to notify IME of focus",
+       this));
+    mIMEContentObserver->ClearPendingNotifications();
+    return;
+  }
+
+  if (!IsSafeToNotifyIME(eChangeEventType_Focus)) {
+    MOZ_LOG(sIMECOLog, LogLevel::Debug,
+      ("IMECO: 0x%p   IMEContentObserver::IMENotificationSender::"
+       "SendFocusSet(), retrying to send NOTIFY_IME_OF_FOCUS...", this));
     mIMEContentObserver->PostFocusSetNotification();
-    return NS_OK;
+    return;
   }
 
   mIMEContentObserver->mIMEHasFocus = true;
   // Initialize selection cache with the first selection data.
   mIMEContentObserver->UpdateSelectionCache();
 
   MOZ_LOG(sIMECOLog, LogLevel::Info,
-    ("IMECO: 0x%p IMEContentObserver::FocusSetEvent::Run(), "
-     "sending NOTIFY_IME_OF_FOCUS...", this));
+    ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::"
+     "SendFocusSet(), sending NOTIFY_IME_OF_FOCUS...", this));
 
   IMEStateManager::NotifyIME(IMENotification(NOTIFY_IME_OF_FOCUS),
                              mIMEContentObserver->mWidget);
 
   MOZ_LOG(sIMECOLog, LogLevel::Debug,
-    ("IMECO: 0x%p IMEContentObserver::FocusSetEvent::Run(), "
-     "sent NOTIFY_IME_OF_FOCUS", this));
-  return NS_OK;
+    ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::"
+     "SendFocusSet(), sent NOTIFY_IME_OF_FOCUS", this));
 }
 
-/******************************************************************************
- * mozilla::IMEContentObserver::SelectionChangeEvent
- ******************************************************************************/
-
-NS_IMETHODIMP
-IMEContentObserver::SelectionChangeEvent::Run()
+void
+IMEContentObserver::IMENotificationSender::SendSelectionChange()
 {
-  if (!CanNotifyIME()) {
+  if (!CanNotifyIME(eChangeEventType_Selection)) {
     MOZ_LOG(sIMECOLog, LogLevel::Debug,
-      ("IMECO: 0x%p IMEContentObserver::SelectionChangeEvent::Run(), FAILED, "
-       "due to impossible to notify IME of selection change", this));
-    return NS_OK;
+      ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::"
+       "SendSelectionChange(), FAILED, due to impossible to notify IME of "
+       "selection change", this));
+    return;
   }
 
-  if (!IsSafeToNotifyIME()) {
+  if (!IsSafeToNotifyIME(eChangeEventType_Selection)) {
     MOZ_LOG(sIMECOLog, LogLevel::Debug,
-      ("IMECO: 0x%p   IMEContentObserver::SelectionChangeEvent::Run(), "
-       "retrying to send NOTIFY_IME_OF_SELECTION_CHANGE...", this));
+      ("IMECO: 0x%p   IMEContentObserver::IMENotificationSender::"
+       "SendSelectionChange(), retrying to send "
+       "NOTIFY_IME_OF_SELECTION_CHANGE...", this));
     mIMEContentObserver->PostSelectionChangeNotification();
-    return NS_OK;
+    return;
   }
 
   SelectionChangeData lastSelChangeData = mIMEContentObserver->mSelectionData;
   if (NS_WARN_IF(!mIMEContentObserver->UpdateSelectionCache())) {
     MOZ_LOG(sIMECOLog, LogLevel::Error,
-      ("IMECO: 0x%p IMEContentObserver::SelectionChangeEvent::Run(), FAILED, "
-       "due to UpdateSelectionCache() failure", this));
-    return NS_OK;
+      ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::"
+       "SendSelectionChange(), FAILED, due to UpdateSelectionCache() failure",
+       this));
+    return;
   }
 
   // If the IME doesn't want selection change notifications caused by
   // composition, we should do nothing anymore.
   SelectionChangeData& newSelChangeData = mIMEContentObserver->mSelectionData;
   if (newSelChangeData.mCausedByComposition &&
       !mIMEContentObserver->
         mUpdatePreference.WantChangesCausedByComposition()) {
-    return NS_OK;
+    return;
   }
 
   // The state may be changed since querying content causes flushing layout.
-  if (!CanNotifyIME()) {
+  if (!CanNotifyIME(eChangeEventType_Selection)) {
     MOZ_LOG(sIMECOLog, LogLevel::Debug,
-      ("IMECO: 0x%p IMEContentObserver::SelectionChangeEvent::Run(), FAILED, "
-       "due to flushing layout having changed something", this));
-    return NS_OK;
+      ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::"
+       "SendSelectionChange(), FAILED, due to flushing layout having changed "
+       "something", this));
+    return;
   }
 
   // If the selection isn't changed actually, we shouldn't notify IME of
   // selection change.
   if (lastSelChangeData.IsValid() &&
       lastSelChangeData.mOffset == newSelChangeData.mOffset &&
       lastSelChangeData.String() == newSelChangeData.String() &&
       lastSelChangeData.GetWritingMode() == newSelChangeData.GetWritingMode() &&
       lastSelChangeData.mReversed == newSelChangeData.mReversed) {
     MOZ_LOG(sIMECOLog, LogLevel::Debug,
-      ("IMECO: 0x%p IMEContentObserver::SelectionChangeEvent::Run(), not "
-       "notifying IME of NOTIFY_IME_OF_SELECTION_CHANGE due to not changed "
-       "actually", this));
-    return NS_OK;
+      ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::"
+       "SendSelectionChange(), not notifying IME of "
+       "NOTIFY_IME_OF_SELECTION_CHANGE due to not changed actually", this));
+    return;
   }
 
   MOZ_LOG(sIMECOLog, LogLevel::Info,
-    ("IMECO: 0x%p IMEContentObserver::SelectionChangeEvent::Run(), "
-     "sending NOTIFY_IME_OF_SELECTION_CHANGE... newSelChangeData=%s",
+    ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::"
+     "SendSelectionChange(), sending NOTIFY_IME_OF_SELECTION_CHANGE... "
+     "newSelChangeData=%s",
      this, SelectionChangeDataToString(newSelChangeData).get()));
 
   IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
   notification.SetData(mIMEContentObserver->mSelectionData);
   IMEStateManager::NotifyIME(notification, mIMEContentObserver->mWidget);
 
   MOZ_LOG(sIMECOLog, LogLevel::Debug,
-    ("IMECO: 0x%p IMEContentObserver::SelectionChangeEvent::Run(), "
-     "sent NOTIFY_IME_OF_SELECTION_CHANGE", this));
-  return NS_OK;
+    ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::"
+     "SendSelectionChange(), sent NOTIFY_IME_OF_SELECTION_CHANGE", this));
 }
 
-/******************************************************************************
- * mozilla::IMEContentObserver::TextChangeEvent
- ******************************************************************************/
-
-NS_IMETHODIMP
-IMEContentObserver::TextChangeEvent::Run()
+void
+IMEContentObserver::IMENotificationSender::SendTextChange()
 {
-  if (!CanNotifyIME()) {
+  if (!CanNotifyIME(eChangeEventType_Text)) {
     MOZ_LOG(sIMECOLog, LogLevel::Debug,
-      ("IMECO: 0x%p IMEContentObserver::TextChangeEvent::Run(), FAILED, "
-       "due to impossible to notify IME of text change", this));
-    return NS_OK;
+      ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::"
+       "SendTextChange(), FAILED, due to impossible to notify IME of text "
+       "change", this));
+    return;
   }
 
-  if (!IsSafeToNotifyIME()) {
+  if (!IsSafeToNotifyIME(eChangeEventType_Text)) {
     MOZ_LOG(sIMECOLog, LogLevel::Debug,
-      ("IMECO: 0x%p   IMEContentObserver::TextChangeEvent::Run(), retrying to "
-       "send NOTIFY_IME_OF_TEXT_CHANGE...", this));
+      ("IMECO: 0x%p   IMEContentObserver::IMENotificationSender::"
+       "SendTextChange(), retrying to send NOTIFY_IME_OF_TEXT_CHANGE...",
+       this));
     mIMEContentObserver->PostTextChangeNotification();
-    return NS_OK;
+    return;
   }
 
   MOZ_LOG(sIMECOLog, LogLevel::Info,
-    ("IMECO: 0x%p IMEContentObserver::TextChangeEvent::Run(), "
-     "sending NOTIFY_IME_OF_TEXT_CHANGE... mIMEContentObserver={ "
-     "mTextChangeData=%s }",
+    ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::"
+     "SendTextChange(), sending NOTIFY_IME_OF_TEXT_CHANGE... "
+     "mIMEContentObserver={ mTextChangeData=%s }",
      this, TextChangeDataToString(mIMEContentObserver->mTextChangeData).get()));
 
   IMENotification notification(NOTIFY_IME_OF_TEXT_CHANGE);
   notification.SetData(mIMEContentObserver->mTextChangeData);
   mIMEContentObserver->mTextChangeData.Clear();
   IMEStateManager::NotifyIME(notification, mIMEContentObserver->mWidget);
 
   MOZ_LOG(sIMECOLog, LogLevel::Debug,
-    ("IMECO: 0x%p IMEContentObserver::TextChangeEvent::Run(), "
-     "sent NOTIFY_IME_OF_TEXT_CHANGE", this));
-  return NS_OK;
+    ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::"
+     "SendTextChange(), sent NOTIFY_IME_OF_TEXT_CHANGE", this));
 }
 
-/******************************************************************************
- * mozilla::IMEContentObserver::PositionChangeEvent
- ******************************************************************************/
-
-NS_IMETHODIMP
-IMEContentObserver::PositionChangeEvent::Run()
+void
+IMEContentObserver::IMENotificationSender::SendPositionChange()
 {
-  if (!CanNotifyIME()) {
+  if (!CanNotifyIME(eChangeEventType_Position)) {
     MOZ_LOG(sIMECOLog, LogLevel::Debug,
-      ("IMECO: 0x%p IMEContentObserver::PositionChangeEvent::Run(), FAILED, "
-       "due to impossible to notify IME of position change", this));
-    return NS_OK;
+      ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::"
+       "SendPositionChange(), FAILED, due to impossible to notify IME of "
+       "position change", this));
+    return;
   }
 
-  if (!IsSafeToNotifyIME()) {
+  if (!IsSafeToNotifyIME(eChangeEventType_Position)) {
     MOZ_LOG(sIMECOLog, LogLevel::Debug,
-      ("IMECO: 0x%p   IMEContentObserver::PositionChangeEvent::Run(), "
-       "retrying to send NOTIFY_IME_OF_POSITION_CHANGE...", this));
+      ("IMECO: 0x%p   IMEContentObserver::IMENotificationSender::"
+       "SendPositionChange(), retrying to send "
+       "NOTIFY_IME_OF_POSITION_CHANGE...", this));
     mIMEContentObserver->PostPositionChangeNotification();
-    return NS_OK;
+    return;
   }
 
   MOZ_LOG(sIMECOLog, LogLevel::Info,
-    ("IMECO: 0x%p IMEContentObserver::PositionChangeEvent::Run(), "
-     "sending NOTIFY_IME_OF_POSITION_CHANGE...", this));
+    ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::"
+     "SendPositionChange(), sending NOTIFY_IME_OF_POSITION_CHANGE...", this));
 
   IMEStateManager::NotifyIME(IMENotification(NOTIFY_IME_OF_POSITION_CHANGE),
                              mIMEContentObserver->mWidget);
 
   MOZ_LOG(sIMECOLog, LogLevel::Debug,
-    ("IMECO: 0x%p IMEContentObserver::PositionChangeEvent::Run(), "
-     "sent NOTIFY_IME_OF_POSITION_CHANGE", this));
-  return NS_OK;
+    ("IMECO: 0x%p IMEContentObserver::IMENotificationSender::"
+     "SendPositionChange(), sent NOTIFY_IME_OF_POSITION_CHANGE", this));
 }
 
 /******************************************************************************
  * mozilla::IMEContentObserver::AsyncMergeableNotificationsFlusher
  ******************************************************************************/
 
 NS_IMETHODIMP
 IMEContentObserver::AsyncMergeableNotificationsFlusher::Run()
 {
-  if (!CanNotifyIME()) {
+  if (!CanNotifyIME(eChangeEventType_FlushPendingEvents)) {
     MOZ_LOG(sIMECOLog, LogLevel::Debug,
       ("IMECO: 0x%p IMEContentObserver::AsyncMergeableNotificationsFlusher::"
        "Run(), FAILED, due to impossible to flush pending notifications",
        this));
     return NS_OK;
   }
 
   MOZ_LOG(sIMECOLog, LogLevel::Info,
--- a/dom/events/IMEContentObserver.h
+++ b/dom/events/IMEContentObserver.h
@@ -255,85 +255,57 @@ private:
     {
       eChangeEventType_Focus,
       eChangeEventType_Selection,
       eChangeEventType_Text,
       eChangeEventType_Position,
       eChangeEventType_FlushPendingEvents
     };
 
-    AChangeEvent(ChangeEventType aChangeEventType,
-                 IMEContentObserver* aIMEContentObserver)
+    explicit AChangeEvent(IMEContentObserver* aIMEContentObserver)
       : mIMEContentObserver(aIMEContentObserver)
-      , mChangeEventType(aChangeEventType)
     {
       MOZ_ASSERT(mIMEContentObserver);
     }
 
     nsRefPtr<IMEContentObserver> mIMEContentObserver;
-    ChangeEventType mChangeEventType;
 
     /**
      * CanNotifyIME() checks if mIMEContentObserver can and should notify IME.
      */
-    bool CanNotifyIME() const;
+    bool CanNotifyIME(ChangeEventType aChangeEventType) const;
 
     /**
      * IsSafeToNotifyIME() checks if it's safe to noitify IME.
      */
-    bool IsSafeToNotifyIME() const;
+    bool IsSafeToNotifyIME(ChangeEventType aChangeEventType) const;
   };
 
-  class FocusSetEvent: public AChangeEvent
+  class IMENotificationSender: public AChangeEvent
   {
   public:
-    explicit FocusSetEvent(IMEContentObserver* aIMEContentObserver)
-      : AChangeEvent(eChangeEventType_Focus, aIMEContentObserver)
-    {
-    }
-    NS_IMETHOD Run() override;
-  };
-
-  class SelectionChangeEvent : public AChangeEvent
-  {
-  public:
-    explicit SelectionChangeEvent(IMEContentObserver* aIMEContentObserver)
-      : AChangeEvent(eChangeEventType_Selection, aIMEContentObserver)
+    explicit IMENotificationSender(IMEContentObserver* aIMEContentObserver)
+      : AChangeEvent(aIMEContentObserver)
     {
     }
     NS_IMETHOD Run() override;
-  };
 
-  class TextChangeEvent : public AChangeEvent
-  {
-  public:
-    explicit TextChangeEvent(IMEContentObserver* aIMEContentObserver)
-      : AChangeEvent(eChangeEventType_Text, aIMEContentObserver)
-    {
-      MOZ_ASSERT(aIMEContentObserver->mTextChangeData.IsValid());
-    }
-    NS_IMETHOD Run() override;
-  };
-
-  class PositionChangeEvent final : public AChangeEvent
-  {
-  public:
-    explicit PositionChangeEvent(IMEContentObserver* aIMEContentObserver)
-      : AChangeEvent(eChangeEventType_Position, aIMEContentObserver)
-    {
-    }
-    NS_IMETHOD Run() override;
+  private:
+    void SendFocusSet();
+    void SendSelectionChange();
+    void SendTextChange();
+    void SendPositionChange();
   };
 
   class AsyncMergeableNotificationsFlusher : public AChangeEvent
   {
   public:
     explicit AsyncMergeableNotificationsFlusher(
       IMEContentObserver* aIMEContentObserver)
-      : AChangeEvent(eChangeEventType_FlushPendingEvents, aIMEContentObserver)
+      : AChangeEvent(aIMEContentObserver)
     {
     }
     NS_IMETHOD Run() override;
   };
 };
 
 } // namespace mozilla