Bug 1460509 - part 62: Make HTMLEditRules::OutdentPartOfBlock() return NS_ERROR_EDITOR_DESTROYED if it causes destroying the editor r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 17 May 2018 16:53:18 +0900
changeset 798780 2e022b1173c768f4d7c1378793e8cbdb72f63f17
parent 798779 628d6f26bd9f2054da351592bf1dcf1e0d69e17e
child 798781 841f2930f0e48f38bd89989306314e943f653b51
push id110840
push usermasayuki@d-toybox.com
push dateWed, 23 May 2018 13:41:58 +0000
reviewersm_kato
bugs1460509
milestone62.0a1
Bug 1460509 - part 62: Make HTMLEditRules::OutdentPartOfBlock() return NS_ERROR_EDITOR_DESTROYED if it causes destroying the editor r?m_kato MozReview-Commit-ID: 7IkBuQ6Tr3P
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditRules.h
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -5115,21 +5115,24 @@ HTMLEditRules::WillOutdent(bool* aCancel
         continue;
       }
 
       // Is it a blockquote?
       if (curNode->IsHTMLElement(nsGkAtoms::blockquote)) {
         // If it is a blockquote, remove it.  So we need to finish up dealng
         // with any curBlockQuote first.
         if (curBlockQuote) {
-          rv = OutdentPartOfBlock(*curBlockQuote, *firstBQChild, *lastBQChild,
-                                  curBlockQuoteIsIndentedWithCSS,
-                                  getter_AddRefs(rememberedLeftBQ),
-                                  getter_AddRefs(rememberedRightBQ));
-          NS_ENSURE_SUCCESS(rv, rv);
+          SplitRangeOffFromNodeResult outdentResult =
+            OutdentPartOfBlock(*curBlockQuote, *firstBQChild, *lastBQChild,
+                               curBlockQuoteIsIndentedWithCSS);
+          if (NS_WARN_IF(outdentResult.Failed())) {
+            return outdentResult.Rv();
+          }
+          rememberedLeftBQ = outdentResult.GetLeftContent();
+          rememberedRightBQ = outdentResult.GetRightContent();
           curBlockQuote = nullptr;
           firstBQChild = nullptr;
           lastBQChild = nullptr;
           curBlockQuoteIsIndentedWithCSS = false;
         }
         rv = HTMLEditorRef().RemoveBlockContainerWithTransaction(
                                *curNode->AsElement());
         if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -5156,21 +5159,24 @@ HTMLEditRules::WillOutdent(bool* aCancel
         }
       }
       // Is it a list item?
       if (HTMLEditUtils::IsListItem(curNode)) {
         // If it is a list item, that means we are not outdenting whole list.
         // So we need to finish up dealing with any curBlockQuote, and then pop
         // this list item.
         if (curBlockQuote) {
-          rv = OutdentPartOfBlock(*curBlockQuote, *firstBQChild, *lastBQChild,
-                                  curBlockQuoteIsIndentedWithCSS,
-                                  getter_AddRefs(rememberedLeftBQ),
-                                  getter_AddRefs(rememberedRightBQ));
-          NS_ENSURE_SUCCESS(rv, rv);
+          SplitRangeOffFromNodeResult outdentResult =
+            OutdentPartOfBlock(*curBlockQuote, *firstBQChild, *lastBQChild,
+                               curBlockQuoteIsIndentedWithCSS);
+          if (NS_WARN_IF(outdentResult.Failed())) {
+            return outdentResult.Rv();
+          }
+          rememberedLeftBQ = outdentResult.GetLeftContent();
+          rememberedRightBQ = outdentResult.GetRightContent();
           curBlockQuote = nullptr;
           firstBQChild = nullptr;
           lastBQChild = nullptr;
           curBlockQuoteIsIndentedWithCSS = false;
         }
         rv = PopListItem(*curNode->AsContent());
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
@@ -5183,21 +5189,24 @@ HTMLEditRules::WillOutdent(bool* aCancel
         if (EditorUtils::IsDescendantOf(*curNode, *curBlockQuote)) {
           lastBQChild = curNode;
           // Then we don't need to do anything different for this node
           continue;
         }
         // Otherwise, we have progressed beyond end of curBlockQuote, so
         // let's handle it now.  We need to remove the portion of
         // curBlockQuote that contains [firstBQChild - lastBQChild].
-        rv = OutdentPartOfBlock(*curBlockQuote, *firstBQChild, *lastBQChild,
-                                curBlockQuoteIsIndentedWithCSS,
-                                getter_AddRefs(rememberedLeftBQ),
-                                getter_AddRefs(rememberedRightBQ));
-        NS_ENSURE_SUCCESS(rv, rv);
+        SplitRangeOffFromNodeResult outdentResult =
+          OutdentPartOfBlock(*curBlockQuote, *firstBQChild, *lastBQChild,
+                             curBlockQuoteIsIndentedWithCSS);
+        if (NS_WARN_IF(outdentResult.Failed())) {
+          return outdentResult.Rv();
+        }
+        rememberedLeftBQ = outdentResult.GetLeftContent();
+        rememberedRightBQ = outdentResult.GetRightContent();
         curBlockQuote = nullptr;
         firstBQChild = nullptr;
         lastBQChild = nullptr;
         curBlockQuoteIsIndentedWithCSS = false;
         // Fall out and handle curNode
       }
 
       // Are we inside a blockquote?
@@ -5300,21 +5309,24 @@ HTMLEditRules::WillOutdent(bool* aCancel
             NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
               "Failed to decrease indentation");
           }
         }
       }
     }
     if (curBlockQuote) {
       // We have a blockquote we haven't finished handling
-      rv = OutdentPartOfBlock(*curBlockQuote, *firstBQChild, *lastBQChild,
-                              curBlockQuoteIsIndentedWithCSS,
-                              getter_AddRefs(rememberedLeftBQ),
-                              getter_AddRefs(rememberedRightBQ));
-      NS_ENSURE_SUCCESS(rv, rv);
+      SplitRangeOffFromNodeResult outdentResult =
+        OutdentPartOfBlock(*curBlockQuote, *firstBQChild, *lastBQChild,
+                           curBlockQuoteIsIndentedWithCSS);
+      if (NS_WARN_IF(outdentResult.Failed())) {
+        return outdentResult.Rv();
+      }
+      rememberedLeftBQ = outdentResult.GetLeftContent();
+      rememberedRightBQ = outdentResult.GetRightContent();
     }
   }
   // Make sure selection didn't stick to last piece of content in old bq (only
   // a problem for collapsed selections)
   if (!rememberedLeftBQ && !rememberedRightBQ) {
     return NS_OK;
   }
 
@@ -5427,64 +5439,59 @@ HTMLEditRules::SplitRangeOffFromBlock(El
     return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_DESTROYED);
   }
   NS_WARNING_ASSERTION(splitAtEndResult.Succeeded(),
     "Failed to split aBlockElement at after end");
 
   return SplitRangeOffFromNodeResult(splitAtStartResult, splitAtEndResult);
 }
 
-nsresult
-HTMLEditRules::OutdentPartOfBlock(Element& aBlock,
-                                  nsIContent& aStartChild,
-                                  nsIContent& aEndChild,
-                                  bool aIsBlockIndentedWithCSS,
-                                  nsIContent** aOutLeftNode,
-                                  nsIContent** aOutRightNode)
-{
-  MOZ_ASSERT(IsEditorDataAvailable());
-  MOZ_ASSERT(aOutLeftNode && aOutRightNode);
+SplitRangeOffFromNodeResult
+HTMLEditRules::OutdentPartOfBlock(Element& aBlockElement,
+                                  nsIContent& aStartOfOutdent,
+                                  nsIContent& aEndOfOutdent,
+                                  bool aIsBlockIndentedWithCSS)
+{
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   SplitRangeOffFromNodeResult splitResult =
-    SplitRangeOffFromBlock(aBlock, aStartChild, aEndChild);
+    SplitRangeOffFromBlock(aBlockElement, aStartOfOutdent, aEndOfOutdent);
   if (NS_WARN_IF(splitResult.Rv() == NS_ERROR_EDITOR_DESTROYED)) {
-    return NS_ERROR_EDITOR_DESTROYED;
-  }
-
-  if (aOutLeftNode) {
-    NS_IF_ADDREF(*aOutLeftNode = splitResult.GetLeftContent());
-  }
-  if (aOutRightNode) {
-    NS_IF_ADDREF(*aOutRightNode = splitResult.GetRightContent());
+    return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_DESTROYED);
   }
 
   if (NS_WARN_IF(!splitResult.GetMiddleContentAsElement())) {
-    return NS_ERROR_FAILURE;
+    return SplitRangeOffFromNodeResult(NS_ERROR_FAILURE);
   }
 
   if (!aIsBlockIndentedWithCSS) {
     nsresult rv =
       HTMLEditorRef().RemoveBlockContainerWithTransaction(
                         *splitResult.GetMiddleContentAsElement());
+    if (NS_WARN_IF(!CanHandleEditAction())) {
+      return SplitRangeOffFromNodeResult(NS_ERROR_EDITOR_DESTROYED);
+    }
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-    return NS_OK;
+      return SplitRangeOffFromNodeResult(rv);
+    }
+    return SplitRangeOffFromNodeResult(splitResult.GetLeftContent(),
+                                       nullptr,
+                                       splitResult.GetRightContent());
   }
 
   if (splitResult.GetMiddleContentAsElement()) {
     nsresult rv =
       DecreaseMarginToOutdent(*splitResult.GetMiddleContentAsElement());
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-    return NS_OK;
-  }
-
-  return NS_OK;
+      return SplitRangeOffFromNodeResult(rv);
+    }
+    return splitResult;
+  }
+
+  return splitResult;
 }
 
 CreateElementResult
 HTMLEditRules::ConvertListType(Element& aListElement,
                                nsAtom& aNewListTag,
                                nsAtom& aNewListItemTag)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
--- a/editor/libeditor/HTMLEditRules.h
+++ b/editor/libeditor/HTMLEditRules.h
@@ -541,22 +541,43 @@ protected:
    * @param aStartOfMiddleElement   Start node of middle block element.
    * @param aEndOfMiddleElement     End node of middle block element.
    */
   MOZ_MUST_USE SplitRangeOffFromNodeResult
   SplitRangeOffFromBlock(Element& aBlockElement,
                          nsIContent& aStartOfMiddleElement,
                          nsIContent& aEndOfMiddleElement);
 
-  nsresult OutdentPartOfBlock(Element& aBlock,
-                              nsIContent& aStartChild,
-                              nsIContent& aEndChild,
-                              bool aIsBlockIndentedWithCSS,
-                              nsIContent** aOutLeftNode,
-                              nsIContent** aOutRightNode);
+  /**
+   * OutdentPartOfBlock() outdents the nodes between aStartOfOutdent and
+   * aEndOfOutdent.  This splits the range off from aBlockElement first.
+   * Then, removes the middle element if aIsBlockIndentedWithCSS is false.
+   * Otherwise, decreases the margin of the middle element.
+   *
+   * @param aBlockElement           A block element which includes both
+   *                                aStartOfOutdent and aEndOfOutdent.
+   * @param aStartOfOutdent         First node which is descendant of
+   *                                aBlockElement will be outdented.
+   * @param aEndOfOutdent           Last node which is descandant of
+   *                                aBlockElement will be outdented.
+   * @param aIsBlockIndentedWithCSS true if aBlockElement is indented with
+   *                                CSS margin property.
+   *                                false if aBlockElement is <blockquote>
+   *                                or something.
+   * @return                        The left content is new created element
+   *                                splitting before aStartOfOutdent.
+   *                                The right content is existing element.
+   *                                The middle content is outdented element
+   *                                if aIsBlockIndentedWithCSS is true.
+   *                                Otherwise, nullptr.
+   */
+  MOZ_MUST_USE SplitRangeOffFromNodeResult
+  OutdentPartOfBlock(Element& aBlockElement,
+                     nsIContent& aStartOfOutdent, nsIContent& aEndOutdent,
+                     bool aIsBlockIndentedWithCSS);
 
   /**
    * ConvertListType() replaces child list items of aListElement with
    * new list item element whose tag name is aNewListItemTag.
    * Note that if there are other list elements as children of aListElement,
    * this calls itself recursively even though it's invalid structure.
    *
    * @param aListElement        The list element whose list items will be