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
--- 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.