Bug 1460509 - part 63: Make HTMLEditRules::RemovePartOfBlock() 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 17:13:04 +0900
changeset 798781 841f2930f0e48f38bd89989306314e943f653b51
parent 798780 2e022b1173c768f4d7c1378793e8cbdb72f63f17
child 798782 fd141fa5b3cb8ef9c821b0daac382a3770278797
push id110840
push usermasayuki@d-toybox.com
push dateWed, 23 May 2018 13:41:58 +0000
reviewersm_kato
bugs1460509
milestone62.0a1
Bug 1460509 - part 63: Make HTMLEditRules::RemovePartOfBlock() return NS_ERROR_EDITOR_DESTROYED if it causes destroying the editor r?m_kato And this patch renames it to SplitRangeOffFromBlockAndRemoveMiddleContainer() for making the name explain what it does. MozReview-Commit-ID: 546dnCeoGOV
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditRules.h
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -5372,40 +5372,42 @@ HTMLEditRules::WillOutdent(bool* aCancel
       SelectionRef().Collapse(atRememberedRightBQ, error);
       NS_WARNING_ASSERTION(!error.Failed(),
         "Failed to collapse selection after the right <blockquote>");
     }
   }
   return NS_OK;
 }
 
-/**
- * RemovePartOfBlock() splits aBlock and move aStartChild to aEndChild out of
- * aBlock.
- */
-nsresult
-HTMLEditRules::RemovePartOfBlock(Element& aBlock,
-                                 nsIContent& aStartChild,
-                                 nsIContent& aEndChild)
+SplitRangeOffFromNodeResult
+HTMLEditRules::SplitRangeOffFromBlockAndRemoveMiddleContainer(
+                 Element& aBlockElement,
+                 nsIContent& aStartOfRange,
+                 nsIContent& aEndOfRange)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   SplitRangeOffFromNodeResult splitResult =
-    SplitRangeOffFromBlock(aBlock, aStartChild, aEndChild);
+    SplitRangeOffFromBlock(aBlockElement, aStartOfRange, aEndOfRange);
   if (NS_WARN_IF(splitResult.Rv() == NS_ERROR_EDITOR_DESTROYED)) {
-    return NS_ERROR_EDITOR_DESTROYED;
+    return splitResult;
   }
   NS_WARNING_ASSERTION(splitResult.Succeeded(),
     "Failed to split the range off from the block element");
-  // Get rid of part of blockquote we are outdenting
-  nsresult rv = HTMLEditorRef().RemoveBlockContainerWithTransaction(aBlock);
+  nsresult rv =
+    HTMLEditorRef().RemoveBlockContainerWithTransaction(aBlockElement);
+  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());
 }
 
 SplitRangeOffFromNodeResult
 HTMLEditRules::SplitRangeOffFromBlock(Element& aBlockElement,
                                       nsIContent& aStartOfMiddleElement,
                                       nsIContent& aEndOfMiddleElement)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
@@ -8445,19 +8447,21 @@ HTMLEditRules::RemoveBlockStyle(nsTArray
   // inline things...
   nsCOMPtr<Element> curBlock;
   nsCOMPtr<nsIContent> firstNode, lastNode;
   for (auto& curNode : aNodeArray) {
     // If curNode is an <address>, <p>, <hn>, or <pre>, remove it.
     if (HTMLEditUtils::IsFormatNode(curNode)) {
       // Process any partial progress saved
       if (curBlock) {
-        nsresult rv = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          return rv;
+        SplitRangeOffFromNodeResult removeMiddleContainerResult =
+          SplitRangeOffFromBlockAndRemoveMiddleContainer(*curBlock,
+                                                         *firstNode, *lastNode);
+        if (NS_WARN_IF(removeMiddleContainerResult.Failed())) {
+          return removeMiddleContainerResult.Rv();
         }
         firstNode = lastNode = curBlock = nullptr;
       }
       if (!HTMLEditorRef().IsEditable(curNode)) {
         continue;
       }
       // Remove current block
       nsresult rv =
@@ -8478,19 +8482,21 @@ HTMLEditRules::RemoveBlockStyle(nsTArray
                                      nsGkAtoms::tbody,
                                      nsGkAtoms::td,
                                      nsGkAtoms::li,
                                      nsGkAtoms::blockquote,
                                      nsGkAtoms::div) ||
         HTMLEditUtils::IsList(curNode)) {
       // Process any partial progress saved
       if (curBlock) {
-        nsresult rv = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          return rv;
+        SplitRangeOffFromNodeResult removeMiddleContainerResult =
+          SplitRangeOffFromBlockAndRemoveMiddleContainer(*curBlock,
+                                                         *firstNode, *lastNode);
+        if (NS_WARN_IF(removeMiddleContainerResult.Failed())) {
+          return removeMiddleContainerResult.Rv();
         }
         firstNode = lastNode = curBlock = nullptr;
       }
       if (!HTMLEditorRef().IsEditable(curNode)) {
         continue;
       }
       // Recursion time
       nsTArray<OwningNonNull<nsINode>> childArray;
@@ -8508,19 +8514,21 @@ HTMLEditRules::RemoveBlockStyle(nsTArray
         if (EditorUtils::IsDescendantOf(*curNode, *curBlock)) {
           // Then we don't need to do anything different for this node
           lastNode = curNode->AsContent();
           continue;
         }
         // Otherwise, we have progressed beyond end of curBlock, so let's
         // handle it now.  We need to remove the portion of curBlock that
         // contains [firstNode - lastNode].
-        nsresult rv = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          return rv;
+        SplitRangeOffFromNodeResult removeMiddleContainerResult =
+          SplitRangeOffFromBlockAndRemoveMiddleContainer(*curBlock,
+                                                         *firstNode, *lastNode);
+        if (NS_WARN_IF(removeMiddleContainerResult.Failed())) {
+          return removeMiddleContainerResult.Rv();
         }
         firstNode = lastNode = curBlock = nullptr;
         // Fall out and handle curNode
       }
       curBlock = HTMLEditorRef().GetBlockNodeParent(curNode);
       if (!curBlock || !HTMLEditUtils::IsFormatNode(curBlock) ||
           !HTMLEditorRef().IsEditable(curBlock)) {
         // Not a block kind that we care about.
@@ -8529,29 +8537,33 @@ HTMLEditRules::RemoveBlockStyle(nsTArray
         firstNode = lastNode = curNode->AsContent();
       }
       continue;
     }
 
     if (curBlock) {
       // Some node that is already sans block style.  Skip over it and process
       // any partial progress saved.
-      nsresult rv = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        return rv;
+      SplitRangeOffFromNodeResult removeMiddleContainerResult =
+        SplitRangeOffFromBlockAndRemoveMiddleContainer(*curBlock,
+                                                       *firstNode, *lastNode);
+      if (NS_WARN_IF(removeMiddleContainerResult.Failed())) {
+        return removeMiddleContainerResult.Rv();
       }
       firstNode = lastNode = curBlock = nullptr;
       continue;
     }
   }
   // Process any partial progress saved
   if (curBlock) {
-    nsresult rv = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
+    SplitRangeOffFromNodeResult removeMiddleContainerResult =
+      SplitRangeOffFromBlockAndRemoveMiddleContainer(*curBlock,
+                                                     *firstNode, *lastNode);
+    if (NS_WARN_IF(removeMiddleContainerResult.Failed())) {
+      return removeMiddleContainerResult.Rv();
     }
     firstNode = lastNode = curBlock = nullptr;
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::ApplyBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray,
--- a/editor/libeditor/HTMLEditRules.h
+++ b/editor/libeditor/HTMLEditRules.h
@@ -524,18 +524,37 @@ protected:
 
   /**
    * Called after handling edit action.  This may adjust Selection, remove
    * unnecessary empty nodes, create <br> elements if needed, etc.
    */
   MOZ_MUST_USE nsresult
   AfterEditInner(EditAction action, nsIEditor::EDirection aDirection);
 
-  nsresult RemovePartOfBlock(Element& aBlock, nsIContent& aStartChild,
-                             nsIContent& aEndChild);
+  /**
+   * SplitRangeOffFromBlockAndRemoveMiddleContainer() splits the nodes
+   * between aStartOfRange and aEndOfRange, then, removes the middle element
+   * and moves its content to where the middle element was.
+   *
+   * @param aBlockElement           The node which will be split.
+   * @param aStartOfRange           The first node which will be unwrapped
+   *                                from aBlockElement.
+   * @param aEndOfRange             The last node which will be unwrapped from
+   *                                aBlockElement.
+   * @return                        The left content is new created left
+   *                                element of aBlockElement.
+   *                                The right content is split element,
+   *                                i.e., must be aBlockElement.
+   *                                The middle content is nullptr since
+   *                                removing it is the job of this method.
+   */
+  MOZ_MUST_USE SplitRangeOffFromNodeResult
+  SplitRangeOffFromBlockAndRemoveMiddleContainer(Element& aBlockElement,
+                                                 nsIContent& aStartOfRange,
+                                                 nsIContent& aEndOfRange);
 
   /**
    * SplitRangeOffFromBlock() splits aBlock at two points, before aStartChild
    * and after aEndChild.  If they are very start or very end of aBlcok, this
    * won't create empty block.
    *
    * @param aBlockElement           A block element which will be split.
    * @param aStartOfMiddleElement   Start node of middle block element.