Bug 1460509 - part 41: Make HTMLEditRules::ReturnInHeader() return NS_ERROR_EDITOR_DESTROYED if it causes destroying the editor r?m_kato
MozReview-Commit-ID: r03QSPXsZ2
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -1942,18 +1942,24 @@ HTMLEditRules::WillInsertBreak(bool* aCa
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"Failed to insert break into list item");
*aHandled = true;
return NS_OK;
}
if (HTMLEditUtils::IsHeader(*blockParent)) {
// Headers: close (or split) header
- ReturnInHeader(*blockParent, *atStartOfSelection.GetContainer(),
- atStartOfSelection.Offset());
+ nsresult rv =
+ ReturnInHeader(*blockParent, *atStartOfSelection.GetContainer(),
+ atStartOfSelection.Offset());
+ if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
+ return NS_ERROR_EDITOR_DESTROYED;
+ }
+ NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+ "Failed to handle insertParagraph in the heading element");
*aHandled = true;
return NS_OK;
}
// XXX Ideally, we should take same behavior with both <p> container and
// <div> container. However, we are still using <br> as default
// paragraph separator (non-standard) and we've split only <p> container
// long time. Therefore, some web apps may depend on this behavior like
@@ -7365,48 +7371,50 @@ HTMLEditRules::IsInListItem(nsINode* aNo
nsAtom&
HTMLEditRules::DefaultParagraphSeparator()
{
MOZ_ASSERT(IsEditorDataAvailable());
return ParagraphSeparatorElement(
HTMLEditorRef().GetDefaultParagraphSeparator());
}
-/**
- * ReturnInHeader: do the right thing for returns pressed in headers
- */
nsresult
HTMLEditRules::ReturnInHeader(Element& aHeader,
nsINode& aNode,
int32_t aOffset)
{
MOZ_ASSERT(IsEditorDataAvailable());
// Remember where the header is
nsCOMPtr<nsINode> headerParent = aHeader.GetParentNode();
int32_t offset = headerParent ? headerParent->ComputeIndexOf(&aHeader) : -1;
// Get ws code to adjust any ws
nsCOMPtr<nsINode> node = &aNode;
nsresult rv = WSRunObject::PrepareToSplitAcrossBlocks(&HTMLEditorRef(),
address_of(node),
&aOffset);
+ if (NS_WARN_IF(!CanHandleEditAction())) {
+ return NS_ERROR_EDITOR_DESTROYED;
+ }
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (NS_WARN_IF(!node->IsContent())) {
return NS_ERROR_FAILURE;
}
// Split the header
- ErrorResult error;
SplitNodeResult splitHeaderResult =
HTMLEditorRef().SplitNodeDeepWithTransaction(
aHeader, EditorRawDOMPoint(node, aOffset),
SplitAtEdges::eAllowToCreateEmptyContainer);
+ if (NS_WARN_IF(!CanHandleEditAction())) {
+ return NS_ERROR_EDITOR_DESTROYED;
+ }
NS_WARNING_ASSERTION(splitHeaderResult.Succeeded(),
"Failed to split aHeader");
// If the previous heading of split point is empty, put a mozbr into it.
nsCOMPtr<nsIContent> prevItem = HTMLEditorRef().GetPriorHTMLSibling(&aHeader);
if (prevItem) {
MOZ_DIAGNOSTIC_ASSERT(
HTMLEditUtils::IsHeader(*prevItem));
@@ -7422,16 +7430,19 @@ HTMLEditRules::ReturnInHeader(Element& a
return createMozBrResult.Rv();
}
}
}
// If the new (righthand) header node is empty, delete it
if (IsEmptyBlockElement(aHeader, IgnoreSingleBR::eYes)) {
rv = HTMLEditorRef().DeleteNodeWithTransaction(aHeader);
+ if (NS_WARN_IF(!CanHandleEditAction())) {
+ return NS_ERROR_EDITOR_DESTROYED;
+ }
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// Layout tells the caret to blink in a weird place if we don't place a
// break after the header.
nsCOMPtr<nsIContent> sibling;
if (aHeader.GetNextSibling()) {
sibling = HTMLEditorRef().GetNextHTMLSibling(aHeader.GetNextSibling());
@@ -7443,50 +7454,68 @@ HTMLEditRules::ReturnInHeader(Element& a
// Create a paragraph
nsAtom& paraAtom = DefaultParagraphSeparator();
// We want a wrapper element even if we separate with <br>
EditorRawDOMPoint nextToHeader(headerParent, offset + 1);
RefPtr<Element> pNode =
HTMLEditorRef().CreateNodeWithTransaction(¶Atom == nsGkAtoms::br ?
*nsGkAtoms::p : paraAtom,
nextToHeader);
+ if (NS_WARN_IF(!CanHandleEditAction())) {
+ return NS_ERROR_EDITOR_DESTROYED;
+ }
if (NS_WARN_IF(!pNode)) {
return NS_ERROR_FAILURE;
}
// Append a <br> to it
RefPtr<Element> brElement =
HTMLEditorRef().InsertBrElementWithTransaction(
SelectionRef(), EditorRawDOMPoint(pNode, 0));
+ if (NS_WARN_IF(!CanHandleEditAction())) {
+ return NS_ERROR_EDITOR_DESTROYED;
+ }
if (NS_WARN_IF(!brElement)) {
return NS_ERROR_FAILURE;
}
// Set selection to before the break
ErrorResult error;
SelectionRef().Collapse(EditorRawDOMPoint(pNode, 0), error);
+ if (NS_WARN_IF(!CanHandleEditAction())) {
+ error.SuppressException();
+ return NS_ERROR_EDITOR_DESTROYED;
+ }
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
} else {
EditorRawDOMPoint afterSibling(sibling);
if (NS_WARN_IF(!afterSibling.AdvanceOffset())) {
return NS_ERROR_FAILURE;
}
// Put selection after break
ErrorResult error;
SelectionRef().Collapse(afterSibling, error);
+ if (NS_WARN_IF(!CanHandleEditAction())) {
+ error.SuppressException();
+ return NS_ERROR_EDITOR_DESTROYED;
+ }
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
}
} else {
// Put selection at front of righthand heading
ErrorResult error;
SelectionRef().Collapse(RawRangeBoundary(&aHeader, 0), error);
+ if (NS_WARN_IF(!CanHandleEditAction())) {
+ error.SuppressException();
+ return NS_ERROR_EDITOR_DESTROYED;
+ }
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
}
return NS_OK;
}
EditActionResult
--- a/editor/libeditor/HTMLEditRules.h
+++ b/editor/libeditor/HTMLEditRules.h
@@ -364,17 +364,32 @@ protected:
enum class Lists { no, yes };
enum class Tables { no, yes };
void GetInnerContent(nsINode& aNode,
nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
int32_t* aIndex, Lists aLists = Lists::yes,
Tables aTables = Tables::yes);
Element* IsInListItem(nsINode* aNode);
nsAtom& DefaultParagraphSeparator();
- nsresult ReturnInHeader(Element& aHeader, nsINode& aNode, int32_t aOffset);
+
+ /**
+ * ReturnInHeader() handles insertParagraph command (i.e., handling Enter
+ * key press) in a heading element. This splits aHeader element at
+ * aOffset in aNode. Then, if right heading element is empty, it'll be
+ * removed and new paragraph is created (its type is decided with default
+ * paragraph separator).
+ *
+ * @param aHeader The heading element to be split.
+ * @param aNode Typically, Selection start container,
+ * where to be split.
+ * @param aOffset Typically, Selection start offset in the
+ * start container, where to be split.
+ */
+ MOZ_MUST_USE nsresult
+ ReturnInHeader(Element& aHeader, nsINode& aNode, int32_t aOffset);
/**
* ReturnInParagraph() does the right thing for Enter key press or
* 'insertParagraph' command in aParentDivOrP. aParentDivOrP will be
* split at start of first selection range.
*
* @param aParentDivOrP The parent block. This must be <p> or <div>
* element.