Bug 1460509 - part 79: Make HTMLEditRules::TryToJoinBlocksWithTransaction() return NS_ERROR_EDITOR_DESTROYED if it causes destroying the editor r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 18 May 2018 00:22:43 +0900
changeset 796825 3f48ab31b2246eb7fb85fee7c4bd43e1a5b40a6b
parent 796824 33fd00f9fa4b65703a6cfa11ca6721c5ea8c7ef4
child 796826 270fa03173f0c597ed7f2b27a96ba2d80c3bed36
push id110360
push usermasayuki@d-toybox.com
push dateFri, 18 May 2018 10:24:57 +0000
reviewersm_kato
bugs1460509
milestone62.0a1
Bug 1460509 - part 79: Make HTMLEditRules::TryToJoinBlocksWithTransaction() return NS_ERROR_EDITOR_DESTROYED if it causes destroying the editor r?m_kato MozReview-Commit-ID: BdoIrAYckNe
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditRules.h
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -3423,28 +3423,34 @@ HTMLEditRules::TryToJoinBlocksWithTransa
     // just destroys non-visible ws at boundaries we will be joining.
     DebugOnly<bool> advanced = atRightBlockChild.AdvanceOffset();
     NS_WARNING_ASSERTION(advanced,
       "Failed to advance offset to after child of rightBlock, "
       "leftBlock is a descendant of the child");
     nsresult rv = WSRunObject::ScrubBlockBoundary(&HTMLEditorRef(),
                                                   WSRunObject::kBlockEnd,
                                                   leftBlock);
+    if (NS_WARN_IF(!CanHandleEditAction())) {
+      return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+    }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return EditActionIgnored(rv);
     }
 
     {
       // We can't just track rightBlock because it's an Element.
       AutoTrackDOMPoint tracker(HTMLEditorRef().mRangeUpdater,
                                 &atRightBlockChild);
       rv = WSRunObject::ScrubBlockBoundary(&HTMLEditorRef(),
                                            WSRunObject::kAfterBlock,
                                            atRightBlockChild.GetContainer(),
                                            atRightBlockChild.Offset());
+      if (NS_WARN_IF(!CanHandleEditAction())) {
+        return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+      }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return EditActionIgnored(rv);
       }
 
       // XXX AutoTrackDOMPoint instance, tracker, hasn't been destroyed here.
       //     Do we really need to do update rightBlock here??
       MOZ_ASSERT(rightBlock == atRightBlockChild.GetContainer());
       if (atRightBlockChild.GetContainerAsElement()) {
@@ -3490,45 +3496,58 @@ HTMLEditRules::TryToJoinBlocksWithTransa
         "Failed to move contents of the right block to the left block");
       if (retMoveBlock.Handled()) {
         ret.MarkAsHandled();
       }
       // Now, all children of rightBlock were moved to leftBlock.  So,
       // atRightBlockChild is now invalid.
       atRightBlockChild.Clear();
     }
-    if (brNode &&
-        NS_SUCCEEDED(HTMLEditorRef().DeleteNodeWithTransaction(*brNode))) {
-      ret.MarkAsHandled();
+    if (brNode) {
+      nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(*brNode);
+      if (NS_WARN_IF(!CanHandleEditAction())) {
+        return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+      }
+      if (NS_SUCCEEDED(rv)) {
+        ret.MarkAsHandled();
+      } else {
+        NS_WARNING("Failed to remove the <br> element");
+      }
     }
     return ret;
   }
 
   MOZ_DIAGNOSTIC_ASSERT(!atRightBlockChild.IsSet());
 
   // Offset below is where you find yourself in leftBlock when you traverse
   // upwards from rightBlock
   EditorDOMPoint leftBlockChild;
   if (EditorUtils::IsDescendantOf(*rightBlock, *leftBlock, &leftBlockChild)) {
     // Tricky case.  Right block is inside left block.  Do ws adjustment.  This
     // just destroys non-visible ws at boundaries we will be joining.
     nsresult rv = WSRunObject::ScrubBlockBoundary(&HTMLEditorRef(),
                                                   WSRunObject::kBlockStart,
                                                   rightBlock);
+    if (NS_WARN_IF(!CanHandleEditAction())) {
+      return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+    }
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return EditActionIgnored(rv);
     }
 
     {
       // We can't just track leftBlock because it's an Element, so track
       // something else.
       AutoTrackDOMPoint tracker(HTMLEditorRef().mRangeUpdater, &leftBlockChild);
       rv = WSRunObject::ScrubBlockBoundary(&HTMLEditorRef(),
                                            WSRunObject::kBeforeBlock,
                                            leftBlock, leftBlockChild.Offset());
+      if (NS_WARN_IF(!CanHandleEditAction())) {
+        return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+      }
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return EditActionIgnored(rv);
       }
       // XXX AutoTrackDOMPoint instance, tracker, hasn't been destroyed here.
       //     Do we really need to do update rightBlock here??
       MOZ_DIAGNOSTIC_ASSERT(leftBlock == leftBlockChild.GetContainer());
       if (leftBlockChild.GetContainerAsElement()) {
         leftBlock = leftBlockChild.GetContainerAsElement();
@@ -3595,16 +3614,19 @@ HTMLEditRules::TryToJoinBlocksWithTransa
         nsCOMPtr<nsINode> previousContentParent =
           previousContent.GetContainer();
         int32_t previousContentOffset = previousContent.Offset();
         rv = HTMLEditorRef().SplitStyleAbovePoint(
                                address_of(previousContentParent),
                                &previousContentOffset,
                                nullptr, nullptr, nullptr,
                                getter_AddRefs(splittedPreviousContent));
+        if (NS_WARN_IF(!CanHandleEditAction())) {
+          return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+        }
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return EditActionIgnored(rv);
         }
 
         if (splittedPreviousContent) {
           previousContent.Set(splittedPreviousContent);
         } else {
           previousContent.Set(previousContentParent, previousContentOffset);
@@ -3616,34 +3638,44 @@ HTMLEditRules::TryToJoinBlocksWithTransa
       }
 
       ret |= MoveBlock(*previousContent.GetContainerAsElement(), *rightBlock,
                        previousContent.Offset(), 0);
       if (NS_WARN_IF(ret.Failed())) {
         return ret;
       }
     }
-    if (brNode &&
-        NS_SUCCEEDED(HTMLEditorRef().DeleteNodeWithTransaction(*brNode))) {
-      ret.MarkAsHandled();
+    if (brNode) {
+      nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(*brNode);
+      if (NS_WARN_IF(!CanHandleEditAction())) {
+        return ret.SetResult(NS_ERROR_EDITOR_DESTROYED);
+      }
+      if (NS_SUCCEEDED(rv)) {
+        ret.MarkAsHandled();
+      } else {
+        NS_WARNING("Failed to remove the <br> element");
+      }
     }
     return ret;
   }
 
   MOZ_DIAGNOSTIC_ASSERT(!atRightBlockChild.IsSet());
   MOZ_DIAGNOSTIC_ASSERT(!leftBlockChild.IsSet());
 
   // Normal case.  Blocks are siblings, or at least close enough.  An example
   // of the latter is <p>paragraph</p><ul><li>one<li>two<li>three</ul>.  The
   // first li and the p are not true siblings, but we still want to join them
   // if you backspace from li into p.
 
   // Adjust whitespace at block boundaries
   nsresult rv =
     WSRunObject::PrepareToJoinBlocks(&HTMLEditorRef(), leftBlock, rightBlock);
+  if (NS_WARN_IF(!CanHandleEditAction())) {
+    return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+  }
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return EditActionIgnored(rv);
   }
   // Do br adjustment.
   nsCOMPtr<Element> brNode =
     CheckForInvisibleBR(*leftBlock, BRLocation::blockEnd);
   EditActionResult ret(NS_OK);
   if (mergeLists || leftBlock->NodeInfo()->NameAtom() ==
@@ -3667,16 +3699,19 @@ HTMLEditRules::TryToJoinBlocksWithTransa
     // Nodes are dissimilar types.
     ret |= MoveBlock(*leftBlock, *rightBlock, -1, 0);
     if (NS_WARN_IF(ret.Failed())) {
       return ret;
     }
   }
   if (brNode) {
     rv = HTMLEditorRef().DeleteNodeWithTransaction(*brNode);
+    if (NS_WARN_IF(!CanHandleEditAction())) {
+      return ret.SetResult(NS_ERROR_EDITOR_DESTROYED);
+    }
     // XXX In other top level if blocks, the result of
     //     DeleteNodeWithTransaction() is ignored.  Why does only this result
     //     is respected?
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return ret.SetResult(rv);
     }
     ret.MarkAsHandled();
   }
--- a/editor/libeditor/HTMLEditRules.h
+++ b/editor/libeditor/HTMLEditRules.h
@@ -282,18 +282,19 @@ protected:
    * @return            Sets canceled to true if the operation should do
    *                    nothing anymore even if this doesn't join the blocks.
    *                    Sets handled to true if this actually handles the
    *                    request.  Note that this may set it to true even if this
    *                    does not join the block.  E.g., if the blocks shouldn't
    *                    be joined or it's impossible to join them but it's not
    *                    unexpected case, this returns true with this.
    */
-  EditActionResult TryToJoinBlocksWithTransaction(nsIContent& aLeftNode,
-                                                  nsIContent& aRightNode);
+  MOZ_MUST_USE EditActionResult
+  TryToJoinBlocksWithTransaction(nsIContent& aLeftNode,
+                                 nsIContent& aRightNode);
 
   /**
    * MoveBlock() moves the content from aRightBlock starting from aRightOffset
    * into aLeftBlock at aLeftOffset. Note that the "block" can be inline nodes
    * between <br>s, or between blocks, etc.  DTD containment rules are followed
    * throughout.
    *
    * @return            Sets handled to true if this actually joins the nodes.