Bug 1649121: part 19) Add `HTMLWithContextInserter` and move content of `DoInsertHTMLWithContext` to it. r=masayuki

This is minimally invasive. In the following parts, methods will be
moved to it and potentially other methods will be extracted.

Differential Revision: https://phabricator.services.mozilla.com/D82384
This commit is contained in:
Mirko Brodesser 2020-07-07 12:32:05 +00:00
Родитель 1684d9040a
Коммит b1c3499828
2 изменённых файлов: 113 добавлений и 56 удалений

Просмотреть файл

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

Просмотреть файл

@ -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<nsINode> 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<Element> cellElement = GetFirstSelectedTableCellElement(ignoredError);
RefPtr<Element> 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 `<br>` element at the point because if there is a `<br>`
// element at end of what we paste, it will make the existing invisible
// `<br>` 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<nsIContent> 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<nsresult> rvIgnored = DeleteNodeWithTransaction(
MOZ_KnownLive(*pointToInsert.GetChild()));
DebugOnly<nsresult> 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<nsIContent> 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<nsIContent> 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;
}