diff --git a/editor/libeditor/HTMLEditor.h b/editor/libeditor/HTMLEditor.h
index 3c8ed5c24430..48ed83682fa7 100644
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -4616,6 +4616,8 @@ class HTMLEditor final : public TextEditor,
EditorDOMPoint GetNewCaretPointAfterInsertingHTML(
const EditorDOMPoint& lastInsertedPoint) const;
+ class HTMLWithContextInserter;
+
/**
* This function is used to insert a string of HTML input optionally with some
* context information into the editable field. The HTML input either comes
diff --git a/editor/libeditor/HTMLEditorDataTransfer.cpp b/editor/libeditor/HTMLEditorDataTransfer.cpp
index aabb9d04971e..dc3b34af5110 100644
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -200,6 +200,26 @@ nsresult HTMLEditor::InsertHTMLAsAction(const nsAString& aInString,
return EditorBase::ToGenericNSResult(rv);
}
+class MOZ_STACK_CLASS HTMLEditor::HTMLWithContextInserter final {
+ public:
+ MOZ_CAN_RUN_SCRIPT explicit HTMLWithContextInserter(HTMLEditor& aHTMLEditor)
+ : mHTMLEditor(aHTMLEditor) {}
+
+ HTMLWithContextInserter() = delete;
+ HTMLWithContextInserter(const HTMLWithContextInserter&) = delete;
+ HTMLWithContextInserter(HTMLWithContextInserter&&) = delete;
+
+ MOZ_CAN_RUN_SCRIPT nsresult Run(const nsAString& aInputString,
+ const nsAString& aContextStr,
+ const nsAString& aInfoStr,
+ const EditorDOMPoint& aPointToInsert,
+ bool aDoDeleteSelection, bool aTrustedInput,
+ bool aClearStyle);
+
+ private:
+ HTMLEditor& mHTMLEditor;
+};
+
EditorDOMPoint HTMLEditor::GetNewCaretPointAfterInsertingHTML(
const EditorDOMPoint& aLastInsertedPoint) const {
EditorDOMPoint pointToPutCaret;
@@ -277,23 +297,36 @@ EditorDOMPoint HTMLEditor::GetNewCaretPointAfterInsertingHTML(
return pointToPutCaret;
}
+
nsresult HTMLEditor::DoInsertHTMLWithContext(
const nsAString& aInputString, const nsAString& aContextStr,
const nsAString& aInfoStr, const nsAString& aFlavor, Document* aSourceDoc,
const EditorDOMPoint& aPointToInsert, bool aDoDeleteSelection,
bool aTrustedInput, bool aClearStyle) {
- MOZ_ASSERT(IsEditActionDataAvailable());
+ HTMLWithContextInserter htmlWithContextInserter(*this);
- if (NS_WARN_IF(!mInitSucceeded)) {
+ return htmlWithContextInserter.Run(aInputString, aContextStr, aInfoStr,
+ aPointToInsert, aDoDeleteSelection,
+ aTrustedInput, aClearStyle);
+}
+
+nsresult HTMLEditor::HTMLWithContextInserter::Run(
+ const nsAString& aInputString, const nsAString& aContextStr,
+ const nsAString& aInfoStr, const EditorDOMPoint& aPointToInsert,
+ bool aDoDeleteSelection, bool aTrustedInput, bool aClearStyle) {
+ MOZ_ASSERT(mHTMLEditor.IsEditActionDataAvailable());
+
+ if (NS_WARN_IF(!mHTMLEditor.mInitSucceeded)) {
return NS_ERROR_NOT_INITIALIZED;
}
// force IME commit; set up rules sniffing and batching
- CommitComposition();
- AutoPlaceholderBatch treatAsOneTransaction(*this);
+ mHTMLEditor.CommitComposition();
+ AutoPlaceholderBatch treatAsOneTransaction(mHTMLEditor);
IgnoredErrorResult ignoredError;
AutoEditSubActionNotifier startToHandleEditSubAction(
- *this, EditSubAction::ePasteHTMLContent, nsIEditor::eNext, ignoredError);
+ MOZ_KnownLive(mHTMLEditor), EditSubAction::ePasteHTMLContent,
+ nsIEditor::eNext, ignoredError);
if (NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
return ignoredError.StealNSResult();
}
@@ -306,7 +339,7 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
nsCOMPtr fragmentAsNode, streamStartParent, streamEndParent;
int32_t streamStartOffset = 0, streamEndOffset = 0;
- nsresult rv = CreateDOMFragmentFromPaste(
+ nsresult rv = mHTMLEditor.CreateDOMFragmentFromPaste(
aInputString, aContextStr, aInfoStr, address_of(fragmentAsNode),
address_of(streamStartParent), address_of(streamEndParent),
&streamStartOffset, &streamEndOffset, aTrustedInput);
@@ -322,7 +355,8 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
// scenarios where we are dropping in an editor (and may want to delete
// the selection before collapsing the selection in the new destination)
if (aPointToInsert.IsSet()) {
- rv = PrepareToInsertContent(aPointToInsert, aDoDeleteSelection);
+ rv = MOZ_KnownLive(mHTMLEditor)
+ .PrepareToInsertContent(aPointToInsert, aDoDeleteSelection);
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::PrepareToInsertContent() failed");
return rv;
@@ -357,7 +391,8 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
// XXX What will this do? We've already called DeleteSelectionAsSubAtion()
// above if insertion point is specified.
if (aDoDeleteSelection) {
- nsresult rv = DeleteSelectionAsSubAction(eNone, eStrip);
+ nsresult rv =
+ MOZ_KnownLive(mHTMLEditor).DeleteSelectionAsSubAction(eNone, eStrip);
if (NS_FAILED(rv)) {
NS_WARNING(
"EditorBase::DeleteSelectionAsSubAction(eNone, eStrip) failed");
@@ -370,7 +405,8 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
// Are there any table elements in the list?
// check for table cell selection mode
bool cellSelectionMode = false;
- RefPtr cellElement = GetFirstSelectedTableCellElement(ignoredError);
+ RefPtr cellElement =
+ mHTMLEditor.GetFirstSelectedTableCellElement(ignoredError);
if (cellElement) {
cellSelectionMode = true;
}
@@ -387,7 +423,7 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
}
if (!cellSelectionMode) {
- rv = DeleteSelectionAndPrepareToCreateNode();
+ rv = MOZ_KnownLive(mHTMLEditor).DeleteSelectionAndPrepareToCreateNode();
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::DeleteSelectionAndPrepareToCreateNode() failed");
return rv;
@@ -395,8 +431,11 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
if (aClearStyle) {
// pasting does not inherit local inline styles
- EditResult result = ClearStyleAt(
- EditorDOMPoint(SelectionRefPtr()->AnchorRef()), nullptr, nullptr);
+ EditResult result =
+ MOZ_KnownLive(mHTMLEditor)
+ .ClearStyleAt(
+ EditorDOMPoint(mHTMLEditor.SelectionRefPtr()->AnchorRef()),
+ nullptr, nullptr);
if (result.Failed()) {
NS_WARNING("HTMLEditor::ClearStyleAt() failed");
return result.Rv();
@@ -409,8 +448,8 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
// Save current selection since DeleteTableCellWithTransaction() perturbs
// it.
{
- AutoSelectionRestorer restoreSelectionLater(*this);
- rv = DeleteTableCellWithTransaction(1);
+ AutoSelectionRestorer restoreSelectionLater(mHTMLEditor);
+ rv = MOZ_KnownLive(mHTMLEditor).DeleteTableCellWithTransaction(1);
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::DeleteTableCellWithTransaction(1) failed");
return rv;
@@ -418,26 +457,26 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
}
// collapse selection to beginning of deleted table content
IgnoredErrorResult ignoredError;
- SelectionRefPtr()->CollapseToStart(ignoredError);
+ mHTMLEditor.SelectionRefPtr()->CollapseToStart(ignoredError);
NS_WARNING_ASSERTION(!ignoredError.Failed(),
"Selection::Collapse() failed, but ignored");
}
// XXX Why don't we test this first?
- if (IsReadonly()) {
+ if (mHTMLEditor.IsReadonly()) {
return NS_OK;
}
- EditActionResult result = CanHandleHTMLEditSubAction();
+ EditActionResult result = mHTMLEditor.CanHandleHTMLEditSubAction();
if (result.Failed() || result.Canceled()) {
NS_WARNING_ASSERTION(result.Succeeded(),
"HTMLEditor::CanHandleHTMLEditSubAction() failed");
return result.Rv();
}
- UndefineCaretBidiLevel();
+ mHTMLEditor.UndefineCaretBidiLevel();
- rv = EnsureNoPaddingBRElementForEmptyEditor();
+ rv = MOZ_KnownLive(mHTMLEditor).EnsureNoPaddingBRElementForEmptyEditor();
if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
return NS_ERROR_EDITOR_DESTROYED;
}
@@ -445,8 +484,9 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
"EditorBase::EnsureNoPaddingBRElementForEmptyEditor() "
"failed, but ignored");
- if (NS_SUCCEEDED(rv) && SelectionRefPtr()->IsCollapsed()) {
- nsresult rv = EnsureCaretNotAfterPaddingBRElement();
+ if (NS_SUCCEEDED(rv) && mHTMLEditor.SelectionRefPtr()->IsCollapsed()) {
+ nsresult rv =
+ MOZ_KnownLive(mHTMLEditor).EnsureCaretNotAfterPaddingBRElement();
if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
return NS_ERROR_EDITOR_DESTROYED;
}
@@ -454,7 +494,7 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
"HTMLEditor::EnsureCaretNotAfterPaddingBRElement() "
"failed, but ignored");
if (NS_SUCCEEDED(rv)) {
- nsresult rv = PrepareInlineStylesForCaret();
+ nsresult rv = MOZ_KnownLive(mHTMLEditor).PrepareInlineStylesForCaret();
if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
return NS_ERROR_EDITOR_DESTROYED;
}
@@ -465,9 +505,9 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
}
// Adjust position based on the first node we are going to insert.
- EditorDOMPoint pointToInsert =
- GetBetterInsertionPointFor(arrayOfTopMostChildContents[0],
- EditorBase::GetStartPoint(*SelectionRefPtr()));
+ EditorDOMPoint pointToInsert = mHTMLEditor.GetBetterInsertionPointFor(
+ arrayOfTopMostChildContents[0],
+ EditorBase::GetStartPoint(*mHTMLEditor.SelectionRefPtr()));
if (!pointToInsert.IsSet()) {
NS_WARNING("HTMLEditor::GetBetterInsertionPointFor() failed");
return NS_ERROR_FAILURE;
@@ -476,14 +516,16 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
// Remove invisible `
` element at the point because if there is a `
`
// element at end of what we paste, it will make the existing invisible
// `
` element visible.
- WSRunScanner wsRunScannerAtInsertionPoint(this, pointToInsert);
+ WSRunScanner wsRunScannerAtInsertionPoint(&mHTMLEditor, pointToInsert);
if (wsRunScannerAtInsertionPoint.GetEndReasonContent() &&
wsRunScannerAtInsertionPoint.GetEndReasonContent()->IsHTMLElement(
nsGkAtoms::br) &&
- !IsVisibleBRElement(wsRunScannerAtInsertionPoint.GetEndReasonContent())) {
+ !mHTMLEditor.IsVisibleBRElement(
+ wsRunScannerAtInsertionPoint.GetEndReasonContent())) {
AutoEditorDOMPointChildInvalidator lockOffset(pointToInsert);
- nsresult rv = DeleteNodeWithTransaction(
- MOZ_KnownLive(*wsRunScannerAtInsertionPoint.GetEndReasonContent()));
+ nsresult rv = MOZ_KnownLive(mHTMLEditor)
+ .DeleteNodeWithTransaction(MOZ_KnownLive(
+ *wsRunScannerAtInsertionPoint.GetEndReasonContent()));
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::DeleteNodeWithTransaction() failed");
return rv;
@@ -491,12 +533,14 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
}
const bool insertionPointWasInLink =
- !!GetLinkElement(pointToInsert.GetContainer());
+ !!HTMLEditor::GetLinkElement(pointToInsert.GetContainer());
if (pointToInsert.IsInTextNode()) {
- SplitNodeResult splitNodeResult = SplitNodeDeepWithTransaction(
- MOZ_KnownLive(*pointToInsert.GetContainerAsContent()), pointToInsert,
- SplitAtEdges::eAllowToCreateEmptyContainer);
+ SplitNodeResult splitNodeResult =
+ MOZ_KnownLive(mHTMLEditor)
+ .SplitNodeDeepWithTransaction(
+ MOZ_KnownLive(*pointToInsert.GetContainerAsContent()),
+ pointToInsert, SplitAtEdges::eAllowToCreateEmptyContainer);
if (splitNodeResult.Failed()) {
NS_WARNING("HTMLEditor::SplitNodeDeepWithTransaction() failed");
return splitNodeResult.Rv();
@@ -559,9 +603,10 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
for (nsCOMPtr firstChild = content->GetFirstChild();
firstChild; firstChild = content->GetFirstChild()) {
EditorDOMPoint insertedPoint =
- InsertNodeIntoProperAncestorWithTransaction(
- *firstChild, pointToInsert,
- SplitAtEdges::eDoNotCreateEmptyContainer);
+ MOZ_KnownLive(mHTMLEditor)
+ .InsertNodeIntoProperAncestorWithTransaction(
+ *firstChild, pointToInsert,
+ SplitAtEdges::eDoNotCreateEmptyContainer);
if (!insertedPoint.IsSet()) {
NS_WARNING(
"HTMLEditor::InsertNodeIntoProperAncestorWithTransaction("
@@ -596,24 +641,27 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
// is not proper child of the parent element, or current node
// is a list element.
if (HTMLEditUtils::IsListItem(pointToInsert.GetContainer()) &&
- IsEmptyNode(*pointToInsert.GetContainer(), true)) {
+ mHTMLEditor.IsEmptyNode(*pointToInsert.GetContainer(), true)) {
NS_WARNING_ASSERTION(pointToInsert.GetContainerParent(),
"Insertion point is out of the DOM tree");
if (pointToInsert.GetContainerParent()) {
pointToInsert.Set(pointToInsert.GetContainer());
MOZ_ASSERT(pointToInsert.IsSet());
AutoEditorDOMPointChildInvalidator lockOffset(pointToInsert);
- DebugOnly rvIgnored = DeleteNodeWithTransaction(
- MOZ_KnownLive(*pointToInsert.GetChild()));
+ DebugOnly rvIgnored =
+ MOZ_KnownLive(mHTMLEditor)
+ .DeleteNodeWithTransaction(
+ MOZ_KnownLive(*pointToInsert.GetChild()));
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
"HTMLEditor::DeleteNodeWithTransaction() "
"failed, but ignored");
}
}
EditorDOMPoint insertedPoint =
- InsertNodeIntoProperAncestorWithTransaction(
- *firstChild, pointToInsert,
- SplitAtEdges::eDoNotCreateEmptyContainer);
+ MOZ_KnownLive(mHTMLEditor)
+ .InsertNodeIntoProperAncestorWithTransaction(
+ *firstChild, pointToInsert,
+ SplitAtEdges::eDoNotCreateEmptyContainer);
if (!insertedPoint.IsSet()) {
NS_WARNING(
"HTMLEditor::InsertNodeIntoProperAncestorWithTransaction("
@@ -649,9 +697,10 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
for (nsCOMPtr firstChild = content->GetFirstChild();
firstChild; firstChild = content->GetFirstChild()) {
EditorDOMPoint insertedPoint =
- InsertNodeIntoProperAncestorWithTransaction(
- *firstChild, pointToInsert,
- SplitAtEdges::eDoNotCreateEmptyContainer);
+ MOZ_KnownLive(mHTMLEditor)
+ .InsertNodeIntoProperAncestorWithTransaction(
+ *firstChild, pointToInsert,
+ SplitAtEdges::eDoNotCreateEmptyContainer);
if (!insertedPoint.IsSet()) {
NS_WARNING(
"HTMLEditor::InsertNodeIntoProperAncestorWithTransaction("
@@ -675,9 +724,10 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
// MOZ_KnownLive because 'arrayOfTopMostChildContents' is guaranteed to
// keep it alive.
EditorDOMPoint insertedPoint =
- InsertNodeIntoProperAncestorWithTransaction(
- MOZ_KnownLive(content), pointToInsert,
- SplitAtEdges::eDoNotCreateEmptyContainer);
+ MOZ_KnownLive(mHTMLEditor)
+ .InsertNodeIntoProperAncestorWithTransaction(
+ MOZ_KnownLive(content), pointToInsert,
+ SplitAtEdges::eDoNotCreateEmptyContainer);
NS_WARNING_ASSERTION(
insertedPoint.IsSet(),
"HTMLEditor::InsertNodeIntoProperAncestorWithTransaction("
@@ -703,9 +753,10 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
}
OwningNonNull oldParentContent(
*childContent->GetParent());
- insertedPoint = InsertNodeIntoProperAncestorWithTransaction(
- oldParentContent, pointToInsert,
- SplitAtEdges::eDoNotCreateEmptyContainer);
+ insertedPoint = MOZ_KnownLive(mHTMLEditor)
+ .InsertNodeIntoProperAncestorWithTransaction(
+ oldParentContent, pointToInsert,
+ SplitAtEdges::eDoNotCreateEmptyContainer);
NS_WARNING_ASSERTION(
insertedPoint.IsSet(),
"HTMLEditor::InsertNodeIntoProperAncestorWithTransaction("
@@ -740,9 +791,9 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
}
const EditorDOMPoint pointToPutCaret =
- GetNewCaretPointAfterInsertingHTML(lastInsertedPoint);
+ mHTMLEditor.GetNewCaretPointAfterInsertingHTML(lastInsertedPoint);
// Now collapse the selection to the end of what we just inserted.
- rv = CollapseSelectionTo(pointToPutCaret);
+ rv = MOZ_KnownLive(mHTMLEditor).CollapseSelectionTo(pointToPutCaret);
if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
return NS_ERROR_EDITOR_DESTROYED;
}
@@ -763,15 +814,19 @@ nsresult HTMLEditor::DoInsertHTMLWithContext(
// above just placed selection inside that. So we need to split it instead.
// XXX Sounds like that it's not really expensive comparing with the reason
// to use SplitNodeDeepWithTransaction() here.
- SplitNodeResult splitLinkResult = SplitNodeDeepWithTransaction(
- *linkElement, pointToPutCaret, SplitAtEdges::eDoNotCreateEmptyContainer);
+ SplitNodeResult splitLinkResult =
+ MOZ_KnownLive(mHTMLEditor)
+ .SplitNodeDeepWithTransaction(
+ *linkElement, pointToPutCaret,
+ SplitAtEdges::eDoNotCreateEmptyContainer);
NS_WARNING_ASSERTION(
splitLinkResult.Succeeded(),
"HTMLEditor::SplitNodeDeepWithTransaction() failed, but ignored");
if (splitLinkResult.GetPreviousNode()) {
EditorRawDOMPoint afterLeftLink(splitLinkResult.GetPreviousNode());
if (afterLeftLink.AdvanceOffset()) {
- nsresult rv = CollapseSelectionTo(afterLeftLink);
+ nsresult rv =
+ MOZ_KnownLive(mHTMLEditor).CollapseSelectionTo(afterLeftLink);
if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
return NS_ERROR_EDITOR_DESTROYED;
}