Bug 1374207 - part2: TextComposition, IMEContentObserver and IMEStateManager should use EditorBase instead of nsIEditor r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 20 Jun 2017 19:23:44 +0900
changeset 598745 0132f4fe66d271c4e80d0ba5412f8d5c42ba5e87
parent 598744 70720f0e953b6f4525c3402c094796e5eeb8a1ee
child 598746 ef927041c15c28e4622c3ddcc24c6eeaabae7b8f
push id65310
push usermasayuki@d-toybox.com
push dateThu, 22 Jun 2017 06:46:13 +0000
reviewersm_kato
bugs1374207
milestone56.0a1
Bug 1374207 - part2: TextComposition, IMEContentObserver and IMEStateManager should use EditorBase instead of nsIEditor r?m_kato MozReview-Commit-ID: IdHmseTiv2t
dom/events/IMEContentObserver.cpp
dom/events/IMEContentObserver.h
dom/events/IMEStateManager.cpp
dom/events/IMEStateManager.h
dom/events/TextComposition.cpp
dom/events/TextComposition.h
editor/libeditor/EditorBase.cpp
editor/libeditor/EditorEventListener.cpp
--- a/dom/events/IMEContentObserver.cpp
+++ b/dom/events/IMEContentObserver.cpp
@@ -130,33 +130,33 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IM
 
   tmp->NotifyIMEOfBlur();
   tmp->UnregisterObservers();
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mSelection)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRootContent)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditableNode)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditor)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorBase)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentObserver)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mEndOfAddedTextCache.mContainerNode)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mStartOfRemovingTextRangeCache.mContainerNode)
 
   tmp->mIMENotificationRequests = nullptr;
   tmp->mESM = nullptr;
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IMEContentObserver)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWidget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFocusedWidget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSelection)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRootContent)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditableNode)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocShell)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditor)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEditorBase)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentObserver)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEndOfAddedTextCache.mContainerNode)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(
     mStartOfRemovingTextRangeCache.mContainerNode)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IMEContentObserver)
  NS_INTERFACE_MAP_ENTRY(nsISelectionListener)
@@ -192,17 +192,17 @@ IMEContentObserver::IMEContentObserver()
   mTextChangeData.Test();
 #endif
 }
 
 void
 IMEContentObserver::Init(nsIWidget* aWidget,
                          nsPresContext* aPresContext,
                          nsIContent* aContent,
-                         nsIEditor* aEditor)
+                         EditorBase* aEditorBase)
 {
   State state = GetState();
   if (NS_WARN_IF(state == eState_Observing)) {
     return; // Nothing to do.
   }
 
   bool firstInitialization = state != eState_StoppedObserving;
   if (!firstInitialization) {
@@ -219,17 +219,17 @@ IMEContentObserver::Init(nsIWidget* aWid
   mIMENotificationRequests = &mWidget->IMENotificationRequestsRef();
 
   if (aWidget->GetInputContext().mIMEState.mEnabled == IMEState::PLUGIN) {
     if (!InitWithPlugin(aPresContext, aContent)) {
       Clear();
       return;
     }
   } else {
-    if (!InitWithEditor(aPresContext, aContent, aEditor)) {
+    if (!InitWithEditor(aPresContext, aContent, aEditorBase)) {
       Clear();
       return;
     }
   }
 
   if (firstInitialization) {
     // Now, try to send NOTIFY_IME_OF_FOCUS to IME via the widget.
     MaybeNotifyIMEOfFocusSet();
@@ -284,28 +284,28 @@ IMEContentObserver::OnIMEReceivedFocus()
   // Some change events may wait to notify IME because this was being
   // initialized.  It is the time to flush them.
   FlushMergeableNotifications();
 }
 
 bool
 IMEContentObserver::InitWithEditor(nsPresContext* aPresContext,
                                    nsIContent* aContent,
-                                   nsIEditor* aEditor)
+                                   EditorBase* aEditorBase)
 {
-  MOZ_ASSERT(aEditor);
+  MOZ_ASSERT(aEditorBase);
 
   mEditableNode =
     IMEStateManager::GetRootEditableNode(aPresContext, aContent);
   if (NS_WARN_IF(!mEditableNode)) {
     return false;
   }
 
-  mEditor = aEditor;
-  if (NS_WARN_IF(!mEditor)) {
+  mEditorBase = aEditorBase;
+  if (NS_WARN_IF(!mEditorBase)) {
     return false;
   }
 
   nsIPresShell* presShell = aPresContext->PresShell();
 
   // get selection and root content
   nsCOMPtr<nsISelectionController> selCon;
   if (mEditableNode->IsNodeOfType(nsINode::eCONTENT)) {
@@ -384,17 +384,17 @@ IMEContentObserver::InitWithPlugin(nsPre
     return false;
   }
   selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
                        getter_AddRefs(mSelection));
   if (NS_WARN_IF(!mSelection)) {
     return false;
   }
 
-  mEditor = nullptr;
+  mEditorBase = nullptr;
   mEditableNode = aContent;
   mRootContent = aContent;
   // Should be safe to clear mDocumentObserver here even though it *might*
   // grab this instance because this is called by Init() and the callers of
   // it and MaybeReinitialize() grabs this instance with local RefPtr.
   // So, this won't cause refcount of this instance become 0.
   mDocumentObserver = nullptr;
 
@@ -406,23 +406,23 @@ IMEContentObserver::InitWithPlugin(nsPre
   MOZ_ASSERT(WasInitializedWithPlugin());
 
   return true;
 }
 
 bool
 IMEContentObserver::WasInitializedWithPlugin() const
 {
-  return mDocShell && !mEditor;
+  return mDocShell && !mEditorBase;
 }
 
 void
 IMEContentObserver::Clear()
 {
-  mEditor = nullptr;
+  mEditorBase = nullptr;
   mSelection = nullptr;
   mEditableNode = nullptr;
   mRootContent = nullptr;
   mDocShell = nullptr;
   // Should be safe to clear mDocumentObserver here even though it grabs
   // this instance in most cases because this is called by Init() or Destroy().
   // The callers of Init() grab this instance with local RefPtr.
   // The caller of Destroy() also grabs this instance with local RefPtr.
@@ -445,18 +445,18 @@ IMEContentObserver::ObserveEditableNode(
   if (!mIMEHasFocus) {
     MOZ_ASSERT(!mWidget || mNeedsToNotifyIMEOfFocusSet ||
                mSendingNotification == NOTIFY_IME_OF_FOCUS,
                "Wow, OnIMEReceivedFocus() won't be called?");
     return;
   }
 
   mIsObserving = true;
-  if (mEditor) {
-    mEditor->AddEditorObserver(this);
+  if (mEditorBase) {
+    mEditorBase->AddEditorObserver(this);
   }
 
   if (!WasInitializedWithPlugin()) {
     // Add selection change listener only when this starts to observe
     // non-plugin content since we cannot detect selection changes in
     // plugins.
     nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSelection));
     NS_ENSURE_TRUE_VOID(selPrivate);
@@ -524,18 +524,18 @@ IMEContentObserver::NotifyIMEOfBlur()
 void
 IMEContentObserver::UnregisterObservers()
 {
   if (!mIsObserving) {
     return;
   }
   mIsObserving = false;
 
-  if (mEditor) {
-    mEditor->RemoveEditorObserver(this);
+  if (mEditorBase) {
+    mEditorBase->RemoveEditorObserver(this);
   }
 
   if (mSelection) {
     nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSelection));
     if (selPrivate) {
       selPrivate->RemoveSelectionListener(this);
     }
     mSelectionData.Clear();
@@ -592,24 +592,24 @@ IMEContentObserver::DisconnectFromEventS
 {
   mESM = nullptr;
 }
 
 bool
 IMEContentObserver::MaybeReinitialize(nsIWidget* aWidget,
                                       nsPresContext* aPresContext,
                                       nsIContent* aContent,
-                                      nsIEditor* aEditor)
+                                      EditorBase* aEditorBase)
 {
   if (!IsObservingContent(aPresContext, aContent)) {
     return false;
   }
 
   if (GetState() == eState_StoppedObserving) {
-    Init(aWidget, aPresContext, aContent, aEditor);
+    Init(aWidget, aPresContext, aContent, aEditorBase);
   }
   return IsManaging(aPresContext, aContent);
 }
 
 bool
 IMEContentObserver::IsManaging(nsPresContext* aPresContext,
                                nsIContent* aContent) const
 {
@@ -675,25 +675,20 @@ IMEContentObserver::IsEditorHandlingEven
 
 bool
 IMEContentObserver::IsEditorComposing() const
 {
   // Note that don't use TextComposition here. The important thing is,
   // whether the editor already started to handle composition because
   // web contents can change selection, text content and/or something from
   // compositionstart event listener which is run before EditorBase handles it.
-  if (NS_WARN_IF(!mEditor)) {
+  if (NS_WARN_IF(!mEditorBase)) {
     return false;
   }
-  bool isComposing = false;
-  nsresult rv = mEditor->GetComposing(&isComposing);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return false;
-  }
-  return isComposing;
+  return mEditorBase->IsIMEComposing();
 }
 
 nsresult
 IMEContentObserver::GetSelectionAndRoot(nsISelection** aSelection,
                                         nsIContent** aRootContent) const
 {
   if (!mEditableNode || !mSelection) {
     return NS_ERROR_NOT_AVAILABLE;
@@ -1671,19 +1666,17 @@ IMEContentObserver::IsSafeToNotifyIME() 
 
   // If it's in reflow, we should wait to finish the reflow.
   // FYI: This should be called again from Reflow() or ReflowInterruptible().
   if (IsReflowLocked()) {
     return false;
   }
 
   // If we're in handling an edit action, this method will be called later.
-  bool isInEditAction = false;
-  if (mEditor && NS_SUCCEEDED(mEditor->GetIsInEditAction(&isInEditAction)) &&
-      isInEditAction) {
+  if (mEditorBase && mEditorBase->IsInEditAction()) {
     return false;
   }
 
   return true;
 }
 
 void
 IMEContentObserver::FlushMergeableNotifications()
--- a/dom/events/IMEContentObserver.h
+++ b/dom/events/IMEContentObserver.h
@@ -3,20 +3,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_IMEContentObserver_h_
 #define mozilla_IMEContentObserver_h_
 
 #include "mozilla/Attributes.h"
+#include "mozilla/EditorBase.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDocShell.h" // XXX Why does only this need to be included here?
-#include "nsIEditor.h"
 #include "nsIEditorObserver.h"
 #include "nsIReflowObserver.h"
 #include "nsISelectionListener.h"
 #include "nsIScrollObserver.h"
 #include "nsIWidget.h"
 #include "nsStubDocumentObserver.h"
 #include "nsStubMutationObserver.h"
 #include "nsThreadUtils.h"
@@ -81,24 +81,24 @@ public:
    * won't be released during calling this.
    *
    * @param aWidget         The widget which can access native IME.
    * @param aPresContext    The PresContext which has aContent.
    * @param aContent        An editable element or a plugin host element which
    *                        user may use IME in.
    *                        Or nullptr if this will observe design mode
    *                        document.
-   * @param aEditor         When aContent is an editable element or nullptr,
+   * @param aEditorBase     When aContent is an editable element or nullptr,
    *                        non-nullptr referring an editor instance which
    *                        manages aContent.
    *                        Otherwise, i.e., this will observe a plugin content,
    *                        should be nullptr.
    */
   void Init(nsIWidget* aWidget, nsPresContext* aPresContext,
-            nsIContent* aContent, nsIEditor* aEditor);
+            nsIContent* aContent, EditorBase* aEditorBase);
 
   /**
    * Destroy() finalizes the instance, i.e., stops observing contents and
    * clearing the members.
    * Be aware, callers of this method need to guarantee that the instance
    * won't be released during calling this.
    */
   void Destroy();
@@ -124,29 +124,32 @@ public:
    * won't be released during calling this.
    *
    * @return            Returns true if the instance is managing the content.
    *                    Otherwise, false.
    */
   bool MaybeReinitialize(nsIWidget* aWidget,
                          nsPresContext* aPresContext,
                          nsIContent* aContent,
-                         nsIEditor* aEditor);
+                         EditorBase* aEditorBase);
 
   bool IsManaging(nsPresContext* aPresContext, nsIContent* aContent) const;
   bool IsManaging(const TextComposition* aTextComposition) const;
   bool WasInitializedWithPlugin() const;
+  bool WasInitializedWith(const EditorBase& aEditorBase) const
+  {
+    return mEditorBase == &aEditorBase;
+  }
   bool IsEditorHandlingEventForComposition() const;
   bool KeepAliveDuringDeactive() const
   {
     return mIMENotificationRequests &&
            mIMENotificationRequests->WantDuringDeactive();
   }
   nsIWidget* GetWidget() const { return mWidget; }
-  nsIEditor* GetEditor() const { return mEditor; }
   void SuppressNotifyingIME();
   void UnsuppressNotifyingIME();
   nsPresContext* GetPresContext() const;
   nsresult GetSelectionAndRoot(nsISelection** aSelection,
                                nsIContent** aRoot) const;
 
   /**
    * TryToFlushPendingNotifications() should be called when pending events
@@ -166,19 +169,19 @@ private:
   enum State {
     eState_NotObserving,
     eState_Initializing,
     eState_StoppedObserving,
     eState_Observing
   };
   State GetState() const;
   bool InitWithEditor(nsPresContext* aPresContext, nsIContent* aContent,
-                      nsIEditor* aEditor);
+                      EditorBase* aEditorBase);
   bool InitWithPlugin(nsPresContext* aPresContext, nsIContent* aContent);
-  bool IsInitializedWithPlugin() const { return !mEditor; }
+  bool IsInitializedWithPlugin() const { return !mEditorBase; }
   void OnIMEReceivedFocus();
   void Clear();
   bool IsObservingContent(nsPresContext* aPresContext,
                           nsIContent* aContent) const;
   bool IsReflowLocked() const;
   bool IsSafeToNotifyIME() const;
   bool IsEditorComposing() const;
 
@@ -302,17 +305,17 @@ private:
   // mFocusedWidget has the editor observed by the instance.  E.g., if the
   // focused editor is in XUL panel, this should be the widget of the panel.
   // On the other hand, mWidget is its parent which handles IME.
   nsCOMPtr<nsIWidget> mFocusedWidget;
   nsCOMPtr<nsISelection> mSelection;
   nsCOMPtr<nsIContent> mRootContent;
   nsCOMPtr<nsINode> mEditableNode;
   nsCOMPtr<nsIDocShell> mDocShell;
-  nsCOMPtr<nsIEditor> mEditor;
+  RefPtr<EditorBase> mEditorBase;
 
   /**
    * Helper classes to notify IME.
    */
 
   class AChangeEvent: public Runnable
   {
   protected:
--- a/dom/events/IMEStateManager.cpp
+++ b/dom/events/IMEStateManager.cpp
@@ -703,22 +703,22 @@ IMEStateManager::OnClickInEditor(nsPresC
   IMEState newState = GetNewIMEState(aPresContext, aContent);
   SetIMEState(newState, aContent, widget, action);
 }
 
 // static
 void
 IMEStateManager::OnFocusInEditor(nsPresContext* aPresContext,
                                  nsIContent* aContent,
-                                 nsIEditor* aEditor)
+                                 EditorBase& aEditorBase)
 {
   MOZ_LOG(sISMLog, LogLevel::Info,
-    ("OnFocusInEditor(aPresContext=0x%p, aContent=0x%p, aEditor=0x%p), "
+    ("OnFocusInEditor(aPresContext=0x%p, aContent=0x%p, aEditorBase=0x%p), "
      "sPresContext=0x%p, sContent=0x%p, sActiveIMEContentObserver=0x%p",
-     aPresContext, aContent, aEditor, sPresContext.get(), sContent.get(),
+     aPresContext, aContent, &aEditorBase, sPresContext.get(), sContent.get(),
      sActiveIMEContentObserver.get()));
 
   if (sPresContext != aPresContext || sContent != aContent) {
     MOZ_LOG(sISMLog, LogLevel::Debug,
       ("  OnFocusInEditor(), "
        "an editor not managed by ISM gets focus"));
     return;
   }
@@ -730,55 +730,55 @@ IMEStateManager::OnFocusInEditor(nsPresC
       MOZ_LOG(sISMLog, LogLevel::Debug,
         ("  OnFocusInEditor(), "
          "the editor is already being managed by sActiveIMEContentObserver"));
       return;
     }
     DestroyIMEContentObserver();
   }
 
-  CreateIMEContentObserver(aEditor);
+  CreateIMEContentObserver(&aEditorBase);
 
   // Let's flush the focus notification now.
   if (sActiveIMEContentObserver) {
     MOZ_LOG(sISMLog, LogLevel::Debug,
       ("  OnFocusInEditor(), new IMEContentObserver is "
        "created, trying to flush pending notifications..."));
     sActiveIMEContentObserver->TryToFlushPendingNotifications();
   }
 }
 
 // static
 void
-IMEStateManager::OnEditorInitialized(nsIEditor* aEditor)
+IMEStateManager::OnEditorInitialized(EditorBase& aEditorBase)
 {
   if (!sActiveIMEContentObserver ||
-      sActiveIMEContentObserver->GetEditor() != aEditor) {
+      !sActiveIMEContentObserver->WasInitializedWith(aEditorBase)) {
     return;
   }
 
   MOZ_LOG(sISMLog, LogLevel::Info,
-    ("OnEditorInitialized(aEditor=0x%p)",
-     aEditor));
+    ("OnEditorInitialized(aEditorBase=0x%p)",
+     &aEditorBase));
 
   sActiveIMEContentObserver->UnsuppressNotifyingIME();
 }
 
 // static
 void
-IMEStateManager::OnEditorDestroying(nsIEditor* aEditor)
+IMEStateManager::OnEditorDestroying(EditorBase& aEditorBase)
 {
   if (!sActiveIMEContentObserver ||
-      sActiveIMEContentObserver->GetEditor() != aEditor) {
+      !sActiveIMEContentObserver->WasInitializedWith(aEditorBase)) {
     return;
   }
 
   MOZ_LOG(sISMLog, LogLevel::Info,
-    ("OnEditorDestroying(aEditor=0x%p)",
-     aEditor));
+    ("OnEditorDestroying(aEditorBase=0x%p)",
+     &aEditorBase));
 
   // The IMEContentObserver shouldn't notify IME of anything until reframing
   // is finished.
   sActiveIMEContentObserver->SuppressNotifyingIME();
 }
 
 // static
 void
@@ -1664,24 +1664,24 @@ IMEStateManager::DestroyIMEContentObserv
      "the active IMEContentObserver..."));
   RefPtr<IMEContentObserver> tsm = sActiveIMEContentObserver.get();
   sActiveIMEContentObserver = nullptr;
   tsm->Destroy();
 }
 
 // static
 void
-IMEStateManager::CreateIMEContentObserver(nsIEditor* aEditor)
+IMEStateManager::CreateIMEContentObserver(EditorBase* aEditorBase)
 {
   MOZ_LOG(sISMLog, LogLevel::Info,
-    ("CreateIMEContentObserver(aEditor=0x%p), "
+    ("CreateIMEContentObserver(aEditorBase=0x%p), "
      "sPresContext=0x%p, sContent=0x%p, sWidget=0x%p (available: %s), "
      "sActiveIMEContentObserver=0x%p, "
      "sActiveIMEContentObserver->IsManaging(sPresContext, sContent)=%s",
-     aEditor, sPresContext.get(), sContent.get(),
+     aEditorBase, sPresContext.get(), sContent.get(),
      sWidget, GetBoolName(sWidget && !sWidget->Destroyed()),
      sActiveIMEContentObserver.get(),
      GetBoolName(sActiveIMEContentObserver ?
        sActiveIMEContentObserver->IsManaging(sPresContext, sContent) : false)));
 
   if (NS_WARN_IF(sActiveIMEContentObserver)) {
     MOZ_LOG(sISMLog, LogLevel::Error,
       ("  CreateIMEContentObserver(), FAILED due to "
@@ -1720,17 +1720,17 @@ IMEStateManager::CreateIMEContentObserve
     ("  CreateIMEContentObserver() is creating an "
      "IMEContentObserver instance..."));
   sActiveIMEContentObserver = new IMEContentObserver();
 
   // IMEContentObserver::Init() might create another IMEContentObserver
   // instance.  So, sActiveIMEContentObserver would be replaced with new one.
   // We should hold the current instance here.
   RefPtr<IMEContentObserver> activeIMEContentObserver(sActiveIMEContentObserver);
-  activeIMEContentObserver->Init(widget, sPresContext, sContent, aEditor);
+  activeIMEContentObserver->Init(widget, sPresContext, sContent, aEditorBase);
 }
 
 // static
 nsresult
 IMEStateManager::GetFocusSelectionAndRoot(nsISelection** aSelection,
                                           nsIContent** aRootContent)
 {
   if (!sActiveIMEContentObserver) {
--- a/dom/events/IMEStateManager.h
+++ b/dom/events/IMEStateManager.h
@@ -154,24 +154,24 @@ public:
 
   // This method is called when editor actually gets focus.
   // aContent must be:
   //   If the editor is for <input> or <textarea>, the element.
   //   If the editor is for contenteditable, the active editinghost.
   //   If the editor is for designMode, nullptr.
   static void OnFocusInEditor(nsPresContext* aPresContext,
                               nsIContent* aContent,
-                              nsIEditor* aEditor);
+                              EditorBase& aEditorBase);
 
   // This method is called when the editor is initialized.
-  static void OnEditorInitialized(nsIEditor* aEditor);
+  static void OnEditorInitialized(EditorBase& aEditorBase);
 
   // This method is called when the editor is (might be temporarily) being
   // destroyed.
-  static void OnEditorDestroying(nsIEditor* aEditor);
+  static void OnEditorDestroying(EditorBase& aEditorBase);
 
   /**
    * All composition events must be dispatched via DispatchCompositionEvent()
    * for storing the composition target and ensuring a set of composition
    * events must be fired the stored target.  If the stored composition event
    * target is destroying, this removes the stored composition automatically.
    */
   static void DispatchCompositionEvent(
@@ -251,17 +251,17 @@ protected:
                           InputContextAction aAction);
   static void SetInputContext(nsIWidget* aWidget,
                               const InputContext& aInputContext,
                               const InputContextAction& aAction);
   static IMEState GetNewIMEState(nsPresContext* aPresContext,
                                  nsIContent* aContent);
 
   static void EnsureTextCompositionArray();
-  static void CreateIMEContentObserver(nsIEditor* aEditor);
+  static void CreateIMEContentObserver(EditorBase* aEditorBase);
   static void DestroyIMEContentObserver();
 
   static bool IsEditable(nsINode* node);
 
   static bool IsIMEObserverNeeded(const IMEState& aState);
 
   static nsIContent* GetRootContent(nsPresContext* aPresContext);
 
--- a/dom/events/TextComposition.cpp
+++ b/dom/events/TextComposition.cpp
@@ -4,20 +4,20 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ContentEventHandler.h"
 #include "IMEContentObserver.h"
 #include "IMEStateManager.h"
 #include "nsContentUtils.h"
 #include "nsIContent.h"
-#include "nsIEditor.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "mozilla/AutoRestore.h"
+#include "mozilla/EditorBase.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/IMEStateManager.h"
 #include "mozilla/MiscEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/TextComposition.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/Unused.h"
 #include "mozilla/dom/TabParent.h"
@@ -668,48 +668,49 @@ TextComposition::OnEditorDestroyed()
 void
 TextComposition::EditorDidHandleCompositionChangeEvent()
 {
   mString = mLastData;
   mIsEditorHandlingEvent = false;
 }
 
 void
-TextComposition::StartHandlingComposition(nsIEditor* aEditor)
+TextComposition::StartHandlingComposition(EditorBase* aEditorBase)
 {
   MOZ_RELEASE_ASSERT(!mTabParent);
 
   MOZ_ASSERT(!HasEditor(), "There is a handling editor already");
-  mEditorWeak = do_GetWeakReference(aEditor);
+  mEditorBaseWeak = do_GetWeakReference(static_cast<nsIEditor*>(aEditorBase));
 }
 
 void
-TextComposition::EndHandlingComposition(nsIEditor* aEditor)
+TextComposition::EndHandlingComposition(EditorBase* aEditorBase)
 {
   MOZ_RELEASE_ASSERT(!mTabParent);
 
 #ifdef DEBUG
-  nsCOMPtr<nsIEditor> editor = GetEditor();
-  MOZ_ASSERT(editor == aEditor, "Another editor handled the composition?");
+  RefPtr<EditorBase> editorBase = GetEditorBase();
+  MOZ_ASSERT(editorBase == aEditorBase,
+             "Another editor handled the composition?");
 #endif // #ifdef DEBUG
-  mEditorWeak = nullptr;
+  mEditorBaseWeak = nullptr;
 }
 
-already_AddRefed<nsIEditor>
-TextComposition::GetEditor() const
+already_AddRefed<EditorBase>
+TextComposition::GetEditorBase() const
 {
-  nsCOMPtr<nsIEditor> editor = do_QueryReferent(mEditorWeak);
-  return editor.forget();
+  nsCOMPtr<nsIEditor> editor = do_QueryReferent(mEditorBaseWeak);
+  RefPtr<EditorBase> editorBase = static_cast<EditorBase*>(editor.get());
+  return editorBase.forget();
 }
 
 bool
 TextComposition::HasEditor() const
 {
-  nsCOMPtr<nsIEditor> editor = GetEditor();
-  return !!editor;
+  return mEditorBaseWeak && mEditorBaseWeak->IsAlive();
 }
 
 /******************************************************************************
  * TextComposition::CompositionEventDispatcher
  ******************************************************************************/
 
 TextComposition::CompositionEventDispatcher::CompositionEventDispatcher(
                                                TextComposition* aComposition,
--- a/dom/events/TextComposition.h
+++ b/dom/events/TextComposition.h
@@ -14,20 +14,19 @@
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 #include "nsPresContext.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/TextRange.h"
 #include "mozilla/dom/TabParent.h"
 
-class nsIEditor;
-
 namespace mozilla {
 
+class EditorBase;
 class EventDispatchingCallback;
 class IMEStateManager;
 
 /**
  * TextComposition represents a text composition.  This class stores the
  * composition event target and its presContext.  At dispatching the event via
  * this class, the instances use the stored event target.
  */
@@ -132,18 +131,18 @@ public:
   {
     return mIsEditorHandlingEvent;
   }
 
   /**
    * StartHandlingComposition() and EndHandlingComposition() are called by
    * editor when it holds a TextComposition instance and release it.
    */
-  void StartHandlingComposition(nsIEditor* aEditor);
-  void EndHandlingComposition(nsIEditor* aEditor);
+  void StartHandlingComposition(EditorBase* aEditorBase);
+  void EndHandlingComposition(EditorBase* aEditorBase);
 
   /**
    * OnEditorDestroyed() is called when the editor is destroyed but there is
    * active composition.
    */
   void OnEditorDestroyed();
 
   /**
@@ -198,18 +197,19 @@ private:
   // Same as mRange, but mRange will have old data during compositionupdate.
   // So this will be valied during compositionupdate.
   RefPtr<TextRangeArray> mLastRanges;
 
   // mNativeContext stores a opaque pointer.  This works as the "ID" for this
   // composition.  Don't access the instance, it may not be available.
   widget::NativeIMEContext mNativeContext;
 
-  // mEditorWeak is a weak reference to the focused editor handling composition.
-  nsWeakPtr mEditorWeak;
+  // mEditorBaseWeak is a weak reference to the focused editor handling
+  // composition.
+  nsWeakPtr mEditorBaseWeak;
 
   // mLastData stores the data attribute of the latest composition event (except
   // the compositionstart event).
   nsString mLastData;
 
   // mString stores the composition text which has been handled by the focused
   // editor.
   nsString mString;
@@ -278,23 +278,23 @@ private:
     , mWasNativeCompositionEndEventDiscarded(false)
     , mAllowControlCharacters(false)
     , mWasCompositionStringEmpty(true)
     , mHasDispatchedCompositionEvents(false)
   {}
   TextComposition(const TextComposition& aOther);
 
   /**
-   * GetEditor() returns nsIEditor pointer of mEditorWeak.
+   * GetEditorBase() returns EditorBase pointer of mEditorBaseWeak.
    */
-  already_AddRefed<nsIEditor> GetEditor() const;
+  already_AddRefed<EditorBase> GetEditorBase() const;
 
   /**
-   * HasEditor() returns true if mEditorWeak holds nsIEditor instance which is
-   * alive.  Otherwise, false.
+   * HasEditor() returns true if mEditorBaseWeak holds EditorBase instance
+   * which is alive.  Otherwise, false.
    */
   bool HasEditor() const;
 
   /**
    * EditorWillHandleCompositionChangeEvent() must be called before the focused
    * editor handles the compositionchange event.
    */
   void EditorWillHandleCompositionChangeEvent(
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -327,17 +327,17 @@ EditorBase::PostCreate()
     IMEState newState;
     rv = GetPreferredIMEState(&newState);
     NS_ENSURE_SUCCESS(rv, NS_OK);
     nsCOMPtr<nsIContent> content = GetFocusedContentForIME();
     IMEStateManager::UpdateIMEState(newState, content, *this);
   }
 
   // FYI: This call might cause destroying this editor.
-  IMEStateManager::OnEditorInitialized(this);
+  IMEStateManager::OnEditorInitialized(*this);
 
   return NS_OK;
 }
 
 void
 EditorBase::CreateEventListeners()
 {
   // Don't create the handler twice
@@ -437,17 +437,17 @@ EditorBase::GetDesiredSpellCheckState()
 }
 
 NS_IMETHODIMP
 EditorBase::PreDestroy(bool aDestroyingFrames)
 {
   if (mDidPreDestroy)
     return NS_OK;
 
-  IMEStateManager::OnEditorDestroying(this);
+  IMEStateManager::OnEditorDestroying(*this);
 
   // Let spellchecker clean up its observers etc. It is important not to
   // actually free the spellchecker here, since the spellchecker could have
   // caused flush notifications, which could have gotten here if a textbox
   // is being removed. Setting the spellchecker to nullptr could free the
   // object that is still in use! It will be freed when the editor is
   // destroyed.
   if (mInlineSpellChecker)
--- a/editor/libeditor/EditorEventListener.cpp
+++ b/editor/libeditor/EditorEventListener.cpp
@@ -1152,17 +1152,17 @@ EditorEventListener::Focus(InternalFocus
   if (DetachedFromEditorOrDefaultPrevented(aFocusEvent)) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIPresShell> ps = GetPresShell();
   NS_ENSURE_TRUE(ps, NS_OK);
   nsCOMPtr<nsIContent> focusedContent = editorBase->GetFocusedContentForIME();
   IMEStateManager::OnFocusInEditor(ps->GetPresContext(), focusedContent,
-                                   editorBase);
+                                   *editorBase);
 
   return NS_OK;
 }
 
 nsresult
 EditorEventListener::Blur(InternalFocusEvent* aBlurEvent)
 {
   if (NS_WARN_IF(!aBlurEvent) || DetachedFromEditor()) {