Bug 1345763 part.2 Implement AsHTMLEditor() in EditorBase and its subclasses and replace casts with it r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 09 Mar 2017 18:38:41 +0900
changeset 347026 743d5c04dc0737da31a6da1e7ee34ef6843bde3b
parent 347025 a0a3c9bacb1e1188e16e1127000c6a662641c70c
child 347027 aa2376407a4d130e54e2b1949991d5c7de65706d
push id31490
push usercbook@mozilla.com
push dateMon, 13 Mar 2017 14:19:54 +0000
treeherdermozilla-central@419c70029023 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1345763
milestone55.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 1345763 part.2 Implement AsHTMLEditor() in EditorBase and its subclasses and replace casts with it r=smaug MozReview-Commit-ID: CUYV0tMjQHH
editor/libeditor/EditorBase.h
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditor.h
editor/libeditor/HTMLEditorEventListener.cpp
editor/libeditor/HTMLEditorEventListener.h
editor/libeditor/TextEditor.cpp
editor/libeditor/TextEditor.h
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -108,16 +108,17 @@ class AutoSelectionRestorer;
 class AutoTransactionsConserveSelection;
 class ChangeAttributeTransaction;
 class CompositionTransaction;
 class CreateElementTransaction;
 class DeleteNodeTransaction;
 class DeleteTextTransaction;
 class EditAggregateTransaction;
 class ErrorResult;
+class HTMLEditor;
 class InsertNodeTransaction;
 class InsertTextTransaction;
 class JoinNodeTransaction;
 class RemoveStyleSheetTransaction;
 class SplitNodeTransaction;
 class TextComposition;
 class TextEditor;
 struct EditorDOMPoint;
@@ -162,16 +163,18 @@ public:
   /**
    * The default constructor. This should suffice. the setting of the
    * interfaces is done after the construction of the editor class.
    */
   EditorBase();
 
   virtual TextEditor* AsTextEditor() = 0;
   virtual const TextEditor* AsTextEditor() const = 0;
+  virtual HTMLEditor* AsHTMLEditor() = 0;
+  virtual const HTMLEditor* AsHTMLEditor() const = 0;
 
 protected:
   /**
    * The default destructor. This should suffice. Should this be pure virtual
    * for someone to derive from the EditorBase later? I don't believe so.
    */
   virtual ~EditorBase();
 
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -236,19 +236,26 @@ NS_INTERFACE_TABLE_TAIL_INHERITING(TextE
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLEditRules, TextEditRules,
                                    mDocChangeRange, mUtilRange, mNewBlock,
                                    mRangeItem)
 
 NS_IMETHODIMP
 HTMLEditRules::Init(TextEditor* aTextEditor)
 {
+  if (NS_WARN_IF(!aTextEditor)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
   InitFields();
 
-  mHTMLEditor = static_cast<HTMLEditor*>(aTextEditor);
+  mHTMLEditor = aTextEditor->AsHTMLEditor();
+  if (NS_WARN_IF(!mHTMLEditor)) {
+    return NS_ERROR_INVALID_ARG;
+  }
 
   // call through to base class Init
   nsresult rv = TextEditRules::Init(aTextEditor);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // cache any prefs we care about
   static const char kPrefName[] =
     "editor.html.typing.returnInEmptyListItemClosesList";
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -94,16 +94,19 @@ public:
     kHeight = 3
   };
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLEditor, TextEditor)
 
   HTMLEditor();
 
+  virtual HTMLEditor* AsHTMLEditor() override { return this; }
+  virtual const HTMLEditor* AsHTMLEditor() const override { return this; }
+
   bool GetReturnInParagraphCreatesNewParagraph();
   Element* GetSelectionContainer();
 
   // nsIEditor overrides
   NS_IMETHOD GetPreferredIMEState(widget::IMEState* aState) override;
 
   // TextEditor overrides
   NS_IMETHOD BeginningOfDocument() override;
--- a/editor/libeditor/HTMLEditorEventListener.cpp
+++ b/editor/libeditor/HTMLEditorEventListener.cpp
@@ -25,46 +25,41 @@
 #include "nsLiteralString.h"
 #include "nsQueryObject.h"
 #include "nsRange.h"
 
 namespace mozilla {
 
 using namespace dom;
 
-#ifdef DEBUG
 nsresult
 HTMLEditorEventListener::Connect(EditorBase* aEditorBase)
 {
-  nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryObject(aEditorBase);
-  nsCOMPtr<nsIHTMLInlineTableEditor> htmlInlineTableEditor =
-    do_QueryObject(aEditorBase);
-  NS_PRECONDITION(htmlEditor && htmlInlineTableEditor,
-                  "Set HTMLEditor or its sub class");
-  return EditorEventListener::Connect(aEditorBase);
-}
-#endif
-
-HTMLEditor*
-HTMLEditorEventListener::GetHTMLEditor()
-{
-  // mEditor must be HTMLEditor or its subclass.
-  return static_cast<HTMLEditor*>(mEditorBase);
+  if (NS_WARN_IF(!aEditorBase)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+  // Guarantee that mEditorBase is always HTMLEditor.
+  HTMLEditor* htmlEditor = aEditorBase->AsHTMLEditor();
+  if (NS_WARN_IF(!htmlEditor)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+  return EditorEventListener::Connect(htmlEditor);
 }
 
 nsresult
 HTMLEditorEventListener::MouseUp(nsIDOMMouseEvent* aMouseEvent)
 {
   if (DetachedFromEditor()) {
     return NS_OK;
   }
 
   // FYI: We need to notify HTML editor of mouseup even if it's consumed
   //      because HTML editor always needs to release grabbing resizer.
-  HTMLEditor* htmlEditor = GetHTMLEditor();
+  HTMLEditor* htmlEditor = mEditorBase->AsHTMLEditor();
+  MOZ_ASSERT(htmlEditor);
 
   nsCOMPtr<nsIDOMEventTarget> target;
   nsresult rv = aMouseEvent->AsEvent()->GetTarget(getter_AddRefs(target));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER);
   nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
 
   int32_t clientX, clientY;
@@ -88,17 +83,19 @@ HTMLEditorEventListener::MouseDown(nsIDO
   // point.  Then, we won't be able to commit the composition.
   if (!EnsureCommitCompoisition()) {
     return NS_OK;
   }
 
   WidgetMouseEvent* mousedownEvent =
     aMouseEvent->AsEvent()->WidgetEventPtr()->AsMouseEvent();
 
-  HTMLEditor* htmlEditor = GetHTMLEditor();
+  HTMLEditor* htmlEditor = mEditorBase->AsHTMLEditor();
+  MOZ_ASSERT(htmlEditor);
+
   // Contenteditable should disregard mousedowns outside it.
   // IsAcceptableInputEvent() checks it for a mouse event.
   if (!htmlEditor->IsAcceptableInputEvent(mousedownEvent)) {
     return EditorEventListener::MouseDown(aMouseEvent);
   }
 
   // Detect only "context menu" click
   // XXX This should be easier to do!
@@ -217,20 +214,26 @@ HTMLEditorEventListener::MouseDown(nsIDO
   }
 
   return EditorEventListener::MouseDown(aMouseEvent);
 }
 
 nsresult
 HTMLEditorEventListener::MouseClick(nsIDOMMouseEvent* aMouseEvent)
 {
+  if (NS_WARN_IF(DetachedFromEditor())) {
+    return NS_OK;
+  }
+
   nsCOMPtr<nsIDOMEventTarget> target;
   nsresult rv = aMouseEvent->AsEvent()->GetTarget(getter_AddRefs(target));
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER);
   nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
 
-  GetHTMLEditor()->DoInlineTableEditingAction(element);
+  HTMLEditor* htmlEditor = mEditorBase->AsHTMLEditor();
+  MOZ_ASSERT(htmlEditor);
+  htmlEditor->DoInlineTableEditingAction(element);
 
   return EditorEventListener::MouseClick(aMouseEvent);
 }
 
 } // namespace mozilla
--- a/editor/libeditor/HTMLEditorEventListener.h
+++ b/editor/libeditor/HTMLEditorEventListener.h
@@ -20,24 +20,22 @@ public:
   HTMLEditorEventListener()
   {
   }
 
   virtual ~HTMLEditorEventListener()
   {
   }
 
-#ifdef DEBUG
-  // WARNING: You must be use HTMLEditor or its sub class for this class.
+  /**
+   * Connect() fails if aEditorBase isn't an HTMLEditor instance.
+   */
   virtual nsresult Connect(EditorBase* aEditorBase) override;
-#endif
 
 protected:
   virtual nsresult MouseDown(nsIDOMMouseEvent* aMouseEvent) override;
   virtual nsresult MouseUp(nsIDOMMouseEvent* aMouseEvent) override;
   virtual nsresult MouseClick(nsIDOMMouseEvent* aMouseEvent) override;
-
-  inline HTMLEditor* GetHTMLEditor();
 };
 
 } // namespace mozilla
 
 #endif // #ifndef HTMLEditorEventListener_h
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -5,16 +5,17 @@
 
 #include "mozilla/TextEditor.h"
 
 #include "InternetCiter.h"
 #include "TextEditUtils.h"
 #include "gfxFontUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/EditorUtils.h" // AutoEditBatch, AutoRules
+#include "mozilla/HTMLEditor.h"
 #include "mozilla/mozalloc.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/TextEditRules.h"
 #include "mozilla/TextComposition.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/dom/Selection.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/Element.h"
@@ -73,16 +74,28 @@ TextEditor::TextEditor()
   , mCaretStyle(0)
 #endif
 {
   // check the "single line editor newline handling"
   // and "caret behaviour in selection" prefs
   GetDefaultEditorPrefs(mNewlineHandling, mCaretStyle);
 }
 
+HTMLEditor*
+TextEditor::AsHTMLEditor()
+{
+  return nullptr;
+}
+
+const HTMLEditor*
+TextEditor::AsHTMLEditor() const
+{
+  return nullptr;
+}
+
 TextEditor::~TextEditor()
 {
   // Remove event listeners. Note that if we had an HTML editor,
   //  it installed its own instead of these
   RemoveEventListeners();
 
   if (mRules)
     mRules->DetachEditor();
--- a/editor/libeditor/TextEditor.h
+++ b/editor/libeditor/TextEditor.h
@@ -53,16 +53,18 @@ public:
     eTypedBR,    /* user typed shift-enter to get a br */
     eTypedBreak  /* user typed enter */
   };
 
   TextEditor();
 
   virtual TextEditor* AsTextEditor() override { return this; }
   virtual const TextEditor* AsTextEditor() const override { return this; }
+  virtual HTMLEditor* AsHTMLEditor() override;
+  virtual const HTMLEditor* AsHTMLEditor() const override;
 
   // nsIPlaintextEditor methods
   NS_DECL_NSIPLAINTEXTEDITOR
 
   // nsIEditorMailSupport overrides
   NS_DECL_NSIEDITORMAILSUPPORT
 
   // Overrides of EditorBase