diff --git a/editor/libeditor/EditorCommands.cpp b/editor/libeditor/EditorCommands.cpp index 003a31ac9e7b..1dd13df39bf1 100644 --- a/editor/libeditor/EditorCommands.cpp +++ b/editor/libeditor/EditorCommands.cpp @@ -872,7 +872,8 @@ nsresult InsertParagraphCommand::DoCommand(Command aCommand, if (!htmlEditor) { return NS_OK; // Do nothing for now. } - nsresult rv = htmlEditor->InsertParagraphSeparatorAsAction(aPrincipal); + nsresult rv = + MOZ_KnownLive(htmlEditor)->InsertParagraphSeparatorAsAction(aPrincipal); NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "InsertParagraphSeparatorAsAction() failed"); return rv; diff --git a/editor/libeditor/HTMLEditRules.cpp b/editor/libeditor/HTMLEditRules.cpp index 0244b9db7bc1..8d0afd23dc2e 100644 --- a/editor/libeditor/HTMLEditRules.cpp +++ b/editor/libeditor/HTMLEditRules.cpp @@ -771,17 +771,6 @@ nsresult HTMLEditRules::WillDoAction(EditSubActionInfo& aInfo, bool* aCancel, return MOZ_KnownLive(HTMLEditorRef()) .WillInsertText(aInfo.mEditSubAction, aCancel, aHandled, aInfo.inString, aInfo.outString, aInfo.maxLength); - case EditSubAction::eInsertParagraphSeparator: { - TextEditorRef().UndefineCaretBidiLevel(); - EditActionResult result = WillInsertParagraphSeparator(); - if (NS_WARN_IF(result.Failed())) { - return result.Rv(); - } - *aCancel = result.Canceled(); - *aHandled = result.Handled(); - MOZ_ASSERT(!result.Ignored()); - return NS_OK; - } case EditSubAction::eDeleteSelectedContent: return WillDeleteSelection(aInfo.collapsedAction, aInfo.stripWrappers, aCancel, aHandled); @@ -827,6 +816,7 @@ nsresult HTMLEditRules::WillDoAction(EditSubActionInfo& aInfo, bool* aCancel, return WillRelativeChangeZIndex(1, aCancel, aHandled); case EditSubAction::eCreateOrRemoveBlock: case EditSubAction::eInsertHTMLSource: + case EditSubAction::eInsertParagraphSeparator: case EditSubAction::eUndo: case EditSubAction::eRedo: MOZ_ASSERT_UNREACHABLE("This path should've been dead code"); @@ -847,7 +837,6 @@ nsresult HTMLEditRules::DidDoAction(EditSubActionInfo& aInfo, switch (aInfo.mEditSubAction) { case EditSubAction::eInsertText: case EditSubAction::eInsertLineBreak: - case EditSubAction::eInsertParagraphSeparator: case EditSubAction::eInsertTextComingFromIME: return NS_OK; case EditSubAction::eDeleteSelectedContent: @@ -871,6 +860,7 @@ nsresult HTMLEditRules::DidDoAction(EditSubActionInfo& aInfo, return NS_OK; case EditSubAction::eCreateOrRemoveBlock: case EditSubAction::eInsertHTMLSource: + case EditSubAction::eInsertParagraphSeparator: case EditSubAction::eUndo: case EditSubAction::eRedo: MOZ_ASSERT_UNREACHABLE("This path should've been dead code"); @@ -1739,15 +1729,32 @@ bool HTMLEditor::CanContainParagraph(Element& aElement) const { return false; } -EditActionResult HTMLEditRules::WillInsertParagraphSeparator() { - MOZ_ASSERT(IsEditorDataAvailable()); +EditActionResult HTMLEditor::InsertParagraphSeparatorAsSubAction() { + if (!mRules) { + return EditActionIgnored(NS_ERROR_NOT_INITIALIZED); + } + + EditActionResult result = CanHandleHTMLEditSubAction(); + NS_WARNING_ASSERTION(result.Succeeded(), + "CanHandleHTMLEditSubAction() failed"); + if (result.Failed() || result.Canceled()) { + return result; + } + + // XXX This may be called by execCommand() with "insertParagraph". + // In such case, naming the transaction "TypingTxnName" is odd. + AutoPlaceholderBatch treatAsOneTransaction(*this, *nsGkAtoms::TypingTxnName); + + AutoEditSubActionNotifier startToHandleEditSubAction( + *this, EditSubAction::eInsertParagraphSeparator, nsIEditor::eNext); + + UndefineCaretBidiLevel(); // If the selection isn't collapsed, delete it. if (!SelectionRefPtr()->IsCollapsed()) { nsresult rv = - MOZ_KnownLive(HTMLEditorRef()) - .DeleteSelectionAsSubAction(nsIEditor::eNone, nsIEditor::eStrip); - if (NS_WARN_IF(!CanHandleEditAction())) { + DeleteSelectionAsSubAction(nsIEditor::eNone, nsIEditor::eStrip); + if (NS_WARN_IF(Destroyed())) { return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED); } if (NS_WARN_IF(NS_FAILED(rv))) { @@ -1756,7 +1763,7 @@ EditActionResult HTMLEditRules::WillInsertParagraphSeparator() { } // FYI: Ignore cancel result of WillInsert(). - nsresult rv = MOZ_KnownLive(HTMLEditorRef()).WillInsert(); + nsresult rv = WillInsert(); if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) { return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED); } @@ -1770,8 +1777,7 @@ EditActionResult HTMLEditRules::WillInsertParagraphSeparator() { return EditActionIgnored(NS_ERROR_FAILURE); } - EditActionResult result = - MOZ_KnownLive(HTMLEditorRef()).SplitMailCiteElements(pointToSplit); + EditActionResult result = SplitMailCiteElements(pointToSplit); if (NS_WARN_IF(result.Failed())) { return result; } @@ -1793,15 +1799,15 @@ EditActionResult HTMLEditRules::WillInsertParagraphSeparator() { MOZ_ASSERT(atStartOfSelection.IsSetAndValid()); // Do nothing if the node is read-only - if (!HTMLEditorRef().IsModifiableNode(*atStartOfSelection.GetContainer())) { + if (!IsModifiableNode(*atStartOfSelection.GetContainer())) { return EditActionCanceled(); } // If the active editing host is an inline element, or if the active editing // host is the block parent itself and we're configured to use
as a // paragraph separator, just append a
. - RefPtr host = HTMLEditorRef().GetActiveEditingHost(); - if (NS_WARN_IF(!host)) { + RefPtr editingHost = GetActiveEditingHost(); + if (NS_WARN_IF(!editingHost)) { return EditActionIgnored(NS_ERROR_FAILURE); } @@ -1809,22 +1815,22 @@ EditActionResult HTMLEditRules::WillInsertParagraphSeparator() { // there is no block parent here because in such case, i.e., editing host // is an inline element, we should insert
simply. RefPtr blockParent = - HTMLEditor::GetBlock(*atStartOfSelection.GetContainer(), host); + HTMLEditor::GetBlock(*atStartOfSelection.GetContainer(), editingHost); - ParagraphSeparator separator = HTMLEditorRef().GetDefaultParagraphSeparator(); + ParagraphSeparator separator = GetDefaultParagraphSeparator(); bool insertBRElement; // If there is no block parent in the editing host, i.e., the editing host // itself is also a non-block element, we should insert a
element. if (!blockParent) { - // XXX Chromium checks if the CSS box of the editing host is block. + // XXX Chromium checks if the CSS box of the editing host is a block. insertBRElement = true; } // If only the editing host is block, and the default paragraph separator // is
or the editing host cannot contain a

element, we should // insert a
element. - else if (host == blockParent) { + else if (editingHost == blockParent) { insertBRElement = separator == ParagraphSeparator::br || - !HTMLEditorRef().CanContainParagraph(*host); + !CanContainParagraph(*editingHost); } // If the nearest block parent is a single-line container declared in // the execCommand spec and not the editing host, we should separate the @@ -1837,34 +1843,33 @@ EditActionResult HTMLEditRules::WillInsertParagraphSeparator() { else { insertBRElement = true; for (Element* blockAncestor = blockParent; blockAncestor && insertBRElement; - blockAncestor = HTMLEditor::GetBlockNodeParent(blockAncestor, host)) { - insertBRElement = !HTMLEditorRef().CanContainParagraph(*blockAncestor); + blockAncestor = + HTMLEditor::GetBlockNodeParent(blockAncestor, editingHost)) { + insertBRElement = !CanContainParagraph(*blockAncestor); } } // If we cannot insert a

/

element at the selection, we should insert // a
element instead. if (insertBRElement) { - nsresult rv = - MOZ_KnownLive(HTMLEditorRef()).InsertBRElement(atStartOfSelection); + nsresult rv = InsertBRElement(atStartOfSelection); if (NS_WARN_IF(NS_FAILED(rv))) { return EditActionIgnored(rv); } return EditActionHandled(); } - if (host == blockParent && separator != ParagraphSeparator::br) { + if (editingHost == blockParent && separator != ParagraphSeparator::br) { // Insert a new block first MOZ_ASSERT(separator == ParagraphSeparator::div || separator == ParagraphSeparator::p); // FormatBlockContainerWithTransaction() creates AutoSelectionRestorer. // Therefore, even if it returns NS_OK, editor might have been destroyed // at restoring Selection. - nsresult rv = MOZ_KnownLive(HTMLEditorRef()) - .FormatBlockContainerWithTransaction(MOZ_KnownLive( - HTMLEditor::ToParagraphSeparatorTagName(separator))); + nsresult rv = FormatBlockContainerWithTransaction( + MOZ_KnownLive(HTMLEditor::ToParagraphSeparatorTagName(separator))); if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED) || - NS_WARN_IF(!CanHandleEditAction())) { + NS_WARN_IF(Destroyed())) { return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED); } // We warn on failure, but don't handle it, because it might be harmless. @@ -1885,13 +1890,13 @@ EditActionResult HTMLEditRules::WillInsertParagraphSeparator() { MOZ_ASSERT(atStartOfSelection.IsSetAndValid()); blockParent = - HTMLEditor::GetBlock(*atStartOfSelection.GetContainer(), host); + HTMLEditor::GetBlock(*atStartOfSelection.GetContainer(), editingHost); if (NS_WARN_IF(!blockParent)) { return EditActionIgnored(NS_ERROR_UNEXPECTED); } - if (NS_WARN_IF(blockParent == host)) { + if (NS_WARN_IF(blockParent == editingHost)) { // Didn't create a new block for some reason, fall back to
- rv = MOZ_KnownLive(HTMLEditorRef()).InsertBRElement(atStartOfSelection); + rv = InsertBRElement(atStartOfSelection); if (NS_WARN_IF(NS_FAILED(rv))) { return EditActionIgnored(rv); } @@ -1904,23 +1909,20 @@ EditActionResult HTMLEditRules::WillInsertParagraphSeparator() { // wrap following inline elements of a
element which is next sibling // of container of the caret. So, we need to adjust mNewBlockElement here // for avoiding jumping caret to odd position. - HTMLEditorRef().TopLevelEditSubActionDataRef().mNewBlockElement = - blockParent; + TopLevelEditSubActionDataRef().mNewBlockElement = blockParent; } // If block is empty, populate with br. (For example, imagine a div that // contains the word "text". The user selects "text" and types return. // "Text" is deleted leaving an empty block. We want to put in one br to // make block have a line. Then code further below will put in a second br.) - if (HTMLEditorRef().IsEmptyBlockElement(*blockParent, - HTMLEditor::IgnoreSingleBR::No)) { + if (IsEmptyBlockElement(*blockParent, IgnoreSingleBR::No)) { AutoEditorDOMPointChildInvalidator lockOffset(atStartOfSelection); EditorDOMPoint endOfBlockParent; endOfBlockParent.SetToEndOf(blockParent); RefPtr brElement = - MOZ_KnownLive(HTMLEditorRef()) - .InsertBRElementWithTransaction(endOfBlockParent); - if (NS_WARN_IF(!CanHandleEditAction())) { + InsertBRElementWithTransaction(endOfBlockParent); + if (NS_WARN_IF(Destroyed())) { return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED); } if (NS_WARN_IF(!brElement)) { @@ -1928,35 +1930,31 @@ EditActionResult HTMLEditRules::WillInsertParagraphSeparator() { } } - RefPtr listItem = - HTMLEditorRef().GetNearestAncestorListItemElement(*blockParent); - if (listItem && listItem != host) { - nsresult rv = - MOZ_KnownLive(HTMLEditorRef()) - .HandleInsertParagraphInListItemElement( - *listItem, MOZ_KnownLive(*atStartOfSelection.GetContainer()), - atStartOfSelection.Offset()); - if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) { - return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED); - } - NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), - "Failed to insert break into list item"); - return EditActionHandled(); - } - - if (HTMLEditUtils::IsHeader(*blockParent)) { - // Headers: close (or split) header - nsresult rv = - MOZ_KnownLive(HTMLEditorRef()) - .HandleInsertParagraphInHeadingElement( - *blockParent, MOZ_KnownLive(*atStartOfSelection.GetContainer()), - atStartOfSelection.Offset()); + RefPtr listItem = GetNearestAncestorListItemElement(*blockParent); + if (listItem && listItem != editingHost) { + nsresult rv = HandleInsertParagraphInListItemElement( + *listItem, MOZ_KnownLive(*atStartOfSelection.GetContainer()), + atStartOfSelection.Offset()); if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) { return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED); } NS_WARNING_ASSERTION( NS_SUCCEEDED(rv), - "Failed to handle insertParagraph in the heading element"); + "HandleInsertParagraphInListItemElement() failed, but ignored"); + return EditActionHandled(); + } + + if (HTMLEditUtils::IsHeader(*blockParent)) { + // Headers: close (or split) header + nsresult rv = HandleInsertParagraphInHeadingElement( + *blockParent, MOZ_KnownLive(*atStartOfSelection.GetContainer()), + atStartOfSelection.Offset()); + if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) { + return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED); + } + NS_WARNING_ASSERTION( + NS_SUCCEEDED(rv), + "HandleInsertParagraphInHeadingElement() failed, but ignored"); return EditActionHandled(); } @@ -1973,9 +1971,7 @@ EditActionResult HTMLEditRules::WillInsertParagraphSeparator() { blockParent->IsAnyOfHTMLElements(nsGkAtoms::p, nsGkAtoms::div))) { AutoEditorDOMPointChildInvalidator lockOffset(atStartOfSelection); // Paragraphs: special rules to look for
s - EditActionResult result = - MOZ_KnownLive(HTMLEditorRef()) - .HandleInsertParagraphInParagraph(*blockParent); + EditActionResult result = HandleInsertParagraphInParagraph(*blockParent); if (NS_WARN_IF(result.Failed())) { return result; } @@ -1988,12 +1984,12 @@ EditActionResult HTMLEditRules::WillInsertParagraphSeparator() { } // Fall through, if HandleInsertParagraphInParagraph() didn't handle it. MOZ_ASSERT(!result.Canceled(), - "HandleInsertParagraphInParagraph canceled this edit action, " + "HandleInsertParagraphInParagraph() canceled this edit action, " "WillInsertBreak() needs to handle such case"); } // If nobody handles this edit action, let's insert new
at the selection. - rv = MOZ_KnownLive(HTMLEditorRef()).InsertBRElement(atStartOfSelection); + rv = InsertBRElement(atStartOfSelection); if (NS_WARN_IF(NS_FAILED(rv))) { return EditActionIgnored(rv); } diff --git a/editor/libeditor/HTMLEditRules.h b/editor/libeditor/HTMLEditRules.h index dfaa2475fa79..f11a43df06f5 100644 --- a/editor/libeditor/HTMLEditRules.h +++ b/editor/libeditor/HTMLEditRules.h @@ -118,14 +118,6 @@ class HTMLEditRules : public TextEditRules { return mData->HTMLEditorRef(); } - /** - * WillInsertParagraphSeparator() is called when insertParagraph command is - * executed or something equivalent. This method actually tries to insert - * new paragraph or
element, etc. - */ - MOZ_CAN_RUN_SCRIPT - MOZ_MUST_USE EditActionResult WillInsertParagraphSeparator(); - /** * If aNode is a text node that contains only collapsed whitespace, delete * it. It doesn't serve any useful purpose, and we don't want it to confuse diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp index a64e711a4aea..78b87b4baf79 100644 --- a/editor/libeditor/HTMLEditor.cpp +++ b/editor/libeditor/HTMLEditor.cpp @@ -962,14 +962,10 @@ HTMLEditor::InsertLineBreak() { return NS_ERROR_NOT_INITIALIZED; } - // XXX This method is called by chrome of comm-central. So, using - // TypingTxnName here is odd in such case. - AutoPlaceholderBatch treatAsOneTransaction(*this, *nsGkAtoms::TypingTxnName); - nsresult rv = InsertParagraphSeparatorAsSubAction(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return EditorBase::ToGenericNSResult(rv); - } - return NS_OK; + EditActionResult result = InsertParagraphSeparatorAsSubAction(); + NS_WARNING_ASSERTION(result.Succeeded(), + "InsertParagraphSeparatorAsSubAction() failed"); + return EditorBase::ToGenericNSResult(result.Rv()); } nsresult HTMLEditor::InsertLineBreakAsAction(nsIPrincipal* aPrincipal) { @@ -997,45 +993,10 @@ nsresult HTMLEditor::InsertParagraphSeparatorAsAction( return NS_ERROR_NOT_INITIALIZED; } - // XXX This may be called by execCommand() with "insertParagraph". - // In such case, naming the transaction "TypingTxnName" is odd. - AutoPlaceholderBatch treatAsOneTransaction(*this, *nsGkAtoms::TypingTxnName); - nsresult rv = InsertParagraphSeparatorAsSubAction(); - if (NS_WARN_IF(NS_FAILED(rv))) { - return EditorBase::ToGenericNSResult(rv); - } - return NS_OK; -} - -nsresult HTMLEditor::InsertParagraphSeparatorAsSubAction() { - MOZ_ASSERT(IsEditActionDataAvailable()); - - if (!mRules) { - return NS_ERROR_NOT_INITIALIZED; - } - - // Protect the edit rules object from dying - RefPtr rules(mRules); - - AutoEditSubActionNotifier startToHandleEditSubAction( - *this, EditSubAction::eInsertParagraphSeparator, nsIEditor::eNext); - - EditSubActionInfo subActionInfo(EditSubAction::eInsertParagraphSeparator); - subActionInfo.maxLength = mMaxTextLength; - bool cancel, handled; - nsresult rv = rules->WillDoAction(subActionInfo, &cancel, &handled); - if (cancel) { - return rv; // We don't need to call DidDoAction() if canceled. - } - // XXX DidDoAction() does nothing for eInsertParagraphSeparator. However, - // we should call it until we keep using this style. Perhaps, each - // editor method should call necessary method of - // TextEditRules/HTMLEditRules directly. - rv = rules->DidDoAction(subActionInfo, rv); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - return NS_OK; + EditActionResult result = InsertParagraphSeparatorAsSubAction(); + NS_WARNING_ASSERTION(result.Succeeded(), + "InsertParagraphSeparatorAsSubAction() failed"); + return EditorBase::ToGenericNSResult(result.Rv()); } nsresult HTMLEditor::TabInTable(bool inIsShift, bool* outHandled) { diff --git a/editor/libeditor/HTMLEditor.h b/editor/libeditor/HTMLEditor.h index 4f81b40bad38..76934f14c6d0 100644 --- a/editor/libeditor/HTMLEditor.h +++ b/editor/libeditor/HTMLEditor.h @@ -144,7 +144,7 @@ class HTMLEditor final : public TextEditor, MOZ_CAN_RUN_SCRIPT NS_IMETHOD DeleteNode(nsINode* aNode) override; - NS_IMETHOD InsertLineBreak() override; + MOZ_CAN_RUN_SCRIPT NS_IMETHOD InsertLineBreak() override; MOZ_CAN_RUN_SCRIPT virtual nsresult HandleKeyPressEvent( @@ -214,7 +214,8 @@ class HTMLEditor final : public TextEditor, * JS. If set to nullptr, will be treated as * called by system. */ - nsresult InsertParagraphSeparatorAsAction(nsIPrincipal* aPrincipal = nullptr); + MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE nsresult + InsertParagraphSeparatorAsAction(nsIPrincipal* aPrincipal = nullptr); MOZ_CAN_RUN_SCRIPT nsresult InsertElementAtSelectionAsAction(Element* aElement, bool aDeleteSelection, @@ -1850,6 +1851,13 @@ class HTMLEditor final : public TextEditor, */ Element* GetNearestAncestorListItemElement(nsIContent& aContent) const; + /** + * InsertParagraphSeparatorAsSubAction() handles insertPargraph commad + * (i.e., handling Enter key press) with the above helper methods. + */ + MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE EditActionResult + InsertParagraphSeparatorAsSubAction(); + protected: // Called by helper classes. virtual void OnStartToHandleTopLevelEditSubAction( EditSubAction aEditSubAction, nsIEditor::EDirection aDirection) override; @@ -1859,12 +1867,6 @@ class HTMLEditor final : public TextEditor, protected: // Shouldn't be used by friend classes virtual ~HTMLEditor(); - /** - * InsertParagraphSeparatorAsSubAction() inserts a line break if it's - * HTMLEditor and it's possible. - */ - nsresult InsertParagraphSeparatorAsSubAction(); - MOZ_CAN_RUN_SCRIPT virtual nsresult SelectAllInternal() override; diff --git a/editor/nsIPlaintextEditor.idl b/editor/nsIPlaintextEditor.idl index b13eb0a15172..da7bb79866f6 100644 --- a/editor/nsIPlaintextEditor.idl +++ b/editor/nsIPlaintextEditor.idl @@ -94,5 +94,6 @@ interface nsIPlaintextEditor : nsISupports * it may enter a character, split a node in the tree, etc. * This may be more efficient than calling InsertText with a newline. */ + [can_run_script] void insertLineBreak(); };