Bug 1463327 - part 3: Change scope of some methods of HTMLEditor which won't be called by non-helper classes of editing to protected r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 22 May 2018 18:28:50 +0900
changeset 799310 9c29466fcf3168465c53eac2ea89e45a3af6ad87
parent 799309 337b122bd4224adf7c0015334785959de58c7e5c
child 799311 7bac98f1978f499f6be6e1bf8f8ebbbe12c8941c
push id111000
push usermasayuki@d-toybox.com
push dateThu, 24 May 2018 12:43:37 +0000
reviewersm_kato
bugs1463327
milestone62.0a1
Bug 1463327 - part 3: Change scope of some methods of HTMLEditor which won't be called by non-helper classes of editing to protected r?m_kato HTMLEditor has 2 type of public methods. One is rue-public methods. I.e., they should be able to be called by anybody. E.g., command handlers, event listeners, or JS via nsIEditor interface. The other is semi-public methods. They are not called by the above examples but called by other classes which are helper classes to handle edit actions. E.g., TextEditRules, HTMLEditRules, HTMLEditUtils, CSSEditUtils and Transaction classes. When we will implement InputEvent.inputType, we need to create new stack class and create its instance at every true-public methods to manage current inputType (like TextEditRules::AutoSafeEditorData). Therefore, it should not happen that new code starts to call semi-public methods without the new stack class instance. For preventing this issue, we should make HTMLEditor have only the true-public methods as public. The other public methods should be protected and their users should be friend classes. Then, we can protect such method from external classes. Note that this patch just moves the methods without any changes in HTMLEditor.h (except removes BlockTransformationType since it's unused and replaces ResizingRequestID with new enum class ResizeAt since normal enum isn't hit by searchfox.org). MozReview-Commit-ID: 7PC8E8vD7w2
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditRules.h
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditor.h
editor/libeditor/HTMLEditorObjectResizer.cpp
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -78,26 +78,16 @@ enum
   kNextSib = 2,
   kBothSibs = 3
 };
 
 /********************************************************
  *  first some helpful functors we will use
  ********************************************************/
 
-static bool IsBlockNode(const nsINode& node)
-{
-  return HTMLEditor::NodeIsBlockStatic(&node);
-}
-
-static bool IsInlineNode(const nsINode& node)
-{
-  return !IsBlockNode(node);
-}
-
 static bool
 IsStyleCachePreservingAction(EditAction action)
 {
   return action == EditAction::deleteSelection ||
          action == EditAction::insertBreak ||
          action == EditAction::makeList ||
          action == EditAction::indent ||
          action == EditAction::outdent ||
--- a/editor/libeditor/HTMLEditRules.h
+++ b/editor/libeditor/HTMLEditRules.h
@@ -151,16 +151,25 @@ protected:
   virtual ~HTMLEditRules();
 
   HTMLEditor& HTMLEditorRef() const
   {
     MOZ_ASSERT(mData);
     return mData->HTMLEditorRef();
   }
 
+  static bool IsBlockNode(const nsINode& aNode)
+  {
+    return HTMLEditor::NodeIsBlockStatic(&aNode);
+  }
+  static bool IsInlineNode(const nsINode& aNode)
+  {
+    return !IsBlockNode(aNode);
+  }
+
   enum RulesEndpoint
   {
     kStart,
     kEnd
   };
 
   void InitFields();
 
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -70,16 +70,18 @@
 #include "mozilla/StyleSheet.h"
 #include "mozilla/StyleSheetInlines.h"
 
 namespace mozilla {
 
 using namespace dom;
 using namespace widget;
 
+const char16_t kNBSP = 160;
+
 // Some utilities to handle overloading of "A" tag for link and named anchor.
 static bool
 IsLinkTag(const nsString& s)
 {
   return s.EqualsIgnoreCase("href");
 }
 
 static bool
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -38,19 +38,18 @@ class nsHTMLDocument;
 class nsITransferable;
 class nsIClipboard;
 class nsILinkHandler;
 class nsTableWrapperFrame;
 class nsRange;
 
 namespace mozilla {
 class AutoSelectionSetterAfterTableEdit;
-class HTMLEditorEventListener;
+class EmptyEditableFunctor;
 class ResizerSelectionListener;
-class TypeInState;
 enum class EditAction : int32_t;
 struct PropItem;
 template<class T> class OwningNonNull;
 namespace dom {
 class DocumentFragment;
 class Event;
 class MouseEvent;
 } // namespace dom
@@ -69,75 +68,20 @@ class HTMLEditor final : public TextEdit
                        , public nsIHTMLObjectResizer
                        , public nsIHTMLAbsPosEditor
                        , public nsITableEditor
                        , public nsIHTMLInlineTableEditor
                        , public nsIEditorStyleSheets
                        , public nsICSSLoaderObserver
                        , public nsStubMutationObserver
 {
-private:
-  enum BlockTransformationType
-  {
-    eNoOp,
-    eReplaceParent = 1,
-    eInsertParent = 2
-  };
-
-  const char16_t kNBSP = 160;
-
 public:
-  enum ResizingRequestID
-  {
-    kX      = 0,
-    kY      = 1,
-    kWidth  = 2,
-    kHeight = 3
-  };
-
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLEditor, TextEditor)
 
-  HTMLEditor();
-
-  bool GetReturnInParagraphCreatesNewParagraph();
-  Element* GetSelectionContainer();
-
-  // nsISelectionListener overrides
-  NS_DECL_NSISELECTIONLISTENER
-
-  // TextEditor overrides
-  virtual nsresult Init(nsIDocument& aDoc, Element* aRoot,
-                        nsISelectionController* aSelCon, uint32_t aFlags,
-                        const nsAString& aValue) override;
-  NS_IMETHOD BeginningOfDocument() override;
-  virtual nsresult HandleKeyPressEvent(
-                     WidgetKeyboardEvent* aKeyboardEvent) override;
-  virtual nsIContent* GetFocusedContent() override;
-  virtual already_AddRefed<nsIContent> GetFocusedContentForIME() override;
-  virtual bool IsActiveInDOMWindow() override;
-  virtual dom::EventTarget* GetDOMEventTarget() override;
-  virtual Element* GetEditorRoot() override;
-  virtual already_AddRefed<nsIContent> FindSelectionRoot(
-                                         nsINode *aNode) override;
-  virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent) override;
-  virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
-  using EditorBase::IsEditable;
-  virtual nsresult RemoveAttributeOrEquivalent(
-                     Element* aElement,
-                     nsAtom* aAttribute,
-                     bool aSuppressTransaction) override;
-  virtual nsresult SetAttributeOrEquivalent(Element* aElement,
-                                            nsAtom* aAttribute,
-                                            const nsAString& aValue,
-                                            bool aSuppressTransaction) override;
-  using EditorBase::RemoveAttributeOrEquivalent;
-  using EditorBase::SetAttributeOrEquivalent;
-  virtual bool CanPasteTransferable(nsITransferable* aTransferable) override;
-
   // nsStubMutationObserver overrides
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
   // nsIHTMLEditor methods
   NS_DECL_NSIHTMLEDITOR
 
@@ -145,85 +89,109 @@ public:
   NS_DECL_NSIHTMLOBJECTRESIZER
 
   // nsIHTMLAbsPosEditor methods (implemented in HTMLAbsPositionEditor.cpp)
   NS_DECL_NSIHTMLABSPOSEDITOR
 
   // nsIHTMLInlineTableEditor methods (implemented in HTMLInlineTableEditor.cpp)
   NS_DECL_NSIHTMLINLINETABLEEDITOR
 
-  // XXX Following methods are not overriding but defined here...
-  nsresult LoadHTML(const nsAString& aInputString);
-
-  nsresult GetCSSBackgroundColorState(bool* aMixed, nsAString& aOutColor,
-                                      bool aBlockLevel);
-  nsresult GetHTMLBackgroundColorState(bool* aMixed, nsAString& outColor);
-
   // nsIEditorStyleSheets methods
   NS_DECL_NSIEDITORSTYLESHEETS
 
   // nsIEditorMailSupport methods
   NS_DECL_NSIEDITORMAILSUPPORT
 
   // nsITableEditor methods
   NS_DECL_NSITABLEEDITOR
 
-  nsresult GetLastCellInRow(nsINode* aRowNode,
-                            nsINode** aCellNode);
-
-  nsresult GetCellFromRange(nsRange* aRange, Element** aCell);
-
-  // Miscellaneous
-
-  /**
-   * This sets background on the appropriate container element (table, cell,)
-   * or calls into nsTextEditor to set the page background.
-   */
-  nsresult SetCSSBackgroundColorWithTransaction(const nsAString& aColor);
-  nsresult SetHTMLBackgroundColorWithTransaction(const nsAString& aColor);
+  // nsISelectionListener overrides
+  NS_DECL_NSISELECTIONLISTENER
 
-  /**
-   * GetBlockNodeParent() returns parent or nearest ancestor of aNode if
-   * there is a block parent.  If aAncestorLimiter is not nullptr,
-   * this stops looking for the result.
-   */
-  static Element* GetBlockNodeParent(nsINode* aNode,
-                                     nsINode* aAncestorLimiter = nullptr);
-  /**
-   * GetBlock() returns aNode itself, or parent or nearest ancestor of aNode
-   * if there is a block parent.  If aAncestorLimiter is not nullptr,
-   * this stops looking for the result.
-   */
-  static Element* GetBlock(nsINode& aNode,
-                           nsINode* aAncestorLimiter = nullptr);
+  // nsICSSLoaderObserver
+  NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet,
+                              bool aWasAlternate, nsresult aStatus) override;
 
-  void IsNextCharInNodeWhitespace(nsIContent* aContent,
-                                  int32_t aOffset,
-                                  bool* outIsSpace,
-                                  bool* outIsNBSP,
-                                  nsIContent** outNode = nullptr,
-                                  int32_t* outOffset = 0);
-  void IsPrevCharInNodeWhitespace(nsIContent* aContent,
-                                  int32_t aOffset,
-                                  bool* outIsSpace,
-                                  bool* outIsNBSP,
-                                  nsIContent** outNode = nullptr,
-                                  int32_t* outOffset = 0);
+  HTMLEditor();
 
-  // Overrides of EditorBase interface methods
-  virtual nsresult EndUpdateViewBatch() override;
+  nsHTMLDocument* GetHTMLDocument() const;
 
   virtual void PreDestroy(bool aDestroyingFrames) override;
 
+  bool GetReturnInParagraphCreatesNewParagraph();
+  Element* GetSelectionContainer();
+
+  // TextEditor overrides
+  virtual nsresult Init(nsIDocument& aDoc, Element* aRoot,
+                        nsISelectionController* aSelCon, uint32_t aFlags,
+                        const nsAString& aValue) override;
+  NS_IMETHOD BeginningOfDocument() override;
+  NS_IMETHOD SetFlags(uint32_t aFlags) override;
+
+  NS_IMETHOD Paste(int32_t aSelectionType) override;
+  NS_IMETHOD CanPaste(int32_t aSelectionType, bool* aCanPaste) override;
+
+  NS_IMETHOD PasteTransferable(nsITransferable* aTransferable) override;
+
+  NS_IMETHOD DeleteNode(nsIDOMNode* aNode) override;
+
+  NS_IMETHOD SelectAll() override;
+
+  NS_IMETHOD DebugUnitTests(int32_t* outNumTests,
+                            int32_t* outNumTestsFailed) override;
+
+  virtual nsresult HandleKeyPressEvent(
+                     WidgetKeyboardEvent* aKeyboardEvent) override;
+  virtual nsIContent* GetFocusedContent() override;
+  virtual already_AddRefed<nsIContent> GetFocusedContentForIME() override;
+  virtual bool IsActiveInDOMWindow() override;
+  virtual dom::EventTarget* GetDOMEventTarget() override;
+  virtual already_AddRefed<nsIContent> FindSelectionRoot(
+                                         nsINode *aNode) override;
+  virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent) override;
+  virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
   virtual nsresult GetPreferredIMEState(widget::IMEState* aState) override;
 
   /**
-   * @param aElement        Must not be null.
+   * Can we paste |aTransferable| or, if |aTransferable| is null, will a call
+   * to pasteTransferable later possibly succeed if given an instance of
+   * nsITransferable then? True if the doc is modifiable, and, if
+   * |aTransfeable| is non-null, we have pasteable data in |aTransfeable|.
+   */
+  virtual bool CanPasteTransferable(nsITransferable* aTransferable) override;
+
+  /**
+   * OnInputLineBreak() is called when user inputs a line break with
+   * Shift + Enter or something.
    */
-  static bool NodeIsBlockStatic(const nsINode* aElement);
+  nsresult OnInputLineBreak();
+
+  /**
+   * event callback when a mouse button is pressed
+   * @param aX      [IN] horizontal position of the pointer
+   * @param aY      [IN] vertical position of the pointer
+   * @param aTarget [IN] the element triggering the event
+   * @param aMouseEvent [IN] the event
+   */
+  nsresult OnMouseDown(int32_t aX, int32_t aY, Element* aTarget,
+                       dom::Event* aMouseEvent);
+
+  /**
+   * event callback when a mouse button is released
+   * @param aX      [IN] horizontal position of the pointer
+   * @param aY      [IN] vertical position of the pointer
+   * @param aTarget [IN] the element triggering the event
+   */
+  nsresult OnMouseUp(int32_t aX, int32_t aY, Element* aTarget);
+
+  /**
+   * event callback when the mouse pointer is moved
+   * @param aMouseEvent [IN] the event
+   */
+  nsresult OnMouseMove(dom::MouseEvent* aMouseEvent);
 
   // non-virtual methods of interface methods
   bool AbsolutePositioningEnabled() const
   {
     return mIsAbsolutelyPositioningEnabled;
   }
 
   /**
@@ -241,48 +209,28 @@ public:
    * extracts the selection from the normal flow of the document and
    * positions it.
    * @param aEnabled [IN] true to absolutely position the selection,
    *                      false to put it back in the normal flow
    */
   nsresult SetSelectionToAbsoluteOrStatic(bool aEnabled);
 
   /**
-   * extracts an element from the normal flow of the document and
-   * positions it, and puts it back in the normal flow.
-   * @param aElement [IN] the element
-   * @param aEnabled [IN] true to absolutely position the element,
-   *                      false to put it back in the normal flow
-   */
-  nsresult SetPositionToAbsoluteOrStatic(Element& aElement,
-                                         bool aEnabled);
-
-  /**
    * returns the absolute z-index of a positioned element. Never returns 'auto'
    * @return         the z-index of the element
    * @param aElement [IN] the element.
    */
   int32_t GetZIndex(Element& aElement);
 
   /**
    * adds aChange to the z-index of the currently positioned element.
    * @param aChange [IN] relative change to apply to current z-index
    */
   nsresult AddZIndex(int32_t aChange);
 
-  /**
-   * adds aChange to the z-index of an arbitrary element.
-   * @param aElement [IN] the element
-   * @param aChange  [IN] relative change to apply to current z-index of
-   *                      the element
-   * @param aReturn  [OUT] the new z-index of the element
-   */
-  nsresult RelativeChangeElementZIndex(Element& aElement, int32_t aChange,
-                                       int32_t* aReturn);
-
   nsresult SetInlineProperty(nsAtom* aProperty,
                              nsAtom* aAttribute,
                              const nsAString& aValue);
   nsresult GetInlineProperty(nsAtom* aProperty,
                              nsAtom* aAttribute,
                              const nsAString& aValue,
                              bool* aFirst,
                              bool* aAny,
@@ -305,75 +253,36 @@ public:
   void SetComposerCommandsUpdater(
          ComposerCommandsUpdater* aComposerCommandsUpdater)
   {
     MOZ_ASSERT(!aComposerCommandsUpdater || !mComposerCommandsUpdater ||
                aComposerCommandsUpdater == mComposerCommandsUpdater);
     mComposerCommandsUpdater = aComposerCommandsUpdater;
   }
 
-protected:
-  virtual ~HTMLEditor();
-
-  using EditorBase::IsBlockNode;
-  virtual bool IsBlockNode(nsINode *aNode) override;
-
-  virtual void
-  InitializeSelectionAncestorLimit(Selection& aSelection,
-                                   nsIContent& aAncestorLimit) override;
-
-public:
-  // XXX Why don't we move following methods above for grouping by the origins?
-  NS_IMETHOD SetFlags(uint32_t aFlags) override;
-
-  NS_IMETHOD Paste(int32_t aSelectionType) override;
-  NS_IMETHOD CanPaste(int32_t aSelectionType, bool* aCanPaste) override;
-
-  NS_IMETHOD PasteTransferable(nsITransferable* aTransferable) override;
-
-  NS_IMETHOD DebugUnitTests(int32_t* outNumTests,
-                            int32_t* outNumTestsFailed) override;
-
-  /**
-   * All editor operations which alter the doc should be prefaced
-   * with a call to StartOperation, naming the action and direction.
-   */
-  virtual nsresult StartOperation(EditAction opID,
-                                  nsIEditor::EDirection aDirection) override;
+  ParagraphSeparator GetDefaultParagraphSeparator() const
+  {
+    return mDefaultParagraphSeparator;
+  }
+  void SetDefaultParagraphSeparator(ParagraphSeparator aSep)
+  {
+    mDefaultParagraphSeparator = aSep;
+  }
 
   /**
-   * All editor operations which alter the doc should be followed
-   * with a call to EndOperation.
-   */
-  virtual nsresult EndOperation() override;
-
-  /**
-   * returns true if aParentTag can contain a child of type aChildTag.
-   */
-  virtual bool TagCanContainTag(nsAtom& aParentTag,
-                                nsAtom& aChildTag) const override;
-
-  /**
-   * Returns true if aNode is a container.
+   * Modifies the table containing the selection according to the
+   * activation of an inline table editing UI element
+   * @param aUIAnonymousElement [IN] the inline table editing UI element
    */
-  virtual bool IsContainer(nsINode* aNode) override;
-
-  /**
-   * Make the given selection span the entire document.
-   */
-  virtual nsresult SelectEntireDocument(Selection* aSelection) override;
+  nsresult DoInlineTableEditingAction(const Element& aUIAnonymousElement);
 
-  /**
-   * Join together any adjacent editable text nodes in the range.
-   */
-  nsresult CollapseAdjacentTextNodes(nsRange* aRange);
+  already_AddRefed<Element>
+  GetElementOrParentByTagName(const nsAString& aTagName, nsINode* aNode);
 
-  virtual bool AreNodesSameType(nsIContent* aNode1,
-                                nsIContent* aNode2) override;
-
+protected: // May be called by friends.
   /**
    * DeleteSelectionWithTransaction() removes selected content or content
    * around caret with transactions.
    *
    * @param aDirection          How much range should be removed.
    * @param aStripWrappers      Whether the parent blocks should be removed
    *                            when they become empty.
    */
@@ -385,18 +294,16 @@ public:
    * DeleteNodeWithTransaction() removes aNode from the DOM tree if it's
    * modifiable.  Note that this is not an override of same method of
    * EditorBase.
    *
    * @param aNode       The node to be removed from the DOM tree.
    */
   nsresult DeleteNodeWithTransaction(nsINode& aNode);
 
-  NS_IMETHOD DeleteNode(nsIDOMNode* aNode) override;
-
   /**
    * DeleteTextWithTransaction() removes text in the range from aCharData if
    * it's modifiable.  Note that this not an override of same method of
    * EditorBase.
    *
    * @param aCharData           The data node which should be modified.
    * @param aOffset             Start offset of removing text in aCharData.
    * @param aLength             Length of removing text.
@@ -409,54 +316,16 @@ public:
    */
   virtual nsresult
   InsertTextWithTransaction(nsIDocument& aDocument,
                             const nsAString& aStringToInsert,
                             const EditorRawDOMPoint& aPointToInsert,
                             EditorRawDOMPoint* aPointAfterInsertedString =
                               nullptr) override;
 
-  virtual bool IsModifiableNode(nsINode* aNode) override;
-
-  NS_IMETHOD SelectAll() override;
-
-  // nsICSSLoaderObserver
-  NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet,
-                              bool aWasAlternate, nsresult aStatus) override;
-
-  /**
-   * OnInputLineBreak() is called when user inputs a line break with
-   * Shift + Enter or something.
-   */
-  nsresult OnInputLineBreak();
-
-  /**
-   * InsertNodeIntoProperAncestorWithTransaction() attempts to insert aNode
-   * into the document, at aPointToInsert.  Checks with strict dtd to see if
-   * containment is allowed.  If not allowed, will attempt to find a parent
-   * in the parent hierarchy of aPointToInsert.GetContainer() that will accept
-   * aNode as a child.  If such a parent is found, will split the document
-   * tree from aPointToInsert up to parent, and then insert aNode.
-   * aPointToInsert is then adjusted to point to the actual location that
-   * aNode was inserted at.  aSplitAtEdges specifies if the splitting process
-   * is allowed to result in empty nodes.
-   *
-   * @param aNode             Node to insert.
-   * @param aPointToInsert    Insertion point.
-   * @param aSplitAtEdges     Splitting can result in empty nodes?
-   * @return                  Returns inserted point if succeeded.
-   *                          Otherwise, the result is not set.
-   */
-  template<typename PT, typename CT>
-  EditorDOMPoint
-  InsertNodeIntoProperAncestorWithTransaction(
-    nsIContent& aNode,
-    const EditorDOMPointBase<PT, CT>& aPointToInsert,
-    SplitAtEdges aSplitAtEdges);
-
   /**
    * CopyLastEditableChildStyles() clones inline container elements into
    * aPreviousBlock to aNewBlock to keep using same style in it.
    *
    * @param aPreviousBlock      The previous block element.  All inline
    *                            elements which are last sibling of each level
    *                            are cloned to aNewBlock.
    * @param aNewBlock           New block container element.
@@ -465,25 +334,115 @@ public:
    *                            element.
    */
   nsresult
   CopyLastEditableChildStylesWithTransaction(Element& aPreviousBlock,
                                              Element& aNewBlock,
                                              RefPtr<Element>* aNewBrElement);
 
   /**
-   * Use this to assure that selection is set after attribute nodes when
-   * trying to collapse selection at begining of a block node
-   * e.g., when setting at beginning of a table cell
-   * This will stop at a table, however, since we don't want to
-   * "drill down" into nested tables.
-   * @param aSelection      Optional. If null, we get current selection.
+   * RemoveBlockContainerWithTransaction() removes aElement from the DOM tree
+   * but moves its all children to its parent node and if its parent needs <br>
+   * element to have at least one line-height, this inserts <br> element
+   * automatically.
+   *
+   * @param aElement            Block element to be removed.
+   */
+  nsresult RemoveBlockContainerWithTransaction(Element& aElement);
+
+  virtual Element* GetEditorRoot() override;
+  using EditorBase::IsEditable;
+  virtual nsresult RemoveAttributeOrEquivalent(
+                     Element* aElement,
+                     nsAtom* aAttribute,
+                     bool aSuppressTransaction) override;
+  virtual nsresult SetAttributeOrEquivalent(Element* aElement,
+                                            nsAtom* aAttribute,
+                                            const nsAString& aValue,
+                                            bool aSuppressTransaction) override;
+  using EditorBase::RemoveAttributeOrEquivalent;
+  using EditorBase::SetAttributeOrEquivalent;
+
+  /**
+   * GetBlockNodeParent() returns parent or nearest ancestor of aNode if
+   * there is a block parent.  If aAncestorLimiter is not nullptr,
+   * this stops looking for the result.
+   */
+  static Element* GetBlockNodeParent(nsINode* aNode,
+                                     nsINode* aAncestorLimiter = nullptr);
+
+  /**
+   * GetBlock() returns aNode itself, or parent or nearest ancestor of aNode
+   * if there is a block parent.  If aAncestorLimiter is not nullptr,
+   * this stops looking for the result.
    */
-  void CollapseSelectionToDeepestNonTableFirstChild(Selection* aSelection,
-                                                    nsINode* aNode);
+  static Element* GetBlock(nsINode& aNode,
+                           nsINode* aAncestorLimiter = nullptr);
+
+  void IsNextCharInNodeWhitespace(nsIContent* aContent,
+                                  int32_t aOffset,
+                                  bool* outIsSpace,
+                                  bool* outIsNBSP,
+                                  nsIContent** outNode = nullptr,
+                                  int32_t* outOffset = 0);
+  void IsPrevCharInNodeWhitespace(nsIContent* aContent,
+                                  int32_t aOffset,
+                                  bool* outIsSpace,
+                                  bool* outIsNBSP,
+                                  nsIContent** outNode = nullptr,
+                                  int32_t* outOffset = 0);
+
+  /**
+   * @param aElement        Must not be null.
+   */
+  static bool NodeIsBlockStatic(const nsINode* aElement);
+
+  /**
+   * extracts an element from the normal flow of the document and
+   * positions it, and puts it back in the normal flow.
+   * @param aElement [IN] the element
+   * @param aEnabled [IN] true to absolutely position the element,
+   *                      false to put it back in the normal flow
+   */
+  nsresult SetPositionToAbsoluteOrStatic(Element& aElement,
+                                         bool aEnabled);
+
+  /**
+   * adds aChange to the z-index of an arbitrary element.
+   * @param aElement [IN] the element
+   * @param aChange  [IN] relative change to apply to current z-index of
+   *                      the element
+   * @param aReturn  [OUT] the new z-index of the element
+   */
+  nsresult RelativeChangeElementZIndex(Element& aElement, int32_t aChange,
+                                       int32_t* aReturn);
+
+  virtual bool IsBlockNode(nsINode *aNode) override;
+  using EditorBase::IsBlockNode;
+
+  virtual bool IsModifiableNode(nsINode* aNode) override;
+
+  /**
+   * returns true if aParentTag can contain a child of type aChildTag.
+   */
+  virtual bool TagCanContainTag(nsAtom& aParentTag,
+                                nsAtom& aChildTag) const override;
+
+  /**
+   * Returns true if aNode is a container.
+   */
+  virtual bool IsContainer(nsINode* aNode) override;
+
+  /**
+   * Join together any adjacent editable text nodes in the range.
+   */
+  nsresult CollapseAdjacentTextNodes(nsRange* aRange);
+
+  virtual bool AreNodesSameType(nsIContent* aNode1,
+                                nsIContent* aNode2) override;
 
   /**
    * IsInVisibleTextFrames() returns true if all text in aText is in visible
    * text frames.  Callers have to guarantee that there is no pending reflow.
    */
   bool IsInVisibleTextFrames(dom::Text& aText);
 
   /**
@@ -502,276 +461,31 @@ public:
                        bool aSafeToAskFrames = false);
   nsresult IsEmptyNodeImpl(nsINode* aNode,
                            bool* outIsEmptyBlock,
                            bool aMozBRDoesntCount,
                            bool aListOrCellNotEmpty,
                            bool aSafeToAskFrames,
                            bool* aSeenBR);
 
-  /**
-   * Returns TRUE if sheet was loaded, false if it wasn't.
-   */
-  bool EnableExistingStyleSheet(const nsAString& aURL);
-
-  /**
-   * Dealing with the internal style sheet lists.
-   */
-  StyleSheet* GetStyleSheetForURL(const nsAString& aURL);
-  void GetURLForStyleSheet(StyleSheet* aStyleSheet,
-                           nsAString& aURL);
-
-  /**
-   * Add a url + known style sheet to the internal lists.
-   */
-  nsresult AddNewStyleSheetToList(const nsAString &aURL,
-                                  StyleSheet* aStyleSheet);
-  nsresult RemoveStyleSheetFromList(const nsAString &aURL);
-
   bool IsCSSEnabled() const
   {
     // TODO: removal of mCSSAware and use only the presence of mCSSEditUtils
     return mCSSAware && mCSSEditUtils && mCSSEditUtils->IsCSSPrefChecked();
   }
 
   static bool HasAttributes(Element* aElement)
   {
     MOZ_ASSERT(aElement);
     uint32_t attrCount = aElement->GetAttrCount();
     return attrCount > 1 ||
            (1 == attrCount &&
             !aElement->GetAttrNameAt(0)->Equals(nsGkAtoms::mozdirty));
   }
 
-  ParagraphSeparator GetDefaultParagraphSeparator() const
-  {
-    return mDefaultParagraphSeparator;
-  }
-  void SetDefaultParagraphSeparator(ParagraphSeparator aSep)
-  {
-    mDefaultParagraphSeparator = aSep;
-  }
-
-  /**
-   * event callback when a mouse button is pressed
-   * @param aX      [IN] horizontal position of the pointer
-   * @param aY      [IN] vertical position of the pointer
-   * @param aTarget [IN] the element triggering the event
-   * @param aMouseEvent [IN] the event
-   */
-  nsresult OnMouseDown(int32_t aX, int32_t aY, Element* aTarget,
-                       dom::Event* aMouseEvent);
-
-  /**
-   * event callback when a mouse button is released
-   * @param aX      [IN] horizontal position of the pointer
-   * @param aY      [IN] vertical position of the pointer
-   * @param aTarget [IN] the element triggering the event
-   */
-  nsresult OnMouseUp(int32_t aX, int32_t aY, Element* aTarget);
-
-  /**
-   * event callback when the mouse pointer is moved
-   * @param aMouseEvent [IN] the event
-   */
-  nsresult OnMouseMove(dom::MouseEvent* aMouseEvent);
-
-  /**
-   * Modifies the table containing the selection according to the
-   * activation of an inline table editing UI element
-   * @param aUIAnonymousElement [IN] the inline table editing UI element
-   */
-  nsresult DoInlineTableEditingAction(const Element& aUIAnonymousElement);
-
-  /**
-   * MaybeCollapseSelectionAtFirstEditableNode() may collapse selection at
-   * proper position to staring to edit.  If there is a non-editable node
-   * before any editable text nodes or inline elements which can have text
-   * nodes as their children, collapse selection at start of the editing
-   * host.  If there is an editable text node which is not collapsed, collapses
-   * selection at the start of the text node.  If there is an editable inline
-   * element which cannot have text nodes as its child, collapses selection at
-   * before the element node.  Otherwise, collapses selection at start of the
-   * editing host.
-   *
-   * @param aIgnoreIfSelectionInEditingHost
-   *                        This method does nothing if selection is in the
-   *                        editing host except if it's collapsed at start of
-   *                        the editing host.
-   *                        Note that if selection ranges were outside of
-   *                        current selection limiter, selection was collapsed
-   *                        at the start of the editing host therefore, if
-   *                        you call this with setting this to true, you can
-   *                        keep selection ranges if user has already been
-   *                        changed.
-   */
-  nsresult
-  MaybeCollapseSelectionAtFirstEditableNode(
-    bool aIgnoreIfSelectionInEditingHost);
-
-  nsHTMLDocument* GetHTMLDocument() const;
-
-protected:
-  class BlobReader final : public nsIEditorBlobListener
-  {
-  public:
-    BlobReader(dom::BlobImpl* aBlob, HTMLEditor* aHTMLEditor,
-               bool aIsSafe, nsIDocument* aSourceDoc,
-               nsINode* aDestinationNode, int32_t aDestOffset,
-               bool aDoDeleteSelection);
-
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSIEDITORBLOBLISTENER
-
-  private:
-    ~BlobReader()
-    {
-    }
-
-    RefPtr<dom::BlobImpl> mBlob;
-    RefPtr<HTMLEditor> mHTMLEditor;
-    bool mIsSafe;
-    nsCOMPtr<nsIDocument> mSourceDoc;
-    nsCOMPtr<nsINode> mDestinationNode;
-    int32_t mDestOffset;
-    bool mDoDeleteSelection;
-  };
-
-  virtual nsresult InitRules() override;
-
-  virtual void CreateEventListeners() override;
-  virtual nsresult InstallEventListeners() override;
-  virtual void RemoveEventListeners() override;
-
-  bool ShouldReplaceRootElement();
-  void NotifyRootChanged();
-  Element* GetBodyElement();
-
-  /**
-   * Get the focused node of this editor.
-   * @return    If the editor has focus, this returns the focused node.
-   *            Otherwise, returns null.
-   */
-  already_AddRefed<nsINode> GetFocusedNode();
-
-  /**
-   * Return TRUE if aElement is a table-related elemet and caret was set.
-   */
-  bool SetCaretInTableCell(dom::Element* aElement);
-
-  nsresult TabInTable(bool inIsShift, bool* outHandled);
-
-  /**
-   * InsertBrElementAtSelectionWithTransaction() inserts a new <br> element at
-   * selection.  If there is non-collapsed selection ranges, the selected
-   * ranges is deleted first.
-   */
-  nsresult InsertBrElementAtSelectionWithTransaction();
-
-  // Table Editing (implemented in nsTableEditor.cpp)
-
-  /**
-   * Insert a new cell after or before supplied aCell.
-   * Optional: If aNewCell supplied, returns the newly-created cell (addref'd,
-   * of course)
-   * This doesn't change or use the current selection.
-   */
-  nsresult InsertCell(Element* aCell, int32_t aRowSpan,
-                      int32_t aColSpan, bool aAfter, bool aIsHeader,
-                      Element** aNewCell);
-
-  /**
-   * Helpers that don't touch the selection or do batch transactions.
-   */
-  nsresult DeleteRow(Element* aTable, int32_t aRowIndex);
-  nsresult DeleteColumn(Element* aTable, int32_t aColIndex);
-  nsresult DeleteCellContents(Element* aCell);
-
-  /**
-   * Move all contents from aCellToMerge into aTargetCell (append at end).
-   */
-  nsresult MergeCells(RefPtr<Element> aTargetCell,
-                      RefPtr<Element> aCellToMerge,
-                      bool aDeleteCellToMerge);
-
-  nsresult DeleteTable2(Element* aTable, Selection* aSelection);
-  nsresult SetColSpan(Element* aCell, int32_t aColSpan);
-  nsresult SetRowSpan(Element* aCell, int32_t aRowSpan);
-
-  /**
-   * Helper used to get nsTableWrapperFrame for a table.
-   */
-  nsTableWrapperFrame* GetTableFrame(Element* aTable);
-
-  /**
-   * Needed to do appropriate deleting when last cell or row is about to be
-   * deleted.  This doesn't count cells that don't start in the given row (are
-   * spanning from row above).
-   */
-  int32_t GetNumberOfCellsInRow(Element* aTable, int32_t rowIndex);
-
-  /**
-   * Test if all cells in row or column at given index are selected.
-   */
-  bool AllCellsInRowSelected(Element* aTable, int32_t aRowIndex,
-                             int32_t aNumberOfColumns);
-  bool AllCellsInColumnSelected(Element* aTable, int32_t aColIndex,
-                                int32_t aNumberOfRows);
-
-  bool IsEmptyCell(Element* aCell);
-
-  /**
-   * Most insert methods need to get the same basic context data.
-   * Any of the pointers may be null if you don't need that datum (for more
-   * efficiency).
-   * Input: *aCell is a known cell,
-   *        if null, cell is obtained from the anchor node of the selection.
-   * Returns NS_EDITOR_ELEMENT_NOT_FOUND if cell is not found even if aCell is
-   * null.
-   */
-  nsresult GetCellContext(Selection** aSelection, Element** aTable,
-                          Element** aCell, nsINode** aCellParent,
-                          int32_t* aCellOffset, int32_t* aRowIndex,
-                          int32_t* aColIndex);
-
-  nsresult GetCellSpansAt(Element* aTable, int32_t aRowIndex,
-                          int32_t aColIndex, int32_t& aActualRowSpan,
-                          int32_t& aActualColSpan);
-
-  nsresult SplitCellIntoColumns(Element* aTable, int32_t aRowIndex,
-                                int32_t aColIndex, int32_t aColSpanLeft,
-                                int32_t aColSpanRight,
-                                Element** aNewCell);
-
-  nsresult SplitCellIntoRows(Element* aTable, int32_t aRowIndex,
-                             int32_t aColIndex, int32_t aRowSpanAbove,
-                             int32_t aRowSpanBelow, Element** aNewCell);
-
-  nsresult CopyCellBackgroundColor(Element* aDestCell,
-                                   Element* aSourceCell);
-
-  /**
-   * Reduce rowspan/colspan when cells span into nonexistent rows/columns.
-   */
-  nsresult FixBadRowSpan(Element* aTable, int32_t aRowIndex,
-                         int32_t& aNewRowCount);
-  nsresult FixBadColSpan(Element* aTable, int32_t aColIndex,
-                         int32_t& aNewColCount);
-
-  /**
-   * Fallback method: Call this after using ClearSelection() and you
-   * failed to set selection to some other content in the document.
-   */
-  nsresult SetSelectionAtDocumentStart(Selection* aSelection);
-
-  // End of Table Editing utilities
-
-  static Element* GetEnclosingTable(nsINode* aNode);
-  static nsIDOMNode* GetEnclosingTable(nsIDOMNode* aNode);
-
   /**
    * Content-based query returns true if <aProperty aAttribute=aValue> effects
    * aNode.  If <aProperty aAttribute=aValue> contains aNode, but
    * <aProperty aAttribute=SomeOtherValue> also contains aNode and the second is
    * more deeply nested than the first, then the first does not effect aNode.
    *
    * @param aNode      The target of the query
    * @param aProperty  The property that we are querying for
@@ -787,195 +501,42 @@ protected:
    * The nsIContent variant returns aIsSet instead of using an out parameter.
    */
   bool IsTextPropertySetByContent(nsINode* aNode,
                                   nsAtom* aProperty,
                                   nsAtom* aAttribute,
                                   const nsAString* aValue,
                                   nsAString* outValue = nullptr);
 
-  // Methods for handling plaintext quotations
-  nsresult PasteAsPlaintextQuotation(int32_t aSelectionType);
-
-  /**
-   * Insert a string as quoted text, replacing the selected text (if any).
-   * @param aQuotedText     The string to insert.
-   * @param aAddCites       Whether to prepend extra ">" to each line
-   *                        (usually true, unless those characters
-   *                        have already been added.)
-   * @return aNodeInserted  The node spanning the insertion, if applicable.
-   *                        If aAddCites is false, this will be null.
-   */
-  nsresult InsertAsPlaintextQuotation(const nsAString& aQuotedText,
-                                      bool aAddCites,
-                                      nsIDOMNode** aNodeInserted);
-
-  nsresult InsertObject(const nsACString& aType, nsISupports* aObject,
-                        bool aIsSafe,
-                        nsIDocument* aSourceDoc,
-                        nsINode* aDestinationNode,
-                        int32_t aDestOffset,
-                        bool aDoDeleteSelection);
-
-  // factored methods for handling insertion of data from transferables
-  // (drag&drop or clipboard)
-  virtual nsresult PrepareTransferable(nsITransferable** transferable) override;
-  nsresult PrepareHTMLTransferable(nsITransferable** transferable);
-  nsresult InsertFromTransferable(nsITransferable* transferable,
-                                    nsIDocument* aSourceDoc,
-                                    const nsAString& aContextStr,
-                                    const nsAString& aInfoStr,
-                                    bool havePrivateHTMLFlavor,
-                                    bool aDoDeleteSelection);
-  virtual nsresult InsertFromDataTransfer(dom::DataTransfer* aDataTransfer,
-                                          int32_t aIndex,
-                                          nsIDocument* aSourceDoc,
-                                          nsINode* aDestinationNode,
-                                          int32_t aDestOffset,
-                                          bool aDoDeleteSelection) override;
-  bool HavePrivateHTMLFlavor(nsIClipboard* clipboard );
-  nsresult ParseCFHTML(nsCString& aCfhtml, char16_t** aStuffToPaste,
-                       char16_t** aCfcontext);
-
   bool IsInLink(nsINode* aNode, nsCOMPtr<nsINode>* outLink = nullptr);
-  nsresult StripFormattingNodes(nsIContent& aNode, bool aOnlyList = false);
-  nsresult CreateDOMFragmentFromPaste(const nsAString& aInputString,
-                                      const nsAString& aContextStr,
-                                      const nsAString& aInfoStr,
-                                      nsCOMPtr<nsINode>* outFragNode,
-                                      nsCOMPtr<nsINode>* outStartNode,
-                                      nsCOMPtr<nsINode>* outEndNode,
-                                      int32_t* outStartOffset,
-                                      int32_t* outEndOffset,
-                                      bool aTrustedInput);
-  nsresult ParseFragment(const nsAString& aStr, nsAtom* aContextLocalName,
-                         nsIDocument* aTargetDoc,
-                         dom::DocumentFragment** aFragment, bool aTrustedInput);
-  void CreateListOfNodesToPaste(dom::DocumentFragment& aFragment,
-                                nsTArray<OwningNonNull<nsINode>>& outNodeList,
-                                nsINode* aStartContainer,
-                                int32_t aStartOffset,
-                                nsINode* aEndContainer,
-                                int32_t aEndOffset);
-  nsresult CreateTagStack(nsTArray<nsString>& aTagStack,
-                          nsIDOMNode* aNode);
-  enum class StartOrEnd { start, end };
-  void GetListAndTableParents(StartOrEnd aStartOrEnd,
-                              nsTArray<OwningNonNull<nsINode>>& aNodeList,
-                              nsTArray<OwningNonNull<Element>>& outArray);
-  int32_t DiscoverPartialListsAndTables(
-            nsTArray<OwningNonNull<nsINode>>& aPasteNodes,
-            nsTArray<OwningNonNull<Element>>& aListsAndTables);
-  nsINode* ScanForListAndTableStructure(
-             StartOrEnd aStartOrEnd,
-             nsTArray<OwningNonNull<nsINode>>& aNodes,
-             Element& aListOrTable);
-  void ReplaceOrphanedStructure(
-         StartOrEnd aStartOrEnd,
-         nsTArray<OwningNonNull<nsINode>>& aNodeArray,
-         nsTArray<OwningNonNull<Element>>& aListAndTableArray,
-         int32_t aHighWaterMark);
 
   /**
    * Small utility routine to test if a break node is visible to user.
    */
   bool IsVisibleBRElement(nsINode* aNode);
 
   /**
-   * GetBetterInsertionPointFor() returns better insertion point to insert
-   * aNodeToInsert.
-   *
-   * @param aNodeToInsert       The node to insert.
-   * @param aPointToInsert      A candidate point to insert the node.
-   * @return                    Better insertion point if next visible node
-   *                            is a <br> element and previous visible node
-   *                            is neither none, another <br> element nor
-   *                            different block level element.
-   */
-  EditorRawDOMPoint
-  GetBetterInsertionPointFor(nsINode& aNodeToInsert,
-                             const EditorRawDOMPoint& aPointToInsert);
-
-  /**
-   * MakeDefinitionListItemWithTransaction() replaces parent list of current
-   * selection with <dl> or create new <dl> element and creates a definition
-   * list item whose name is aTagName.
-   *
-   * @param aTagName            Must be nsGkAtoms::dt or nsGkAtoms::dd.
-   */
-  nsresult MakeDefinitionListItemWithTransaction(nsAtom& aTagName);
-
-  /**
-   * InsertBasicBlockWithTransaction() inserts a block element whose name
-   * is aTagName at selection.
-   *
-   * @param aTagName            A block level element name.  Must NOT be
-   *                            nsGkAtoms::dt nor nsGkAtoms::dd.
-   */
-  nsresult InsertBasicBlockWithTransaction(nsAtom& aTagName);
-
-  /**
-   * Increase/decrease the font size of selection.
+   * Helper routines for font size changing.
    */
   enum class FontSize { incr, decr };
-  nsresult RelativeFontChange(FontSize aDir);
-
-  /**
-   * Helper routines for font size changing.
-   */
   nsresult RelativeFontChangeOnTextNode(FontSize aDir,
                                         Text& aTextNode,
                                         int32_t aStartOffset,
                                         int32_t aEndOffset);
-  nsresult RelativeFontChangeOnNode(int32_t aSizeChange, nsIContent* aNode);
-  nsresult RelativeFontChangeHelper(int32_t aSizeChange, nsINode* aNode);
 
-  /**
-   * Helper routines for inline style.
-   */
-  nsresult SetInlinePropertyOnTextNode(Text& aData,
-                                       int32_t aStartOffset,
-                                       int32_t aEndOffset,
-                                       nsAtom& aProperty,
-                                       nsAtom* aAttribute,
-                                       const nsAString& aValue);
   nsresult SetInlinePropertyOnNode(nsIContent& aNode,
                                    nsAtom& aProperty,
                                    nsAtom* aAttribute,
                                    const nsAString& aValue);
 
-  nsresult PromoteInlineRange(nsRange& aRange);
-  nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange);
-  nsresult SplitStyleAboveRange(nsRange* aRange,
-                                nsAtom* aProperty,
-                                nsAtom* aAttribute);
   nsresult SplitStyleAbovePoint(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
                                 nsAtom* aProperty,
                                 nsAtom* aAttribute,
                                 nsIContent** aOutLeftNode = nullptr,
                                 nsIContent** aOutRightNode = nullptr);
-  nsresult RemoveStyleInside(nsIContent& aNode,
-                             nsAtom* aProperty,
-                             nsAtom* aAttribute,
-                             const bool aChildrenOnly = false);
-
-  bool NodeIsProperty(nsINode& aNode);
-  bool IsAtFrontOfNode(nsINode& aNode, int32_t aOffset);
-  bool IsAtEndOfNode(nsINode& aNode, int32_t aOffset);
-  bool IsOnlyAttribute(const Element* aElement, nsAtom* aAttribute);
-
-  /**
-   * RemoveBlockContainerWithTransaction() removes aElement from the DOM tree
-   * but moves its all children to its parent node and if its parent needs <br>
-   * element to have at least one line-height, this inserts <br> element
-   * automatically.
-   *
-   * @param aElement            Block element to be removed.
-   */
-  nsresult RemoveBlockContainerWithTransaction(Element& aElement);
 
   nsIContent* GetPriorHTMLSibling(nsINode* aNode);
 
   nsIContent* GetNextHTMLSibling(nsINode* aNode);
 
   /**
    * GetPreviousHTMLElementOrText*() methods are similar to
    * EditorBase::GetPreviousElementOrText*() but this won't return nodes
@@ -1143,16 +704,453 @@ protected:
 
   nsresult GetInlinePropertyBase(nsAtom& aProperty,
                                  nsAtom* aAttribute,
                                  const nsAString* aValue,
                                  bool* aFirst,
                                  bool* aAny,
                                  bool* aAll,
                                  nsAString* outValue);
+
+  nsresult ClearStyle(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
+                      nsAtom* aProperty, nsAtom* aAttribute);
+
+  nsresult SetPositionToAbsolute(Element& aElement);
+  nsresult SetPositionToStatic(Element& aElement);
+
+protected: // Called by helper classes.
+  /**
+   * All editor operations which alter the doc should be prefaced
+   * with a call to StartOperation, naming the action and direction.
+   */
+  virtual nsresult StartOperation(EditAction opID,
+                                  nsIEditor::EDirection aDirection) override;
+
+  /**
+   * All editor operations which alter the doc should be followed
+   * with a call to EndOperation.
+   */
+  virtual nsresult EndOperation() override;
+
+  virtual nsresult EndUpdateViewBatch() override;
+
+protected: // Shouldn't be used by friend classes
+  virtual ~HTMLEditor();
+
+  /**
+   * InsertNodeIntoProperAncestorWithTransaction() attempts to insert aNode
+   * into the document, at aPointToInsert.  Checks with strict dtd to see if
+   * containment is allowed.  If not allowed, will attempt to find a parent
+   * in the parent hierarchy of aPointToInsert.GetContainer() that will accept
+   * aNode as a child.  If such a parent is found, will split the document
+   * tree from aPointToInsert up to parent, and then insert aNode.
+   * aPointToInsert is then adjusted to point to the actual location that
+   * aNode was inserted at.  aSplitAtEdges specifies if the splitting process
+   * is allowed to result in empty nodes.
+   *
+   * @param aNode             Node to insert.
+   * @param aPointToInsert    Insertion point.
+   * @param aSplitAtEdges     Splitting can result in empty nodes?
+   * @return                  Returns inserted point if succeeded.
+   *                          Otherwise, the result is not set.
+   */
+  template<typename PT, typename CT>
+  EditorDOMPoint
+  InsertNodeIntoProperAncestorWithTransaction(
+    nsIContent& aNode,
+    const EditorDOMPointBase<PT, CT>& aPointToInsert,
+    SplitAtEdges aSplitAtEdges);
+
+  /**
+   * InsertBrElementAtSelectionWithTransaction() inserts a new <br> element at
+   * selection.  If there is non-collapsed selection ranges, the selected
+   * ranges is deleted first.
+   */
+  nsresult InsertBrElementAtSelectionWithTransaction();
+
+  /**
+   * RemoveStyleSheetWithTransaction() removes the given URL stylesheet
+   * from mStyleSheets and mStyleSheetURLs.
+   */
+  nsresult RemoveStyleSheetWithTransaction(const nsAString& aURL);
+
+  nsresult LoadHTML(const nsAString& aInputString);
+
+  nsresult GetCSSBackgroundColorState(bool* aMixed, nsAString& aOutColor,
+                                      bool aBlockLevel);
+  nsresult GetHTMLBackgroundColorState(bool* aMixed, nsAString& outColor);
+
+  nsresult GetLastCellInRow(nsINode* aRowNode,
+                            nsINode** aCellNode);
+
+  nsresult GetCellFromRange(nsRange* aRange, Element** aCell);
+
+  /**
+   * This sets background on the appropriate container element (table, cell,)
+   * or calls into nsTextEditor to set the page background.
+   */
+  nsresult SetCSSBackgroundColorWithTransaction(const nsAString& aColor);
+  nsresult SetHTMLBackgroundColorWithTransaction(const nsAString& aColor);
+
+  virtual void
+  InitializeSelectionAncestorLimit(Selection& aSelection,
+                                   nsIContent& aAncestorLimit) override;
+
+  /**
+   * Make the given selection span the entire document.
+   */
+  virtual nsresult SelectEntireDocument(Selection* aSelection) override;
+
+  /**
+   * Use this to assure that selection is set after attribute nodes when
+   * trying to collapse selection at begining of a block node
+   * e.g., when setting at beginning of a table cell
+   * This will stop at a table, however, since we don't want to
+   * "drill down" into nested tables.
+   * @param aSelection      Optional. If null, we get current selection.
+   */
+  void CollapseSelectionToDeepestNonTableFirstChild(Selection* aSelection,
+                                                    nsINode* aNode);
+
+  /**
+   * Returns TRUE if sheet was loaded, false if it wasn't.
+   */
+  bool EnableExistingStyleSheet(const nsAString& aURL);
+
+  /**
+   * Dealing with the internal style sheet lists.
+   */
+  StyleSheet* GetStyleSheetForURL(const nsAString& aURL);
+  void GetURLForStyleSheet(StyleSheet* aStyleSheet,
+                           nsAString& aURL);
+
+  /**
+   * Add a url + known style sheet to the internal lists.
+   */
+  nsresult AddNewStyleSheetToList(const nsAString &aURL,
+                                  StyleSheet* aStyleSheet);
+  nsresult RemoveStyleSheetFromList(const nsAString &aURL);
+
+  /**
+   * MaybeCollapseSelectionAtFirstEditableNode() may collapse selection at
+   * proper position to staring to edit.  If there is a non-editable node
+   * before any editable text nodes or inline elements which can have text
+   * nodes as their children, collapse selection at start of the editing
+   * host.  If there is an editable text node which is not collapsed, collapses
+   * selection at the start of the text node.  If there is an editable inline
+   * element which cannot have text nodes as its child, collapses selection at
+   * before the element node.  Otherwise, collapses selection at start of the
+   * editing host.
+   *
+   * @param aIgnoreIfSelectionInEditingHost
+   *                        This method does nothing if selection is in the
+   *                        editing host except if it's collapsed at start of
+   *                        the editing host.
+   *                        Note that if selection ranges were outside of
+   *                        current selection limiter, selection was collapsed
+   *                        at the start of the editing host therefore, if
+   *                        you call this with setting this to true, you can
+   *                        keep selection ranges if user has already been
+   *                        changed.
+   */
+  nsresult
+  MaybeCollapseSelectionAtFirstEditableNode(
+    bool aIgnoreIfSelectionInEditingHost);
+
+  class BlobReader final : public nsIEditorBlobListener
+  {
+  public:
+    BlobReader(dom::BlobImpl* aBlob, HTMLEditor* aHTMLEditor,
+               bool aIsSafe, nsIDocument* aSourceDoc,
+               nsINode* aDestinationNode, int32_t aDestOffset,
+               bool aDoDeleteSelection);
+
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIEDITORBLOBLISTENER
+
+  private:
+    ~BlobReader()
+    {
+    }
+
+    RefPtr<dom::BlobImpl> mBlob;
+    RefPtr<HTMLEditor> mHTMLEditor;
+    bool mIsSafe;
+    nsCOMPtr<nsIDocument> mSourceDoc;
+    nsCOMPtr<nsINode> mDestinationNode;
+    int32_t mDestOffset;
+    bool mDoDeleteSelection;
+  };
+
+  virtual nsresult InitRules() override;
+
+  virtual void CreateEventListeners() override;
+  virtual nsresult InstallEventListeners() override;
+  virtual void RemoveEventListeners() override;
+
+  bool ShouldReplaceRootElement();
+  void NotifyRootChanged();
+  Element* GetBodyElement();
+
+  /**
+   * Get the focused node of this editor.
+   * @return    If the editor has focus, this returns the focused node.
+   *            Otherwise, returns null.
+   */
+  already_AddRefed<nsINode> GetFocusedNode();
+
+  /**
+   * Return TRUE if aElement is a table-related elemet and caret was set.
+   */
+  bool SetCaretInTableCell(dom::Element* aElement);
+
+  nsresult TabInTable(bool inIsShift, bool* outHandled);
+
+  /**
+   * Insert a new cell after or before supplied aCell.
+   * Optional: If aNewCell supplied, returns the newly-created cell (addref'd,
+   * of course)
+   * This doesn't change or use the current selection.
+   */
+  nsresult InsertCell(Element* aCell, int32_t aRowSpan,
+                      int32_t aColSpan, bool aAfter, bool aIsHeader,
+                      Element** aNewCell);
+
+  /**
+   * Helpers that don't touch the selection or do batch transactions.
+   */
+  nsresult DeleteRow(Element* aTable, int32_t aRowIndex);
+  nsresult DeleteColumn(Element* aTable, int32_t aColIndex);
+  nsresult DeleteCellContents(Element* aCell);
+
+  /**
+   * Move all contents from aCellToMerge into aTargetCell (append at end).
+   */
+  nsresult MergeCells(RefPtr<Element> aTargetCell,
+                      RefPtr<Element> aCellToMerge,
+                      bool aDeleteCellToMerge);
+
+  nsresult DeleteTable2(Element* aTable, Selection* aSelection);
+  nsresult SetColSpan(Element* aCell, int32_t aColSpan);
+  nsresult SetRowSpan(Element* aCell, int32_t aRowSpan);
+
+  /**
+   * Helper used to get nsTableWrapperFrame for a table.
+   */
+  nsTableWrapperFrame* GetTableFrame(Element* aTable);
+
+  /**
+   * Needed to do appropriate deleting when last cell or row is about to be
+   * deleted.  This doesn't count cells that don't start in the given row (are
+   * spanning from row above).
+   */
+  int32_t GetNumberOfCellsInRow(Element* aTable, int32_t rowIndex);
+
+  /**
+   * Test if all cells in row or column at given index are selected.
+   */
+  bool AllCellsInRowSelected(Element* aTable, int32_t aRowIndex,
+                             int32_t aNumberOfColumns);
+  bool AllCellsInColumnSelected(Element* aTable, int32_t aColIndex,
+                                int32_t aNumberOfRows);
+
+  bool IsEmptyCell(Element* aCell);
+
+  /**
+   * Most insert methods need to get the same basic context data.
+   * Any of the pointers may be null if you don't need that datum (for more
+   * efficiency).
+   * Input: *aCell is a known cell,
+   *        if null, cell is obtained from the anchor node of the selection.
+   * Returns NS_EDITOR_ELEMENT_NOT_FOUND if cell is not found even if aCell is
+   * null.
+   */
+  nsresult GetCellContext(Selection** aSelection, Element** aTable,
+                          Element** aCell, nsINode** aCellParent,
+                          int32_t* aCellOffset, int32_t* aRowIndex,
+                          int32_t* aColIndex);
+
+  nsresult GetCellSpansAt(Element* aTable, int32_t aRowIndex,
+                          int32_t aColIndex, int32_t& aActualRowSpan,
+                          int32_t& aActualColSpan);
+
+  nsresult SplitCellIntoColumns(Element* aTable, int32_t aRowIndex,
+                                int32_t aColIndex, int32_t aColSpanLeft,
+                                int32_t aColSpanRight,
+                                Element** aNewCell);
+
+  nsresult SplitCellIntoRows(Element* aTable, int32_t aRowIndex,
+                             int32_t aColIndex, int32_t aRowSpanAbove,
+                             int32_t aRowSpanBelow, Element** aNewCell);
+
+  nsresult CopyCellBackgroundColor(Element* aDestCell,
+                                   Element* aSourceCell);
+
+  /**
+   * Reduce rowspan/colspan when cells span into nonexistent rows/columns.
+   */
+  nsresult FixBadRowSpan(Element* aTable, int32_t aRowIndex,
+                         int32_t& aNewRowCount);
+  nsresult FixBadColSpan(Element* aTable, int32_t aColIndex,
+                         int32_t& aNewColCount);
+
+  /**
+   * Fallback method: Call this after using ClearSelection() and you
+   * failed to set selection to some other content in the document.
+   */
+  nsresult SetSelectionAtDocumentStart(Selection* aSelection);
+
+  static Element* GetEnclosingTable(nsINode* aNode);
+  static nsIDOMNode* GetEnclosingTable(nsIDOMNode* aNode);
+
+  // Methods for handling plaintext quotations
+  nsresult PasteAsPlaintextQuotation(int32_t aSelectionType);
+
+  /**
+   * Insert a string as quoted text, replacing the selected text (if any).
+   * @param aQuotedText     The string to insert.
+   * @param aAddCites       Whether to prepend extra ">" to each line
+   *                        (usually true, unless those characters
+   *                        have already been added.)
+   * @return aNodeInserted  The node spanning the insertion, if applicable.
+   *                        If aAddCites is false, this will be null.
+   */
+  nsresult InsertAsPlaintextQuotation(const nsAString& aQuotedText,
+                                      bool aAddCites,
+                                      nsIDOMNode** aNodeInserted);
+
+  nsresult InsertObject(const nsACString& aType, nsISupports* aObject,
+                        bool aIsSafe,
+                        nsIDocument* aSourceDoc,
+                        nsINode* aDestinationNode,
+                        int32_t aDestOffset,
+                        bool aDoDeleteSelection);
+
+  // factored methods for handling insertion of data from transferables
+  // (drag&drop or clipboard)
+  virtual nsresult PrepareTransferable(nsITransferable** transferable) override;
+  nsresult PrepareHTMLTransferable(nsITransferable** transferable);
+  nsresult InsertFromTransferable(nsITransferable* transferable,
+                                    nsIDocument* aSourceDoc,
+                                    const nsAString& aContextStr,
+                                    const nsAString& aInfoStr,
+                                    bool havePrivateHTMLFlavor,
+                                    bool aDoDeleteSelection);
+  virtual nsresult InsertFromDataTransfer(dom::DataTransfer* aDataTransfer,
+                                          int32_t aIndex,
+                                          nsIDocument* aSourceDoc,
+                                          nsINode* aDestinationNode,
+                                          int32_t aDestOffset,
+                                          bool aDoDeleteSelection) override;
+  bool HavePrivateHTMLFlavor(nsIClipboard* clipboard );
+  nsresult ParseCFHTML(nsCString& aCfhtml, char16_t** aStuffToPaste,
+                       char16_t** aCfcontext);
+
+  nsresult StripFormattingNodes(nsIContent& aNode, bool aOnlyList = false);
+  nsresult CreateDOMFragmentFromPaste(const nsAString& aInputString,
+                                      const nsAString& aContextStr,
+                                      const nsAString& aInfoStr,
+                                      nsCOMPtr<nsINode>* outFragNode,
+                                      nsCOMPtr<nsINode>* outStartNode,
+                                      nsCOMPtr<nsINode>* outEndNode,
+                                      int32_t* outStartOffset,
+                                      int32_t* outEndOffset,
+                                      bool aTrustedInput);
+  nsresult ParseFragment(const nsAString& aStr, nsAtom* aContextLocalName,
+                         nsIDocument* aTargetDoc,
+                         dom::DocumentFragment** aFragment, bool aTrustedInput);
+  void CreateListOfNodesToPaste(dom::DocumentFragment& aFragment,
+                                nsTArray<OwningNonNull<nsINode>>& outNodeList,
+                                nsINode* aStartContainer,
+                                int32_t aStartOffset,
+                                nsINode* aEndContainer,
+                                int32_t aEndOffset);
+  enum class StartOrEnd { start, end };
+  void GetListAndTableParents(StartOrEnd aStartOrEnd,
+                              nsTArray<OwningNonNull<nsINode>>& aNodeList,
+                              nsTArray<OwningNonNull<Element>>& outArray);
+  int32_t DiscoverPartialListsAndTables(
+            nsTArray<OwningNonNull<nsINode>>& aPasteNodes,
+            nsTArray<OwningNonNull<Element>>& aListsAndTables);
+  nsINode* ScanForListAndTableStructure(
+             StartOrEnd aStartOrEnd,
+             nsTArray<OwningNonNull<nsINode>>& aNodes,
+             Element& aListOrTable);
+  void ReplaceOrphanedStructure(
+         StartOrEnd aStartOrEnd,
+         nsTArray<OwningNonNull<nsINode>>& aNodeArray,
+         nsTArray<OwningNonNull<Element>>& aListAndTableArray,
+         int32_t aHighWaterMark);
+
+  /**
+   * GetBetterInsertionPointFor() returns better insertion point to insert
+   * aNodeToInsert.
+   *
+   * @param aNodeToInsert       The node to insert.
+   * @param aPointToInsert      A candidate point to insert the node.
+   * @return                    Better insertion point if next visible node
+   *                            is a <br> element and previous visible node
+   *                            is neither none, another <br> element nor
+   *                            different block level element.
+   */
+  EditorRawDOMPoint
+  GetBetterInsertionPointFor(nsINode& aNodeToInsert,
+                             const EditorRawDOMPoint& aPointToInsert);
+
+  /**
+   * MakeDefinitionListItemWithTransaction() replaces parent list of current
+   * selection with <dl> or create new <dl> element and creates a definition
+   * list item whose name is aTagName.
+   *
+   * @param aTagName            Must be nsGkAtoms::dt or nsGkAtoms::dd.
+   */
+  nsresult MakeDefinitionListItemWithTransaction(nsAtom& aTagName);
+
+  /**
+   * InsertBasicBlockWithTransaction() inserts a block element whose name
+   * is aTagName at selection.
+   *
+   * @param aTagName            A block level element name.  Must NOT be
+   *                            nsGkAtoms::dt nor nsGkAtoms::dd.
+   */
+  nsresult InsertBasicBlockWithTransaction(nsAtom& aTagName);
+
+  /**
+   * Increase/decrease the font size of selection.
+   */
+  nsresult RelativeFontChange(FontSize aDir);
+
+  nsresult RelativeFontChangeOnNode(int32_t aSizeChange, nsIContent* aNode);
+  nsresult RelativeFontChangeHelper(int32_t aSizeChange, nsINode* aNode);
+
+  /**
+   * Helper routines for inline style.
+   */
+  nsresult SetInlinePropertyOnTextNode(Text& aData,
+                                       int32_t aStartOffset,
+                                       int32_t aEndOffset,
+                                       nsAtom& aProperty,
+                                       nsAtom* aAttribute,
+                                       const nsAString& aValue);
+
+  nsresult PromoteInlineRange(nsRange& aRange);
+  nsresult PromoteRangeIfStartsOrEndsInNamedAnchor(nsRange& aRange);
+  nsresult SplitStyleAboveRange(nsRange* aRange,
+                                nsAtom* aProperty,
+                                nsAtom* aAttribute);
+  nsresult RemoveStyleInside(nsIContent& aNode,
+                             nsAtom* aProperty,
+                             nsAtom* aAttribute,
+                             const bool aChildrenOnly = false);
+
+  bool NodeIsProperty(nsINode& aNode);
+  bool IsAtFrontOfNode(nsINode& aNode, int32_t aOffset);
+  bool IsAtEndOfNode(nsINode& aNode, int32_t aOffset);
+  bool IsOnlyAttribute(const Element* aElement, nsAtom* aAttribute);
+
   bool HasStyleOrIdOrClass(Element* aElement);
   nsresult RemoveElementIfNoStyleOrIdOrClass(Element& aElement);
 
   /**
    * Whether the outer window of the DOM event target has focus or not.
    */
   bool OurWindowHasFocus();
 
@@ -1174,19 +1172,16 @@ protected:
                                    const nsAString& aFlavor,
                                    nsIDocument* aSourceDoc,
                                    nsINode* aDestNode,
                                    int32_t aDestOffset,
                                    bool aDeleteSelection,
                                    bool aTrustedInput,
                                    bool aClearStyle = true);
 
-  nsresult ClearStyle(nsCOMPtr<nsINode>* aNode, int32_t* aOffset,
-                      nsAtom* aProperty, nsAtom* aAttribute);
-
   /**
    * sets the position of an element; warning it does NOT check if the
    * element is already positioned or not and that's on purpose.
    * @param aElement [IN] the element
    * @param aX       [IN] the x position in pixels.
    * @param aY       [IN] the y position in pixels.
    */
   void SetTopAndLeft(Element& aElement, int32_t aX, int32_t aY);
@@ -1216,43 +1211,16 @@ protected:
                                   int32_t aDirection, bool aSelected);
 
   /**
    * A more C++-friendly version of nsIHTMLEditor::GetSelectedElement
    * that just returns null on errors.
    */
   already_AddRefed<dom::Element> GetSelectedElement(const nsAString& aTagName);
 
-  /**
-   * RemoveStyleSheetWithTransaction() removes the given URL stylesheet
-   * from mStyleSheets and mStyleSheetURLs.
-   */
-  nsresult RemoveStyleSheetWithTransaction(const nsAString& aURL);
-
-protected:
-  RefPtr<TypeInState> mTypeInState;
-  RefPtr<ComposerCommandsUpdater> mComposerCommandsUpdater;
-
-  bool mCRInParagraphCreatesParagraph;
-
-  bool mCSSAware;
-  UniquePtr<CSSEditUtils> mCSSEditUtils;
-
-  // Used by GetFirstSelectedCell and GetNextSelectedCell
-  int32_t  mSelectedCellIndex;
-
-  nsString mLastStyleSheetURL;
-  nsString mLastOverrideStyleSheetURL;
-
-  // Maintain a list of associated style sheets and their urls.
-  nsTArray<nsString> mStyleSheetURLs;
-  nsTArray<RefPtr<StyleSheet>> mStyleSheets;
-
-protected:
-  // ANONYMOUS UTILS
   void RemoveListenerAndDeleteRef(const nsAString& aEvent,
                                   nsIDOMEventListener* aListener,
                                   bool aUseCapture,
                                   ManualNACPtr aElement,
                                   nsIPresShell* aShell);
   void DeleteRefToAnonymousNode(ManualNACPtr aContent,
                                 nsIPresShell* aShell);
 
@@ -1270,16 +1238,158 @@ protected:
                                     int32_t& aBorderTop,
                                     int32_t& aMarginLeft,
                                     int32_t& aMarginTop);
 
   bool IsInObservedSubtree(nsIContent* aChild);
 
   void UpdateRootElement();
 
+  nsresult SetAllResizersPosition();
+
+  /**
+   * Shows active resizers around an element's frame
+   * @param aResizedElement [IN] a DOM Element
+   */
+  nsresult ShowResizers(Element& aResizedElement);
+
+  ManualNACPtr CreateResizer(int16_t aLocation, nsIContent& aParentContent);
+  void SetAnonymousElementPosition(int32_t aX, int32_t aY,
+                                   Element* aResizer);
+
+  ManualNACPtr CreateShadow(nsIContent& aParentContent,
+                            Element& aOriginalObject);
+  nsresult SetShadowPosition(Element* aShadow, Element* aOriginalObject,
+                             int32_t aOriginalObjectX,
+                             int32_t aOriginalObjectY);
+
+  ManualNACPtr CreateResizingInfo(nsIContent& aParentContent);
+  nsresult SetResizingInfoPosition(int32_t aX, int32_t aY,
+                                   int32_t aW, int32_t aH);
+
+  enum class ResizeAt
+  {
+    eX,
+    eY,
+    eWidth,
+    eHeight,
+  };
+  int32_t GetNewResizingIncrement(int32_t aX, int32_t aY,
+                                  ResizeAt aResizeAt);
+
+  nsresult StartResizing(Element* aHandle);
+  int32_t GetNewResizingX(int32_t aX, int32_t aY);
+  int32_t GetNewResizingY(int32_t aX, int32_t aY);
+  int32_t GetNewResizingWidth(int32_t aX, int32_t aY);
+  int32_t GetNewResizingHeight(int32_t aX, int32_t aY);
+  void HideShadowAndInfo();
+  void SetFinalSize(int32_t aX, int32_t aY);
+  void SetResizeIncrements(int32_t aX, int32_t aY, int32_t aW, int32_t aH,
+                           bool aPreserveRatio);
+  void HideAnonymousEditingUIs();
+
+  /**
+   * sets the z-index of an element.
+   * @param aElement [IN] the element
+   * @param aZorder  [IN] the z-index
+   */
+  void SetZIndex(Element& aElement, int32_t aZorder);
+
+  /**
+   * shows a grabber attached to an arbitrary element. The grabber is an image
+   * positioned on the left hand side of the top border of the element. Draggin
+   * and dropping it allows to change the element's absolute position in the
+   * document. See chrome://editor/content/images/grabber.gif
+   * @param aElement [IN] the element
+   */
+  nsresult ShowGrabber(Element& aElement);
+
+  /**
+   * hide the grabber if it shown.
+   */
+  void HideGrabber();
+
+  ManualNACPtr CreateGrabber(nsIContent& aParentContent);
+  nsresult StartMoving();
+  nsresult SetFinalPosition(int32_t aX, int32_t aY);
+  void AddPositioningOffset(int32_t& aX, int32_t& aY);
+  void SnapToGrid(int32_t& newX, int32_t& newY);
+  nsresult GrabberClicked();
+  nsresult EndMoving();
+  nsresult GetTemporaryStyleForFocusedPositionedElement(Element& aElement,
+                                                        nsAString& aReturn);
+
+  /**
+   * Shows inline table editing UI around a table cell
+   * @param aCell [IN] a DOM Element being a table cell, td or th
+   */
+  nsresult ShowInlineTableEditingUI(Element* aCell);
+
+  /**
+   * Hide all inline table editing UI
+   */
+  nsresult HideInlineTableEditingUI();
+
+  /**
+   * IsEmptyTextNode() returns true if aNode is a text node and does not have
+   * any visible characters.
+   */
+  bool IsEmptyTextNode(nsINode& aNode);
+
+  bool IsSimpleModifiableNode(nsIContent* aContent,
+                              nsAtom* aProperty,
+                              nsAtom* aAttribute,
+                              const nsAString* aValue);
+  nsresult SetInlinePropertyOnNodeImpl(nsIContent& aNode,
+                                       nsAtom& aProperty,
+                                       nsAtom* aAttribute,
+                                       const nsAString& aValue);
+  typedef enum { eInserted, eAppended } InsertedOrAppended;
+  void DoContentInserted(nsIContent* aChild, InsertedOrAppended);
+  // XXX Shouldn't this used by external classes instead of nsIHTMLEditor's
+  //     method?
+  already_AddRefed<Element> CreateElementWithDefaults(
+                              const nsAString& aTagName);
+  /**
+   * Returns an anonymous Element of type aTag,
+   * child of aParentContent. If aIsCreatedHidden is true, the class
+   * "hidden" is added to the created element. If aAnonClass is not
+   * the empty string, it becomes the value of the attribute "_moz_anonclass"
+   * @return a Element
+   * @param aTag             [IN] desired type of the element to create
+   * @param aParentContent   [IN] the parent node of the created anonymous
+   *                              element
+   * @param aAnonClass       [IN] contents of the _moz_anonclass attribute
+   * @param aIsCreatedHidden [IN] a boolean specifying if the class "hidden"
+   *                              is to be added to the created anonymous
+   *                              element
+   */
+  ManualNACPtr CreateAnonymousElement(nsAtom* aTag,
+                                      nsIContent& aParentContent,
+                                      const nsAString& aAnonClass,
+                                      bool aIsCreatedHidden);
+protected:
+  RefPtr<TypeInState> mTypeInState;
+  RefPtr<ComposerCommandsUpdater> mComposerCommandsUpdater;
+
+  bool mCRInParagraphCreatesParagraph;
+
+  bool mCSSAware;
+  UniquePtr<CSSEditUtils> mCSSEditUtils;
+
+  // Used by GetFirstSelectedCell and GetNextSelectedCell
+  int32_t  mSelectedCellIndex;
+
+  nsString mLastStyleSheetURL;
+  nsString mLastOverrideStyleSheetURL;
+
+  // Maintain a list of associated style sheets and their urls.
+  nsTArray<nsString> mStyleSheetURLs;
+  nsTArray<RefPtr<StyleSheet>> mStyleSheets;
+
   // resizing
   // If the instance has shown resizers at least once, mHasShownResizers is
   // set to true.
   bool mHasShownResizers;
   bool mIsObjectResizingEnabled;
   bool mIsResizing;
   bool mPreserveRatio;
   bool mResizedObjectIsAnImage;
@@ -1343,50 +1453,16 @@ protected:
   // actually, the following counters are increased.
   uint32_t mResizerUsedCount;
   uint32_t mGrabberUsedCount;
   uint32_t mInlineTableEditorUsedCount;
 
   int8_t  mInfoXIncrement;
   int8_t  mInfoYIncrement;
 
-  nsresult SetAllResizersPosition();
-
-  /**
-   * Shows active resizers around an element's frame
-   * @param aResizedElement [IN] a DOM Element
-   */
-  nsresult ShowResizers(Element& aResizedElement);
-
-  ManualNACPtr CreateResizer(int16_t aLocation, nsIContent& aParentContent);
-  void SetAnonymousElementPosition(int32_t aX, int32_t aY,
-                                   Element* aResizer);
-
-  ManualNACPtr CreateShadow(nsIContent& aParentContent,
-                            Element& aOriginalObject);
-  nsresult SetShadowPosition(Element* aShadow, Element* aOriginalObject,
-                             int32_t aOriginalObjectX,
-                             int32_t aOriginalObjectY);
-
-  ManualNACPtr CreateResizingInfo(nsIContent& aParentContent);
-  nsresult SetResizingInfoPosition(int32_t aX, int32_t aY,
-                                   int32_t aW, int32_t aH);
-
-  int32_t GetNewResizingIncrement(int32_t aX, int32_t aY, int32_t aID);
-  nsresult StartResizing(Element* aHandle);
-  int32_t GetNewResizingX(int32_t aX, int32_t aY);
-  int32_t GetNewResizingY(int32_t aX, int32_t aY);
-  int32_t GetNewResizingWidth(int32_t aX, int32_t aY);
-  int32_t GetNewResizingHeight(int32_t aX, int32_t aY);
-  void HideShadowAndInfo();
-  void SetFinalSize(int32_t aX, int32_t aY);
-  void SetResizeIncrements(int32_t aX, int32_t aY, int32_t aW, int32_t aH,
-                           bool aPreserveRatio);
-  void HideAnonymousEditingUIs();
-
   // absolute positioning
   int32_t mPositionedObjectX;
   int32_t mPositionedObjectY;
   int32_t mPositionedObjectWidth;
   int32_t mPositionedObjectHeight;
 
   int32_t mPositionedObjectMarginLeft;
   int32_t mPositionedObjectMarginTop;
@@ -1394,125 +1470,39 @@ protected:
   int32_t mPositionedObjectBorderTop;
 
   nsCOMPtr<Element> mAbsolutelyPositionedObject;
   ManualNACPtr mGrabber;
   ManualNACPtr mPositioningShadow;
 
   int32_t mGridSize;
 
-  nsresult SetPositionToAbsolute(Element& aElement);
-  nsresult SetPositionToStatic(Element& aElement);
-
-  /**
-   * sets the z-index of an element.
-   * @param aElement [IN] the element
-   * @param aZorder  [IN] the z-index
-   */
-  void SetZIndex(Element& aElement, int32_t aZorder);
-
-  /**
-   * shows a grabber attached to an arbitrary element. The grabber is an image
-   * positioned on the left hand side of the top border of the element. Draggin
-   * and dropping it allows to change the element's absolute position in the
-   * document. See chrome://editor/content/images/grabber.gif
-   * @param aElement [IN] the element
-   */
-  nsresult ShowGrabber(Element& aElement);
-
-  /**
-   * hide the grabber if it shown.
-   */
-  void HideGrabber();
-
-  ManualNACPtr CreateGrabber(nsIContent& aParentContent);
-  nsresult StartMoving();
-  nsresult SetFinalPosition(int32_t aX, int32_t aY);
-  void AddPositioningOffset(int32_t& aX, int32_t& aY);
-  void SnapToGrid(int32_t& newX, int32_t& newY);
-  nsresult GrabberClicked();
-  nsresult EndMoving();
-  nsresult GetTemporaryStyleForFocusedPositionedElement(Element& aElement,
-                                                        nsAString& aReturn);
-
   // inline table editing
   RefPtr<Element> mInlineEditedCell;
 
   ManualNACPtr mAddColumnBeforeButton;
   ManualNACPtr mRemoveColumnButton;
   ManualNACPtr mAddColumnAfterButton;
 
   ManualNACPtr mAddRowBeforeButton;
   ManualNACPtr mRemoveRowButton;
   ManualNACPtr mAddRowAfterButton;
 
-  /**
-   * Shows inline table editing UI around a table cell
-   * @param aCell [IN] a DOM Element being a table cell, td or th
-   */
-  nsresult ShowInlineTableEditingUI(Element* aCell);
-
-  /**
-   * Hide all inline table editing UI
-   */
-  nsresult HideInlineTableEditingUI();
-
   void AddMouseClickListener(Element* aElement);
   void RemoveMouseClickListener(Element* aElement);
 
   nsCOMPtr<nsILinkHandler> mLinkHandler;
 
   ParagraphSeparator mDefaultParagraphSeparator;
 
-public:
   friend class AutoSelectionSetterAfterTableEdit;
-  friend class HTMLEditorEventListener;
+  friend class CSSEditUtils;
+  friend class EmptyEditableFunctor;
   friend class HTMLEditRules;
-  friend class TextEditRules;
   friend class WSRunObject;
-
-private:
-  /**
-   * IsEmptyTextNode() returns true if aNode is a text node and does not have
-   * any visible characters.
-   */
-  bool IsEmptyTextNode(nsINode& aNode);
-
-  bool IsSimpleModifiableNode(nsIContent* aContent,
-                              nsAtom* aProperty,
-                              nsAtom* aAttribute,
-                              const nsAString* aValue);
-  nsresult SetInlinePropertyOnNodeImpl(nsIContent& aNode,
-                                       nsAtom& aProperty,
-                                       nsAtom* aAttribute,
-                                       const nsAString& aValue);
-  typedef enum { eInserted, eAppended } InsertedOrAppended;
-  void DoContentInserted(nsIContent* aChild, InsertedOrAppended);
-  already_AddRefed<Element> GetElementOrParentByTagName(
-                              const nsAString& aTagName, nsINode* aNode);
-  already_AddRefed<Element> CreateElementWithDefaults(
-                              const nsAString& aTagName);
-  /**
-   * Returns an anonymous Element of type aTag,
-   * child of aParentContent. If aIsCreatedHidden is true, the class
-   * "hidden" is added to the created element. If aAnonClass is not
-   * the empty string, it becomes the value of the attribute "_moz_anonclass"
-   * @return a Element
-   * @param aTag             [IN] desired type of the element to create
-   * @param aParentContent   [IN] the parent node of the created anonymous
-   *                              element
-   * @param aAnonClass       [IN] contents of the _moz_anonclass attribute
-   * @param aIsCreatedHidden [IN] a boolean specifying if the class "hidden"
-   *                              is to be added to the created anonymous
-   *                              element
-   */
-  ManualNACPtr CreateAnonymousElement(nsAtom* aTag,
-                                      nsIContent& aParentContent,
-                                      const nsAString& aAnonClass,
-                                      bool aIsCreatedHidden);
 };
 
 } // namespace mozilla
 
 mozilla::HTMLEditor*
 nsIEditor::AsHTMLEditor()
 {
   return static_cast<mozilla::EditorBase*>(this)->mIsHTMLEditorClass ?
--- a/editor/libeditor/HTMLEditorObjectResizer.cpp
+++ b/editor/libeditor/HTMLEditorObjectResizer.cpp
@@ -686,92 +686,98 @@ HTMLEditor::SetShadowPosition(Element* a
     NS_ENSURE_SUCCESS(rv, rv);
   }
   return NS_OK;
 }
 
 int32_t
 HTMLEditor::GetNewResizingIncrement(int32_t aX,
                                     int32_t aY,
-                                    int32_t aID)
+                                    ResizeAt aResizeAt)
 {
   int32_t result = 0;
   if (!mPreserveRatio) {
-    switch (aID) {
-      case kX:
-      case kWidth:
+    switch (aResizeAt) {
+      case ResizeAt::eX:
+      case ResizeAt::eWidth:
         result = aX - mOriginalX;
         break;
-      case kY:
-      case kHeight:
+      case ResizeAt::eY:
+      case ResizeAt::eHeight:
         result = aY - mOriginalY;
         break;
+      default:
+        MOZ_ASSERT_UNREACHABLE("Invalid resizing request");
     }
     return result;
   }
 
   int32_t xi = (aX - mOriginalX) * mWidthIncrementFactor;
   int32_t yi = (aY - mOriginalY) * mHeightIncrementFactor;
   float objectSizeRatio =
               ((float)mResizedObjectWidth) / ((float)mResizedObjectHeight);
   result = (xi > yi) ? xi : yi;
-  switch (aID) {
-    case kX:
-    case kWidth:
+  switch (aResizeAt) {
+    case ResizeAt::eX:
+    case ResizeAt::eWidth:
       if (result == yi)
         result = (int32_t) (((float) result) * objectSizeRatio);
       result = (int32_t) (((float) result) * mWidthIncrementFactor);
       break;
-    case kY:
-    case kHeight:
+    case ResizeAt::eY:
+    case ResizeAt::eHeight:
       if (result == xi)
         result =  (int32_t) (((float) result) / objectSizeRatio);
       result = (int32_t) (((float) result) * mHeightIncrementFactor);
       break;
   }
   return result;
 }
 
 int32_t
 HTMLEditor::GetNewResizingX(int32_t aX,
                             int32_t aY)
 {
-  int32_t resized = mResizedObjectX +
-                    GetNewResizingIncrement(aX, aY, kX) * mXIncrementFactor;
-  int32_t max =   mResizedObjectX + mResizedObjectWidth;
+  int32_t resized =
+    mResizedObjectX +
+      GetNewResizingIncrement(aX, aY, ResizeAt::eX) * mXIncrementFactor;
+  int32_t max = mResizedObjectX + mResizedObjectWidth;
   return std::min(resized, max);
 }
 
 int32_t
 HTMLEditor::GetNewResizingY(int32_t aX,
                             int32_t aY)
 {
-  int32_t resized = mResizedObjectY +
-                    GetNewResizingIncrement(aX, aY, kY) * mYIncrementFactor;
+  int32_t resized =
+    mResizedObjectY +
+      GetNewResizingIncrement(aX, aY, ResizeAt::eY) * mYIncrementFactor;
   int32_t max =   mResizedObjectY + mResizedObjectHeight;
   return std::min(resized, max);
 }
 
 int32_t
 HTMLEditor::GetNewResizingWidth(int32_t aX,
                                 int32_t aY)
 {
-  int32_t resized = mResizedObjectWidth +
-                     GetNewResizingIncrement(aX, aY, kWidth) *
-                         mWidthIncrementFactor;
+  int32_t resized =
+    mResizedObjectWidth +
+      GetNewResizingIncrement(aX, aY,
+                              ResizeAt::eWidth) * mWidthIncrementFactor;
   return std::max(resized, 1);
 }
 
 int32_t
 HTMLEditor::GetNewResizingHeight(int32_t aX,
                                  int32_t aY)
 {
-  int32_t resized = mResizedObjectHeight +
-                     GetNewResizingIncrement(aX, aY, kHeight) *
-                         mHeightIncrementFactor;
+  int32_t resized =
+    mResizedObjectHeight +
+      GetNewResizingIncrement(aX, aY,
+                              ResizeAt::eHeight) * mHeightIncrementFactor;
   return std::max(resized, 1);
 }
 
 nsresult
 HTMLEditor::OnMouseMove(MouseEvent* aMouseEvent)
 {
   MOZ_ASSERT(aMouseEvent);