Bug 1319340 - part6: Implement some interface methods as non-virtual methods of EditorBase or HTMLEditor r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 04 Aug 2017 18:30:13 +0900
changeset 644052 a4e44ef8290892e8333fa07a0b6fa2b80c2377a2
parent 644051 0c2b2c0d1de13de733f02360592c0156bd10c701
child 644053 88b103afd8859020c4db642686f199280194dc7c
push id73292
push usermasayuki@d-toybox.com
push dateThu, 10 Aug 2017 11:23:45 +0000
reviewersm_kato
bugs1319340
milestone57.0a1
Bug 1319340 - part6: Implement some interface methods as non-virtual methods of EditorBase or HTMLEditor r?m_kato nsComposerCommands uses some simple getter methods. They can be simpler non-virtual methods. So, we should do it. Note that this changes that EditorBase::GetIsSelectionEditable() won't return error. However, it has returned error only when selection controller isn't available. That means that the selection controller has been destroyed and the editor will be destroyed. So, this must not be problem since it returns false (non-editable) instead and won't break any behavior since the editor won't be editable by users nor JS anymore. MozReview-Commit-ID: E9ccFspG6na
editor/composer/nsComposerCommands.cpp
editor/libeditor/EditorBase.cpp
editor/libeditor/EditorBase.h
editor/libeditor/HTMLAbsPositionEditor.cpp
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditor.h
--- a/editor/composer/nsComposerCommands.cpp
+++ b/editor/composer/nsComposerCommands.cpp
@@ -80,17 +80,18 @@ nsBaseStateUpdatingCommand::IsCommandEna
 {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
   if (!editor) {
     *outCmdEnabled = false;
     return NS_OK;
   }
   mozilla::EditorBase* editorBase = editor->AsEditorBase();
   MOZ_ASSERT(editorBase);
-  return editorBase->GetIsSelectionEditable(outCmdEnabled);
+  *outCmdEnabled = editorBase->IsSelectionEditable();
+  return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsBaseStateUpdatingCommand::DoCommand(const char *aCommandName,
                                       nsISupports *refCon)
 {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
@@ -415,32 +416,29 @@ nsRemoveListCommand::IsCommandEnabled(co
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
   if (!editor) {
     return NS_OK;
   }
 
   mozilla::EditorBase* editorBase = editor->AsEditorBase();
   MOZ_ASSERT(editorBase);
 
-  bool isEditable = false;
-  nsresult rv = editorBase->GetIsSelectionEditable(&isEditable);
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (!isEditable) {
+  if (!editorBase->IsSelectionEditable()) {
     return NS_OK;
   }
 
   // It is enabled if we are in any list type
   mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
 
   bool bMixed;
   nsAutoString localName;
-  rv = GetListState(htmlEditor, &bMixed, localName);
+  nsresult rv = GetListState(htmlEditor, &bMixed, localName);
   NS_ENSURE_SUCCESS(rv, rv);
 
   *outCmdEnabled = bMixed || !localName.IsEmpty();
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
@@ -482,17 +480,18 @@ nsIndentCommand::IsCommandEnabled(const 
 {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
   if (!editor) {
     *outCmdEnabled = false;
     return NS_OK;
   }
   mozilla::EditorBase* editorBase = editor->AsEditorBase();
   MOZ_ASSERT(editorBase);
-  return editorBase->GetIsSelectionEditable(outCmdEnabled);
+  *outCmdEnabled = editorBase->IsSelectionEditable();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsIndentCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
 {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
   if (!editor) {
     return NS_OK;
@@ -532,17 +531,18 @@ nsOutdentCommand::IsCommandEnabled(const
 {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
   if (!editor) {
     *outCmdEnabled = false;
     return NS_OK;
   }
   mozilla::EditorBase* editorBase = editor->AsEditorBase();
   MOZ_ASSERT(editorBase);
-  return editorBase->GetIsSelectionEditable(outCmdEnabled);
+  *outCmdEnabled = editorBase->IsSelectionEditable();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsOutdentCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
 {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
   if (!editor) {
     return NS_OK;
@@ -591,17 +591,18 @@ nsMultiStateCommand::IsCommandEnabled(co
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
   if (!editor) {
     *outCmdEnabled = false;
     return NS_OK;
   }
   mozilla::EditorBase* editorBase = editor->AsEditorBase();
   MOZ_ASSERT(editorBase);
   // should be disabled sometimes, like if the current selection is an image
-  return editorBase->GetIsSelectionEditable(outCmdEnabled);
+  *outCmdEnabled = editorBase->IsSelectionEditable();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMultiStateCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
 {
 #ifdef DEBUG
   printf("who is calling nsMultiStateCommand::DoCommand \
           (no implementation)? %s\n", aCommandName);
@@ -901,20 +902,20 @@ nsHighlightColorStateCommand::IsCommandE
 {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
   if (!editor) {
     *outCmdEnabled = false;
     return NS_OK;
   }
   mozilla::EditorBase* editorBase = editor->AsEditorBase();
   MOZ_ASSERT(editorBase);
-  return editorBase->GetIsSelectionEditable(outCmdEnabled);
+  *outCmdEnabled = editorBase->IsSelectionEditable();
+  return NS_OK;
 }
 
-
 nsBackgroundColorStateCommand::nsBackgroundColorStateCommand()
 : nsMultiStateCommand()
 {
 }
 
 nsresult
 nsBackgroundColorStateCommand::GetCurrentState(mozilla::HTMLEditor* aHTMLEditor,
                                                nsICommandParams* aParams)
@@ -1015,70 +1016,68 @@ nsAbsolutePositioningCommand::IsCommandE
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
   if (!editor) {
     return NS_OK;
   }
   mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
   if (!htmlEditor) {
     return NS_OK;
   }
-  bool isEditable = false;
-  nsresult rv = htmlEditor->GetIsSelectionEditable(&isEditable);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  if (!isEditable) {
+  if (!htmlEditor->IsSelectionEditable()) {
     return NS_OK;
   }
-  return htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled);
+  *outCmdEnabled = htmlEditor->AbsolutePositioningEnabled();
+  return NS_OK;
 }
 
 nsresult
 nsAbsolutePositioningCommand::GetCurrentState(mozilla::HTMLEditor* aHTMLEditor,
                                               nsICommandParams* aParams)
 {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  bool isEnabled;
-  aHTMLEditor->GetAbsolutePositioningEnabled(&isEnabled);
+  bool isEnabled = aHTMLEditor->AbsolutePositioningEnabled();
   if (!isEnabled) {
     aParams->SetBooleanValue(STATE_MIXED,false);
     aParams->SetCStringValue(STATE_ATTRIBUTE, "");
     return NS_OK;
   }
 
-  nsCOMPtr<nsIDOMElement>  elt;
+  nsCOMPtr<nsINode> container;
   nsresult rv =
-    aHTMLEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt));
+    aHTMLEditor->GetAbsolutelyPositionedSelectionContainer(
+                   getter_AddRefs(container));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoString outStateString;
-  if (elt)
+  if (container) {
     outStateString.AssignLiteral("absolute");
+  }
 
   aParams->SetBooleanValue(STATE_MIXED,false);
   aParams->SetCStringValue(STATE_ATTRIBUTE, NS_ConvertUTF16toUTF8(outStateString).get());
   return NS_OK;
 }
 
 nsresult
 nsAbsolutePositioningCommand::ToggleState(mozilla::HTMLEditor* aHTMLEditor)
 {
   if (NS_WARN_IF(!aHTMLEditor)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  nsCOMPtr<nsIDOMElement> elt;
+  nsCOMPtr<nsINode> container;
   nsresult rv =
-    aHTMLEditor->GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(elt));
+    aHTMLEditor->GetAbsolutelyPositionedSelectionContainer(
+                   getter_AddRefs(container));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return aHTMLEditor->AbsolutePositionSelection(!elt);
+  return aHTMLEditor->AbsolutePositionSelection(!container);
 }
 
 
 NS_IMETHODIMP
 nsDecreaseZIndexCommand::IsCommandEnabled(const char * aCommandName,
                                           nsISupports *refCon,
                                           bool *outCmdEnabled)
 {
@@ -1086,22 +1085,21 @@ nsDecreaseZIndexCommand::IsCommandEnable
   if (NS_WARN_IF(!editor)) {
     return NS_ERROR_FAILURE;
   }
   mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
 
-  htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled);
+  *outCmdEnabled = htmlEditor->AbsolutePositioningEnabled();
   if (!(*outCmdEnabled))
     return NS_OK;
 
-  nsCOMPtr<nsIDOMElement> positionedElement;
-  htmlEditor->GetPositionedElement(getter_AddRefs(positionedElement));
+  RefPtr<Element> positionedElement = htmlEditor->GetPositionedElement();
   *outCmdEnabled = false;
   if (!positionedElement) {
     return NS_OK;
   }
 
   int32_t z;
   nsresult rv = htmlEditor->GetElementZIndex(positionedElement, &z);
   if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -1157,22 +1155,21 @@ nsIncreaseZIndexCommand::IsCommandEnable
   if (NS_WARN_IF(!editor)) {
     return NS_ERROR_FAILURE;
   }
   mozilla::HTMLEditor* htmlEditor = editor->AsHTMLEditor();
   if (NS_WARN_IF(!htmlEditor)) {
     return NS_ERROR_FAILURE;
   }
 
-  htmlEditor->GetAbsolutePositioningEnabled(outCmdEnabled);
+  *outCmdEnabled = htmlEditor->AbsolutePositioningEnabled();
   if (!(*outCmdEnabled))
     return NS_OK;
 
-  nsCOMPtr<nsIDOMElement> positionedElement;
-  htmlEditor->GetPositionedElement(getter_AddRefs(positionedElement));
+  Element* positionedElement = htmlEditor->GetPositionedElement();
   *outCmdEnabled = (nullptr != positionedElement);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsIncreaseZIndexCommand::DoCommand(const char *aCommandName,
                                    nsISupports *refCon)
 {
@@ -1217,17 +1214,18 @@ nsRemoveStylesCommand::IsCommandEnabled(
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
   if (!editor) {
     *outCmdEnabled = false;
     return NS_OK;
   }
   mozilla::EditorBase* editorBase = editor->AsEditorBase();
   MOZ_ASSERT(editorBase);
   // test if we have any styles?
-  return editorBase->GetIsSelectionEditable(outCmdEnabled);
+  *outCmdEnabled = editorBase->IsSelectionEditable();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsRemoveStylesCommand::DoCommand(const char *aCommandName,
                                  nsISupports *refCon)
 {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
   if (!editor) {
@@ -1266,17 +1264,18 @@ nsIncreaseFontSizeCommand::IsCommandEnab
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
   if (!editor) {
     *outCmdEnabled = false;
     return NS_OK;
   }
   mozilla::EditorBase* editorBase = editor->AsEditorBase();
   MOZ_ASSERT(editorBase);
   // test if we are at max size?
-  return editorBase->GetIsSelectionEditable(outCmdEnabled);
+  *outCmdEnabled = editorBase->IsSelectionEditable();
+  return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsIncreaseFontSizeCommand::DoCommand(const char *aCommandName,
                                      nsISupports *refCon)
 {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
@@ -1316,17 +1315,18 @@ nsDecreaseFontSizeCommand::IsCommandEnab
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
   if (!editor) {
     *outCmdEnabled = false;
     return NS_OK;
   }
   mozilla::EditorBase* editorBase = editor->AsEditorBase();
   MOZ_ASSERT(editorBase);
   // test if we are at min size?
-  return editorBase->GetIsSelectionEditable(outCmdEnabled);
+  *outCmdEnabled = editorBase->IsSelectionEditable();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDecreaseFontSizeCommand::DoCommand(const char *aCommandName,
                                      nsISupports *refCon)
 {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
   if (!editor) {
@@ -1365,17 +1365,18 @@ nsInsertHTMLCommand::IsCommandEnabled(co
   NS_ENSURE_ARG_POINTER(outCmdEnabled);
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
   if (!editor) {
     *outCmdEnabled = false;
     return NS_OK;
   }
   mozilla::EditorBase* editorBase = editor->AsEditorBase();
   MOZ_ASSERT(editorBase);
-  return editorBase->GetIsSelectionEditable(outCmdEnabled);
+  *outCmdEnabled = editorBase->IsSelectionEditable();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsInsertHTMLCommand::DoCommand(const char *aCommandName, nsISupports *refCon)
 {
   // If nsInsertHTMLCommand is called with no parameters, it was probably called with
   // an empty string parameter ''. In this case, it should act the same as the delete command
   NS_ENSURE_ARG_POINTER(refCon);
@@ -1451,17 +1452,18 @@ nsInsertTagCommand::IsCommandEnabled(con
   NS_ENSURE_ARG_POINTER(outCmdEnabled);
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(refCon);
   if (!editor) {
     *outCmdEnabled = false;
     return NS_OK;
   }
   mozilla::EditorBase* editorBase = editor->AsEditorBase();
   MOZ_ASSERT(editorBase);
-  return editorBase->GetIsSelectionEditable(outCmdEnabled);
+  *outCmdEnabled = editorBase->IsSelectionEditable();
+  return NS_OK;
 }
 
 // corresponding STATE_ATTRIBUTE is: src (img) and href (a)
 NS_IMETHODIMP
 nsInsertTagCommand::DoCommand(const char *aCmdName, nsISupports *refCon)
 {
   NS_ENSURE_TRUE(mTagName == nsGkAtoms::hr, NS_ERROR_NOT_IMPLEMENTED);
 
--- a/editor/libeditor/EditorBase.cpp
+++ b/editor/libeditor/EditorBase.cpp
@@ -538,27 +538,53 @@ EditorBase::SetFlags(uint32_t aFlags)
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 EditorBase::GetIsSelectionEditable(bool* aIsSelectionEditable)
 {
   NS_ENSURE_ARG_POINTER(aIsSelectionEditable);
-
+  *aIsSelectionEditable = IsSelectionEditable();
+  return NS_OK;
+}
+
+bool
+EditorBase::IsSelectionEditable()
+{
   // get current selection
   RefPtr<Selection> selection = GetSelection();
-  NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
-  // XXX we just check that the anchor node is editable at the moment
-  //     we should check that all nodes in the selection are editable
-  nsCOMPtr<nsINode> anchorNode = selection->GetAnchorNode();
-  *aIsSelectionEditable = anchorNode && IsEditable(anchorNode);
-
-  return NS_OK;
+  if (NS_WARN_IF(!selection)) {
+    return false;
+  }
+
+  if (!mIsHTMLEditorClass) {
+    // XXX we just check that the anchor node is editable at the moment
+    //     we should check that all nodes in the selection are editable
+    nsCOMPtr<nsINode> anchorNode = selection->GetAnchorNode();
+    return anchorNode && IsEditable(anchorNode);
+  }
+
+  // Per the editing spec as of June 2012: we have to have a selection whose
+  // start and end nodes are editable, and which share an ancestor editing
+  // host.  (Bug 766387.)
+  bool isSelectionEditable = selection->RangeCount() &&
+                             selection->GetAnchorNode()->IsEditable() &&
+                             selection->GetFocusNode()->IsEditable();
+  if (!isSelectionEditable) {
+    return false;
+  }
+
+  nsINode* commonAncestor =
+    selection->GetAnchorFocusRange()->GetCommonAncestor();
+  while (commonAncestor && !commonAncestor->IsEditable()) {
+    commonAncestor = commonAncestor->GetParentNode();
+  }
+  // If there is no editable common ancestor, return false.
+  return !!commonAncestor;
 }
 
 NS_IMETHODIMP
 EditorBase::GetIsDocumentEditable(bool* aIsDocumentEditable)
 {
   NS_ENSURE_ARG_POINTER(aIsDocumentEditable);
   nsCOMPtr<nsIDocument> doc = GetDocument();
   *aIsDocumentEditable = doc && IsModifiable();
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -776,16 +776,24 @@ public:
         // Text nodes are considered to be editable by both typed of editors.
         return true;
       default:
         return false;
     }
   }
 
   /**
+   * Returns true if selection is in an editable element and both the range
+   * start and the range end are editable.  E.g., even if the selection range
+   * includes non-editable elements, returns true when one of common ancestors
+   * of the range start and the range end is editable.  Otherwise, false.
+   */
+  bool IsSelectionEditable();
+
+  /**
    * Returns true if aNode is a MozEditorBogus node.
    */
   bool IsMozEditorBogusNode(nsINode* aNode)
   {
     return aNode && aNode->IsElement() &&
            aNode->AsElement()->AttrValueIs(kNameSpaceID_None,
                kMOZEditorBogusNodeAttrAtom, kMOZEditorBogusNodeValue,
                eCaseMatters);
--- a/editor/libeditor/HTMLAbsPositionEditor.cpp
+++ b/editor/libeditor/HTMLAbsPositionEditor.cpp
@@ -75,49 +75,68 @@ HTMLEditor::AbsolutePositionSelection(bo
   }
 
   return rules->DidDoAction(selection, &ruleInfo, rv);
 }
 
 NS_IMETHODIMP
 HTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement** _retval)
 {
+  nsCOMPtr<nsINode> container;
+  nsresult rv =
+    GetAbsolutelyPositionedSelectionContainer(getter_AddRefs(container));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    *_retval = nullptr;
+    return rv;
+  }
+
+  nsCOMPtr<nsIDOMElement> domContainer = do_QueryInterface(container);
+  domContainer.forget(_retval);
+  return NS_OK;
+}
+
+nsresult
+HTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsINode** aContainer)
+{
+  MOZ_ASSERT(aContainer);
+
   nsAutoString positionStr;
   nsCOMPtr<nsINode> node = GetSelectionContainer();
-  nsCOMPtr<nsIDOMNode> resultNode;
+  nsCOMPtr<nsINode> resultNode;
 
   while (!resultNode && node && !node->IsHTMLElement(nsGkAtoms::html)) {
     nsresult rv =
       mCSSEditUtils->GetComputedProperty(*node, *nsGkAtoms::position,
                                          positionStr);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      *aContainer = nullptr;
+      return rv;
+    }
     if (positionStr.EqualsLiteral("absolute"))
-      resultNode = GetAsDOMNode(node);
+      resultNode = node;
     else {
       node = node->GetParentNode();
     }
   }
-
-  nsCOMPtr<nsIDOMElement> element = do_QueryInterface(resultNode);
-  element.forget(_retval);
+  resultNode.forget(aContainer);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLEditor::GetSelectionContainerAbsolutelyPositioned(
               bool* aIsSelectionContainerAbsolutelyPositioned)
 {
   *aIsSelectionContainerAbsolutelyPositioned = (mAbsolutelyPositionedObject != nullptr);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLEditor::GetAbsolutePositioningEnabled(bool* aIsEnabled)
 {
-  *aIsEnabled = mIsAbsolutelyPositioningEnabled;
+  *aIsEnabled = AbsolutePositioningEnabled();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLEditor::SetAbsolutePositioningEnabled(bool aIsEnabled)
 {
   mIsAbsolutelyPositioningEnabled = aIsEnabled;
   return NS_OK;
@@ -184,31 +203,38 @@ HTMLEditor::RelativeChangeZIndex(int32_t
   return rules->DidDoAction(selection, &ruleInfo, rv);
 }
 
 NS_IMETHODIMP
 HTMLEditor::GetElementZIndex(nsIDOMElement* aElement,
                              int32_t* aZindex)
 {
   nsCOMPtr<Element> element = do_QueryInterface(aElement);
-  NS_ENSURE_STATE(element || !aElement);
+  return GetElementZIndex(element, aZindex);
+}
+
+nsresult
+HTMLEditor::GetElementZIndex(Element* aElement,
+                             int32_t* aZindex)
+{
+  if (NS_WARN_IF(!aElement)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+
   nsAutoString zIndexStr;
   *aZindex = 0;
 
   nsresult rv =
-    mCSSEditUtils->GetSpecifiedProperty(*element, *nsGkAtoms::z_index,
+    mCSSEditUtils->GetSpecifiedProperty(*aElement, *nsGkAtoms::z_index,
                                         zIndexStr);
   NS_ENSURE_SUCCESS(rv, rv);
   if (zIndexStr.EqualsLiteral("auto")) {
     // we have to look at the positioned ancestors
     // cf. CSS 2 spec section 9.9.1
-    nsCOMPtr<nsIDOMNode> parentNode;
-    rv = aElement->GetParentNode(getter_AddRefs(parentNode));
-    NS_ENSURE_SUCCESS(rv, rv);
-    nsCOMPtr<nsINode> node = do_QueryInterface(parentNode);
+    nsCOMPtr<nsINode> node = aElement->GetParentNode();
     nsAutoString positionStr;
     while (node && zIndexStr.EqualsLiteral("auto") &&
            !node->IsHTMLElement(nsGkAtoms::body)) {
       rv = mCSSEditUtils->GetComputedProperty(*node, *nsGkAtoms::position,
                                               positionStr);
       NS_ENSURE_SUCCESS(rv, rv);
       if (positionStr.EqualsLiteral("absolute")) {
         // ah, we found one, what's its z-index ? If its z-index is auto,
@@ -592,17 +618,17 @@ HTMLEditor::SetElementPosition(Element& 
   mCSSEditUtils->SetCSSPropertyPixels(aElement, *nsGkAtoms::top, aY);
 }
 
 // self-explanatory
 NS_IMETHODIMP
 HTMLEditor::GetPositionedElement(nsIDOMElement** aReturn)
 {
   nsCOMPtr<nsIDOMElement> ret =
-    static_cast<nsIDOMElement*>(GetAsDOMNode(mAbsolutelyPositionedObject));
+    static_cast<nsIDOMElement*>(GetAsDOMNode(GetPositionedElement()));
   ret.forget(aReturn);
   return NS_OK;
 }
 
 nsresult
 HTMLEditor::CheckPositionedElementBGandFG(nsIDOMElement* aElement,
                                           nsAString& aReturn)
 {
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -3350,46 +3350,16 @@ HTMLEditor::IsModifiableNode(nsIDOMNode*
 }
 
 bool
 HTMLEditor::IsModifiableNode(nsINode* aNode)
 {
   return !aNode || aNode->IsEditable();
 }
 
-NS_IMETHODIMP
-HTMLEditor::GetIsSelectionEditable(bool* aIsSelectionEditable)
-{
-  MOZ_ASSERT(aIsSelectionEditable);
-
-  RefPtr<Selection> selection = GetSelection();
-  NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
-
-  // Per the editing spec as of June 2012: we have to have a selection whose
-  // start and end nodes are editable, and which share an ancestor editing
-  // host.  (Bug 766387.)
-  *aIsSelectionEditable = selection->RangeCount() &&
-                          selection->GetAnchorNode()->IsEditable() &&
-                          selection->GetFocusNode()->IsEditable();
-
-  if (*aIsSelectionEditable) {
-    nsINode* commonAncestor =
-      selection->GetAnchorFocusRange()->GetCommonAncestor();
-    while (commonAncestor && !commonAncestor->IsEditable()) {
-      commonAncestor = commonAncestor->GetParentNode();
-    }
-    if (!commonAncestor) {
-      // No editable common ancestor
-      *aIsSelectionEditable = false;
-    }
-  }
-
-  return NS_OK;
-}
-
 static nsresult
 SetSelectionAroundHeadChildren(Selection* aSelection,
                                nsCOMPtr<nsIDocument>& aDocument)
 {
   MOZ_ASSERT(aDocument);
 
   // Set selection around <head> node
   dom::Element* headNode = aDocument->GetHeadElement();
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -212,16 +212,28 @@ public:
   NS_IMETHOD PreDestroy(bool aDestroyingFrames) override;
 
   /**
    * @param aElement        Must not be null.
    */
   static bool NodeIsBlockStatic(const nsINode* aElement);
   static nsresult NodeIsBlockStatic(nsIDOMNode *aNode, bool *aIsBlock);
 
+  // non-virtual methods of interface methods
+  bool AbsolutePositioningEnabled() const
+  {
+    return mIsAbsolutelyPositioningEnabled;
+  }
+  nsresult GetAbsolutelyPositionedSelectionContainer(nsINode** aContainer);
+  Element* GetPositionedElement() const
+  {
+    return mAbsolutelyPositionedObject;
+  }
+  nsresult GetElementZIndex(Element* aElement, int32_t* aZindex);
+
 protected:
   virtual ~HTMLEditor();
 
   using EditorBase::IsBlockNode;
   virtual bool IsBlockNode(nsINode *aNode) override;
 
 public:
   // XXX Why don't we move following methods above for grouping by the origins?
@@ -283,18 +295,16 @@ public:
                       uint32_t aLength);
   virtual nsresult InsertTextImpl(const nsAString& aStringToInsert,
                                   nsCOMPtr<nsINode>* aInOutNode,
                                   int32_t* aInOutOffset,
                                   nsIDocument* aDoc) override;
   NS_IMETHOD_(bool) IsModifiableNode(nsIDOMNode* aNode) override;
   virtual bool IsModifiableNode(nsINode* aNode) override;
 
-  NS_IMETHOD GetIsSelectionEditable(bool* aIsSelectionEditable) override;
-
   NS_IMETHOD SelectAll() override;
 
   NS_IMETHOD GetRootElement(nsIDOMElement** aRootElement) override;
 
   // nsICSSLoaderObserver
   NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet,
                               bool aWasAlternate, nsresult aStatus) override;