Bug 1047588 IMEContentObserver::Init() should take nsIEditor because nsDocShell sometimes hasn't been initialized and nsContentEditor::GetHTMLEditor() fails r=smaug
☠☠ backed out by 919fe1b47dbb ☠ ☠
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 05 Nov 2014 10:36:37 +0900
changeset 214040 f86dbba73d43d8f87eb93a1b218397e0f22a8f53
parent 214039 4bdc3391644e7200cb8419cdf59e502f36424498
child 214041 2dbf8f6bd2aa84cd40137ece81e81d6d2cbb7ea8
push id27771
push userryanvm@gmail.com
push dateWed, 05 Nov 2014 19:04:24 +0000
treeherdermozilla-central@305b4fecce99 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1047588
milestone36.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 1047588 IMEContentObserver::Init() should take nsIEditor because nsDocShell sometimes hasn't been initialized and nsContentEditor::GetHTMLEditor() fails r=smaug
dom/events/IMEContentObserver.cpp
dom/events/IMEContentObserver.h
dom/events/IMEStateManager.cpp
dom/events/IMEStateManager.h
editor/libeditor/nsEditor.cpp
editor/libeditor/nsEditorEventListener.cpp
--- a/dom/events/IMEContentObserver.cpp
+++ b/dom/events/IMEContentObserver.cpp
@@ -23,17 +23,16 @@
 #include "nsIDOMDocument.h"
 #include "nsIDOMRange.h"
 #include "nsIFrame.h"
 #include "nsINode.h"
 #include "nsIPresShell.h"
 #include "nsISelectionController.h"
 #include "nsISelectionPrivate.h"
 #include "nsISupports.h"
-#include "nsITextControlElement.h"
 #include "nsIWidget.h"
 #include "nsPresContext.h"
 #include "nsThreadUtils.h"
 #include "nsWeakReference.h"
 
 namespace mozilla {
 
 using namespace widget;
@@ -94,48 +93,32 @@ IMEContentObserver::IMEContentObserver()
 #ifdef DEBUG
   TestMergingTextChangeData();
 #endif
 }
 
 void
 IMEContentObserver::Init(nsIWidget* aWidget,
                          nsPresContext* aPresContext,
-                         nsIContent* aContent)
+                         nsIContent* aContent,
+                         nsIEditor* aEditor)
 {
+  MOZ_ASSERT(aEditor, "aEditor must not be null");
+
   mESM = aPresContext->EventStateManager();
   mESM->OnStartToObserveContent(this);
 
   mWidget = aWidget;
   mEditableNode = IMEStateManager::GetRootEditableNode(aPresContext, aContent);
   if (!mEditableNode) {
     return;
   }
 
-  nsCOMPtr<nsITextControlElement> textControlElement =
-    do_QueryInterface(mEditableNode);
-  if (textControlElement) {
-    // This may fail. For example, <input type="button" contenteditable>
-    mEditor = textControlElement->GetTextEditor();
-    if (!mEditor && mEditableNode->IsContent()) {
-      // The element must be an editing host.
-      nsIContent* editingHost = mEditableNode->AsContent()->GetEditingHost();
-      MOZ_ASSERT(editingHost == mEditableNode,
-                 "found editing host should be mEditableNode");
-      if (editingHost == mEditableNode) {
-        mEditor = nsContentUtils::GetHTMLEditor(aPresContext);
-      }
-    }
-  } else {
-    mEditor = nsContentUtils::GetHTMLEditor(aPresContext);
-  }
-  MOZ_ASSERT(mEditor, "Failed to get editor");
-  if (mEditor) {
-    mEditor->AddEditorObserver(this);
-  }
+  mEditor = aEditor;
+  mEditor->AddEditorObserver(this);
 
   nsIPresShell* presShell = aPresContext->PresShell();
 
   // get selection and root content
   nsCOMPtr<nsISelectionController> selCon;
   if (mEditableNode->IsNodeOfType(nsINode::eCONTENT)) {
     nsIFrame* frame =
       static_cast<nsIContent*>(mEditableNode.get())->GetPrimaryFrame();
--- a/dom/events/IMEContentObserver.h
+++ b/dom/events/IMEContentObserver.h
@@ -59,17 +59,17 @@ public:
 
   // nsIScrollObserver
   virtual void ScrollPositionChanged() MOZ_OVERRIDE;
 
   bool OnMouseButtonEvent(nsPresContext* aPresContext,
                           WidgetMouseEvent* aMouseEvent);
 
   void Init(nsIWidget* aWidget, nsPresContext* aPresContext,
-            nsIContent* aContent);
+            nsIContent* aContent, nsIEditor* aEditor);
   void Destroy();
   /**
    * IMEContentObserver is stored by EventStateManager during observing.
    * DisconnectFromEventStateManager() is called when EventStateManager stops
    * storing the instance.
    */
   void DisconnectFromEventStateManager();
   bool IsManaging(nsPresContext* aPresContext, nsIContent* aContent);
--- a/dom/events/IMEStateManager.cpp
+++ b/dom/events/IMEStateManager.cpp
@@ -20,16 +20,17 @@
 #include "HTMLInputElement.h"
 #include "IMEContentObserver.h"
 
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsIDOMMouseEvent.h"
+#include "nsIEditor.h"
 #include "nsIForm.h"
 #include "nsIFormControl.h"
 #include "nsINode.h"
 #include "nsIObserverService.h"
 #include "nsIPresShell.h"
 #include "nsISelection.h"
 #include "nsISupports.h"
 #include "nsPresContext.h"
@@ -554,22 +555,24 @@ IMEStateManager::OnClickInEditor(nsPresC
                             InputContextAction::FOCUS_NOT_CHANGED);
   IMEState newState = GetNewIMEState(aPresContext, aContent);
   SetIMEState(newState, aContent, widget, action);
 }
 
 // static
 void
 IMEStateManager::OnFocusInEditor(nsPresContext* aPresContext,
-                                 nsIContent* aContent)
+                                 nsIContent* aContent,
+                                 nsIEditor* aEditor)
 {
   PR_LOG(sISMLog, PR_LOG_ALWAYS,
-    ("ISM: IMEStateManager::OnFocusInEditor(aPresContext=0x%p, aContent=0x%p), "
-     "sPresContext=0x%p, sContent=0x%p, sActiveIMEContentObserver=0x%p",
-     aPresContext, aContent, sPresContext, sContent,
+    ("ISM: IMEStateManager::OnFocusInEditor(aPresContext=0x%p, aContent=0x%p, "
+     "aEditor=0x%p), sPresContext=0x%p, sContent=0x%p, "
+     "sActiveIMEContentObserver=0x%p",
+     aPresContext, aContent, aEditor, sPresContext, sContent,
      sActiveIMEContentObserver));
 
   if (sPresContext != aPresContext || sContent != aContent) {
     PR_LOG(sISMLog, PR_LOG_DEBUG,
       ("ISM:   IMEStateManager::OnFocusInEditor(), "
        "an editor not managed by ISM gets focus"));
     return;
   }
@@ -581,31 +584,32 @@ IMEStateManager::OnFocusInEditor(nsPresC
       PR_LOG(sISMLog, PR_LOG_DEBUG,
         ("ISM:   IMEStateManager::OnFocusInEditor(), "
          "the editor is already being managed by sActiveIMEContentObserver"));
       return;
     }
     DestroyIMEContentObserver();
   }
 
-  CreateIMEContentObserver();
+  CreateIMEContentObserver(aEditor);
 }
 
 // static
 void
 IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
-                                nsIContent* aContent)
+                                nsIContent* aContent,
+                                nsIEditor* aEditor)
 {
   PR_LOG(sISMLog, PR_LOG_ALWAYS,
     ("ISM: IMEStateManager::UpdateIMEState(aNewIMEState={ mEnabled=%s, "
-     "mOpen=%s }, aContent=0x%p), "
+     "mOpen=%s }, aContent=0x%p, aEditor=0x%p), "
      "sPresContext=0x%p, sContent=0x%p, sActiveIMEContentObserver=0x%p, "
      "sIsGettingNewIMEState=%s",
      GetIMEStateEnabledName(aNewIMEState.mEnabled),
-     GetIMEStateSetOpenName(aNewIMEState.mOpen), aContent,
+     GetIMEStateSetOpenName(aNewIMEState.mOpen), aContent, aEditor,
      sPresContext, sContent, sActiveIMEContentObserver,
      GetBoolName(sIsGettingNewIMEState)));
 
   if (sIsGettingNewIMEState) {
     PR_LOG(sISMLog, PR_LOG_DEBUG,
       ("ISM:   IMEStateManager::UpdateIMEState(), "
        "does nothing because of called while getting new IME state"));
     return;
@@ -646,17 +650,17 @@ IMEStateManager::UpdateIMEState(const IM
 
   if (updateIMEState) {
     InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
                               InputContextAction::FOCUS_NOT_CHANGED);
     SetIMEState(aNewIMEState, aContent, widget, action);
   }
 
   if (createTextStateManager) {
-    CreateIMEContentObserver();
+    CreateIMEContentObserver(aEditor);
   }
 }
 
 // static
 IMEState
 IMEStateManager::GetNewIMEState(nsPresContext* aPresContext,
                                 nsIContent*    aContent)
 {
@@ -1140,23 +1144,23 @@ IMEStateManager::DestroyIMEContentObserv
      "the active IMEContentObserver..."));
   nsRefPtr<IMEContentObserver> tsm;
   tsm.swap(sActiveIMEContentObserver);
   tsm->Destroy();
 }
 
 // static
 void
-IMEStateManager::CreateIMEContentObserver()
+IMEStateManager::CreateIMEContentObserver(nsIEditor* aEditor)
 {
   PR_LOG(sISMLog, PR_LOG_ALWAYS,
-    ("ISM: IMEStateManager::CreateIMEContentObserver(), "
+    ("ISM: IMEStateManager::CreateIMEContentObserver(aEditor=0x%p), "
      "sPresContext=0x%p, sContent=0x%p, sActiveIMEContentObserver=0x%p, "
      "sActiveIMEContentObserver->IsManaging(sPresContext, sContent)=%s",
-     sPresContext, sContent, sActiveIMEContentObserver,
+     aEditor, sPresContext, sContent, sActiveIMEContentObserver,
      GetBoolName(sActiveIMEContentObserver ?
        sActiveIMEContentObserver->IsManaging(sPresContext, sContent) : false)));
 
   if (NS_WARN_IF(sActiveIMEContentObserver)) {
     PR_LOG(sISMLog, PR_LOG_ERROR,
       ("ISM:   IMEStateManager::CreateIMEContentObserver(), FAILED due to "
        "there is already an active IMEContentObserver"));
     MOZ_ASSERT(sActiveIMEContentObserver->IsManaging(sPresContext, sContent));
@@ -1190,17 +1194,17 @@ IMEStateManager::CreateIMEContentObserve
      "IMEContentObserver instance..."));
   sActiveIMEContentObserver = new IMEContentObserver();
   NS_ADDREF(sActiveIMEContentObserver);
 
   // IMEContentObserver::Init() might create another IMEContentObserver
   // instance.  So, sActiveIMEContentObserver would be replaced with new one.
   // We should hold the current instance here.
   nsRefPtr<IMEContentObserver> kungFuDeathGrip(sActiveIMEContentObserver);
-  sActiveIMEContentObserver->Init(widget, sPresContext, sContent);
+  sActiveIMEContentObserver->Init(widget, sPresContext, sContent, aEditor);
 }
 
 // static
 nsresult
 IMEStateManager::GetFocusSelectionAndRoot(nsISelection** aSelection,
                                           nsIContent** aRootContent)
 {
   if (!sActiveIMEContentObserver) {
--- a/dom/events/IMEStateManager.h
+++ b/dom/events/IMEStateManager.h
@@ -6,16 +6,17 @@
 #ifndef mozilla_IMEStateManager_h_
 #define mozilla_IMEStateManager_h_
 
 #include "mozilla/EventForwards.h"
 #include "nsIWidget.h"
 
 class nsIContent;
 class nsIDOMMouseEvent;
+class nsIEditor;
 class nsINode;
 class nsPIDOMWindow;
 class nsPresContext;
 class nsISelection;
 
 namespace mozilla {
 
 class EventDispatchingCallback;
@@ -60,17 +61,18 @@ public:
   // Get the focused editor's selection and root
   static nsresult GetFocusSelectionAndRoot(nsISelection** aSel,
                                            nsIContent** aRoot);
   // This method updates the current IME state.  However, if the enabled state
   // isn't changed by the new state, this method does nothing.
   // Note that this method changes the IME state of the active element in the
   // widget.  So, the caller must have focus.
   static void UpdateIMEState(const IMEState &aNewIMEState,
-                             nsIContent* aContent);
+                             nsIContent* aContent,
+                             nsIEditor* aEditor);
 
   // This method is called when user operates mouse button in focused editor
   // and before the editor handles it.
   // Returns true if IME consumes the event.  Otherwise, false.
   static bool OnMouseButtonEventInEditor(nsPresContext* aPresContext,
                                          nsIContent* aContent,
                                          nsIDOMMouseEvent* aMouseEvent);
 
@@ -84,17 +86,18 @@ public:
                               nsIDOMMouseEvent* aMouseEvent);
 
   // 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);
+                              nsIContent* aContent,
+                              nsIEditor* aEditor);
 
   /**
    * 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(
@@ -144,17 +147,17 @@ protected:
   static void SetIMEState(const IMEState &aState,
                           nsIContent* aContent,
                           nsIWidget* aWidget,
                           InputContextAction aAction);
   static IMEState GetNewIMEState(nsPresContext* aPresContext,
                                  nsIContent* aContent);
 
   static void EnsureTextCompositionArray();
-  static void CreateIMEContentObserver();
+  static void CreateIMEContentObserver(nsIEditor* aEditor);
   static void DestroyIMEContentObserver();
 
   static bool IsEditable(nsINode* node);
 
   static bool IsEditableIMEState(nsIWidget* aWidget);
 
   static nsIContent*    sContent;
   static nsPresContext* sPresContext;
--- a/editor/libeditor/nsEditor.cpp
+++ b/editor/libeditor/nsEditor.cpp
@@ -310,17 +310,17 @@ nsEditor::PostCreate()
     nsEditorEventListener* listener =
       reinterpret_cast<nsEditorEventListener*> (mEventListener.get());
     listener->SpellCheckIfNeeded();
 
     IMEState newState;
     rv = GetPreferredIMEState(&newState);
     NS_ENSURE_SUCCESS(rv, NS_OK);
     nsCOMPtr<nsIContent> content = GetFocusedContentForIME();
-    IMEStateManager::UpdateIMEState(newState, content);
+    IMEStateManager::UpdateIMEState(newState, content, this);
   }
   return NS_OK;
 }
 
 /* virtual */
 void
 nsEditor::CreateEventListeners()
 {
@@ -491,17 +491,17 @@ nsEditor::SetFlags(uint32_t aFlags)
   nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
   if (focusedContent) {
     IMEState newState;
     nsresult rv = GetPreferredIMEState(&newState);
     if (NS_SUCCEEDED(rv)) {
       // NOTE: When the enabled state isn't going to be modified, this method
       // is going to do nothing.
       nsCOMPtr<nsIContent> content = GetFocusedContentForIME();
-      IMEStateManager::UpdateIMEState(newState, content);
+      IMEStateManager::UpdateIMEState(newState, content, this);
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsEditor::GetIsSelectionEditable(bool *aIsSelectionEditable)
--- a/editor/libeditor/nsEditorEventListener.cpp
+++ b/editor/libeditor/nsEditorEventListener.cpp
@@ -1092,17 +1092,18 @@ nsEditorEventListener::Focus(nsIDOMEvent
     }
   }
 
   mEditor->OnFocus(target);
 
   nsCOMPtr<nsIPresShell> ps = GetPresShell();
   NS_ENSURE_TRUE(ps, NS_OK);
   nsCOMPtr<nsIContent> focusedContent = mEditor->GetFocusedContentForIME();
-  IMEStateManager::OnFocusInEditor(ps->GetPresContext(), focusedContent);
+  IMEStateManager::OnFocusInEditor(ps->GetPresContext(), focusedContent,
+                                   mEditor);
 
   return NS_OK;
 }
 
 nsresult
 nsEditorEventListener::Blur(nsIDOMEvent* aEvent)
 {
   NS_ENSURE_TRUE(aEvent, NS_OK);