Bug 1574852 - part 52: Make `HTMLEditRules::WillInsertParagraph()` merged with `HTMLEditor::InsertParagraphSeparatorAsSubAction()` r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 03 Sep 2019 03:59:11 +0000
changeset 491636 7ece9cd0da19e9f73851bf51cdb8798c7847a353
parent 491635 98e552558193505b2df561d78c25aac38f2e4545
child 491637 b7d720cd37f9f96e45d472d0ce00111375d3c2a9
push id36532
push usercbrindusan@mozilla.com
push dateWed, 04 Sep 2019 16:29:47 +0000
treeherdermozilla-central@d23599eaa057 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1574852
milestone71.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1574852 - part 52: Make `HTMLEditRules::WillInsertParagraph()` merged with `HTMLEditor::InsertParagraphSeparatorAsSubAction()` r=m_kato Meaningful job of `HTMLEditor::InsertParagraphSeparatorAsSubAction()` is only calling `HTMLEditRules::WillInsertParagraph()` via `HTMLEditRules::WillDoAction()`. Therefore, we can move all jobs in them into `HTMLEditRules::WillInsertParagraph()` and rename it to `HTMLEditor::InsertParagraphSeparatorAsSubAction()`. Differential Revision: https://phabricator.services.mozilla.com/D44190
editor/libeditor/EditorCommands.cpp
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditRules.h
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditor.h
editor/nsIPlaintextEditor.idl
--- a/editor/libeditor/EditorCommands.cpp
+++ b/editor/libeditor/EditorCommands.cpp
@@ -867,17 +867,18 @@ bool InsertParagraphCommand::IsCommandEn
 
 nsresult InsertParagraphCommand::DoCommand(Command aCommand,
                                            TextEditor& aTextEditor,
                                            nsIPrincipal* aPrincipal) const {
   HTMLEditor* htmlEditor = aTextEditor.AsHTMLEditor();
   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;
 }
 
 nsresult InsertParagraphCommand::GetCommandStateParams(
     Command aCommand, nsCommandParams& aParams, TextEditor* aTextEditor,
     nsIEditingSession* aEditingSession) const {
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -766,27 +766,16 @@ nsresult HTMLEditRules::WillDoAction(Edi
 
   switch (aInfo.mEditSubAction) {
     case EditSubAction::eInsertText:
     case EditSubAction::eInsertTextComingFromIME:
       TextEditorRef().UndefineCaretBidiLevel();
       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);
     case EditSubAction::eCreateOrChangeList:
       return WillMakeList(aInfo.blockType, aInfo.entireList, aInfo.bulletType,
                           aCancel, aHandled);
     case EditSubAction::eIndent:
       return WillIndent(aCancel, aHandled);
@@ -822,16 +811,17 @@ nsresult HTMLEditRules::WillDoAction(Edi
       return NS_OK;
     }
     case EditSubAction::eDecreaseZIndex:
       return WillRelativeChangeZIndex(-1, aCancel, aHandled);
     case EditSubAction::eIncreaseZIndex:
       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");
       return NS_ERROR_UNEXPECTED;
     default:
       return TextEditRules::WillDoAction(aInfo, aCancel, aHandled);
   }
 }
@@ -842,17 +832,16 @@ nsresult HTMLEditRules::DidDoAction(Edit
     return NS_ERROR_EDITOR_DESTROYED;
   }
 
   AutoSafeEditorData setData(*this, *mHTMLEditor);
 
   switch (aInfo.mEditSubAction) {
     case EditSubAction::eInsertText:
     case EditSubAction::eInsertLineBreak:
-    case EditSubAction::eInsertParagraphSeparator:
     case EditSubAction::eInsertTextComingFromIME:
       return NS_OK;
     case EditSubAction::eDeleteSelectedContent:
       return DidDeleteSelection();
     case EditSubAction::eIndent:
     case EditSubAction::eOutdent:
     case EditSubAction::eSetOrClearAlignment:
       return MOZ_KnownLive(HTMLEditorRef())
@@ -866,16 +855,17 @@ nsresult HTMLEditRules::DidDoAction(Edit
       }
       return DidAbsolutePosition();
     }
     case EditSubAction::eInsertElement:
     case EditSubAction::eInsertQuotedText:
       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");
       return NS_ERROR_UNEXPECTED;
     default:
       return TextEditRules::DidDoAction(aInfo, aResult);
   }
 }
@@ -1734,49 +1724,65 @@ bool HTMLEditor::CanContainParagraph(Ele
     return true;
   }
 
   // XXX Otherwise, Chromium checks the CSS box is a block, but we don't do it
   //     for now.
   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))) {
       return EditActionIgnored(rv);
     }
   }
 
   // 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);
   }
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "WillInsert() failed");
 
   // Split any mailcites in the way.  Should we abort this if we encounter
   // table cell boundaries?
   if (IsMailEditor()) {
     EditorDOMPoint pointToSplit(EditorBase::GetStartPoint(*SelectionRefPtr()));
     if (NS_WARN_IF(!pointToSplit.IsSet())) {
       return EditActionIgnored(NS_ERROR_FAILURE);
     }
 
-    EditActionResult result =
-        MOZ_KnownLive(HTMLEditorRef()).SplitMailCiteElements(pointToSplit);
+    EditActionResult result = SplitMailCiteElements(pointToSplit);
     if (NS_WARN_IF(result.Failed())) {
       return result;
     }
     if (result.Handled()) {
       return result;
     }
   }
 
@@ -1788,88 +1794,87 @@ EditActionResult HTMLEditRules::WillInse
 
   EditorDOMPoint atStartOfSelection(firstRange->StartRef());
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return EditActionIgnored(NS_ERROR_FAILURE);
   }
   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 <br> as a
   // paragraph separator, just append a <br>.
-  RefPtr<Element> host = HTMLEditorRef().GetActiveEditingHost();
-  if (NS_WARN_IF(!host)) {
+  RefPtr<Element> editingHost = GetActiveEditingHost();
+  if (NS_WARN_IF(!editingHost)) {
     return EditActionIgnored(NS_ERROR_FAILURE);
   }
 
   // Look for the nearest parent block.  However, don't return error even if
   // there is no block parent here because in such case, i.e., editing host
   // is an inline element, we should insert <br> simply.
   RefPtr<Element> blockParent =
-      HTMLEditor::GetBlock(*atStartOfSelection.GetContainer(), host);
-
-  ParagraphSeparator separator = HTMLEditorRef().GetDefaultParagraphSeparator();
+      HTMLEditor::GetBlock(*atStartOfSelection.GetContainer(), editingHost);
+
+  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 <br> 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 <br> or the editing host cannot contain a <p> element, we should
   // insert a <br> 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
   // block even if the default paragraph separator is <br> element.
   else if (HTMLEditUtils::IsSingleLineContainer(*blockParent)) {
     insertBRElement = false;
   }
   // Otherwise, unless there is no block ancestor which can contain <p>
   // element, we shouldn't insert a <br> element here.
   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 <p>/<div> element at the selection, we should insert
   // a <br> 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.
     // Instead we just check that a new block was actually created.
     NS_WARNING_ASSERTION(
         NS_SUCCEEDED(rv),
         "HTMLEditor::FormatBlockContainerWithTransaction() failed");
 
@@ -1880,125 +1885,116 @@ EditActionResult HTMLEditRules::WillInse
 
     atStartOfSelection = firstRange->StartRef();
     if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
       return EditActionIgnored(NS_ERROR_FAILURE);
     }
     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 <br>
-      rv = MOZ_KnownLive(HTMLEditorRef()).InsertBRElement(atStartOfSelection);
+      rv = InsertBRElement(atStartOfSelection);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return EditActionIgnored(rv);
       }
       return EditActionHandled();
     }
     // Now, mNewBlockElement is last created block element for wrapping inline
     // elements around the caret position and AfterEditInner() will move
     // caret into it.  However, it may be different from block parent of
     // the caret position.  E.g., FormatBlockContainerWithTransaction() may
     // wrap following inline elements of a <br> 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<Element> 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)) {
       return EditActionIgnored(NS_ERROR_FAILURE);
     }
   }
 
-  RefPtr<Element> listItem =
-      HTMLEditorRef().GetNearestAncestorListItemElement(*blockParent);
-  if (listItem && listItem != host) {
-    nsresult rv =
-        MOZ_KnownLive(HTMLEditorRef())
-            .HandleInsertParagraphInListItemElement(
-                *listItem, MOZ_KnownLive(*atStartOfSelection.GetContainer()),
-                atStartOfSelection.Offset());
+  RefPtr<Element> 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 insert break into list item");
+    NS_WARNING_ASSERTION(
+        NS_SUCCEEDED(rv),
+        "HandleInsertParagraphInListItemElement() failed, but ignored");
     return EditActionHandled();
   }
 
   if (HTMLEditUtils::IsHeader(*blockParent)) {
     // Headers: close (or split) header
-    nsresult rv =
-        MOZ_KnownLive(HTMLEditorRef())
-            .HandleInsertParagraphInHeadingElement(
-                *blockParent, MOZ_KnownLive(*atStartOfSelection.GetContainer()),
-                atStartOfSelection.Offset());
+    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),
-        "Failed to handle insertParagraph in the heading element");
+        "HandleInsertParagraphInHeadingElement() failed, but ignored");
     return EditActionHandled();
   }
 
   // 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
   //     Gmail.  So, let's use traditional odd behavior only when the default
   //     paragraph separator is <br>.  Otherwise, take consistent behavior
   //     between <p> container and <div> container.
   if ((separator == ParagraphSeparator::br &&
        blockParent->IsHTMLElement(nsGkAtoms::p)) ||
       (separator != ParagraphSeparator::br &&
        blockParent->IsAnyOfHTMLElements(nsGkAtoms::p, nsGkAtoms::div))) {
     AutoEditorDOMPointChildInvalidator lockOffset(atStartOfSelection);
     // Paragraphs: special rules to look for <br>s
-    EditActionResult result =
-        MOZ_KnownLive(HTMLEditorRef())
-            .HandleInsertParagraphInParagraph(*blockParent);
+    EditActionResult result = HandleInsertParagraphInParagraph(*blockParent);
     if (NS_WARN_IF(result.Failed())) {
       return result;
     }
     if (result.Handled()) {
       // Now, atStartOfSelection may be invalid because the left paragraph
       // may have less children than its offset.  For avoiding warnings of
       // validation of EditorDOMPoint, we should not touch it anymore.
       lockOffset.Cancel();
       return result;
     }
     // 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 <br> at the selection.
-  rv = MOZ_KnownLive(HTMLEditorRef()).InsertBRElement(atStartOfSelection);
+  rv = InsertBRElement(atStartOfSelection);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return EditActionIgnored(rv);
   }
   return EditActionHandled();
 }
 
 nsresult HTMLEditor::InsertBRElement(const EditorDOMPoint& aPointToBreak) {
   MOZ_ASSERT(IsEditActionDataAvailable());
--- a/editor/libeditor/HTMLEditRules.h
+++ b/editor/libeditor/HTMLEditRules.h
@@ -114,24 +114,16 @@ class HTMLEditRules : public TextEditRul
   virtual ~HTMLEditRules() = default;
 
   HTMLEditor& HTMLEditorRef() const {
     MOZ_ASSERT(mData);
     return mData->HTMLEditorRef();
   }
 
   /**
-   * WillInsertParagraphSeparator() is called when insertParagraph command is
-   * executed or something equivalent.  This method actually tries to insert
-   * new paragraph or <br> 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
    * code that doesn't correctly skip over it.
    *
    * If deleting the node fails (like if it's not editable), the caller should
    * proceed as usual, so don't return any errors.
    */
   MOZ_CAN_RUN_SCRIPT
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -957,24 +957,20 @@ HTMLEditor::InsertLineBreak() {
   // XPCOM method's InsertLineBreak() should insert paragraph separator in
   // HTMLEditor.
   AutoEditActionDataSetter editActionData(
       *this, EditAction::eInsertParagraphSeparator);
   if (NS_WARN_IF(!editActionData.CanHandle())) {
     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) {
   AutoEditActionDataSetter editActionData(*this, EditAction::eInsertLineBreak,
                                           aPrincipal);
   if (NS_WARN_IF(!editActionData.CanHandle())) {
     return NS_ERROR_NOT_INITIALIZED;
   }
@@ -992,55 +988,20 @@ nsresult HTMLEditor::InsertLineBreakAsAc
 nsresult HTMLEditor::InsertParagraphSeparatorAsAction(
     nsIPrincipal* aPrincipal) {
   AutoEditActionDataSetter editActionData(
       *this, EditAction::eInsertParagraphSeparator, aPrincipal);
   if (NS_WARN_IF(!editActionData.CanHandle())) {
     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<TextEditRules> 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) {
   NS_ENSURE_TRUE(outHandled, NS_ERROR_NULL_POINTER);
   *outHandled = false;
 
   AutoEditActionDataSetter editActionData(*this, EditAction::eNotEditing);
   if (NS_WARN_IF(!editActionData.CanHandle())) {
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -139,17 +139,17 @@ class HTMLEditor final : public TextEdit
   using EditorBase::CanPaste;
 
   MOZ_CAN_RUN_SCRIPT virtual nsresult PasteTransferableAsAction(
       nsITransferable* aTransferable,
       nsIPrincipal* aPrincipal = nullptr) override;
 
   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(
       WidgetKeyboardEvent* aKeyboardEvent) override;
   virtual nsIContent* GetFocusedContent() override;
   virtual already_AddRefed<nsIContent> GetFocusedContentForIME() override;
   virtual bool IsActiveInDOMWindow() override;
   virtual dom::EventTarget* GetDOMEventTarget() override;
@@ -209,17 +209,18 @@ class HTMLEditor final : public TextEdit
   /**
    * InsertParagraphSeparatorAsAction() is called when user tries to separate
    * current paragraph with Enter key press in HTMLEditor or something.
    *
    * @param aPrincipal          Set subject principal if it may be called by
    *                            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,
                                    nsIPrincipal* aPrincipal = nullptr);
 
   MOZ_CAN_RUN_SCRIPT nsresult InsertLinkAroundSelectionAsAction(
       Element* aAnchorElement, nsIPrincipal* aPrincipal = nullptr);
 
@@ -1845,31 +1846,32 @@ class HTMLEditor final : public TextEdit
 
   /**
    * GetNearestAncestorListItemElement() returns a list item element if
    * aContent or its ancestor in editing host is one.  However, this won't
    * cross table related element.
    */
   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;
   MOZ_CAN_RUN_SCRIPT
   virtual void OnEndHandlingTopLevelEditSubAction() override;
 
  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;
 
   /**
    * SelectContentInternal() sets Selection to aContentToSelect to
    * aContentToSelect + 1 in parent of aContentToSelect.
    *
    * @param aContentToSelect    The content which should be selected.
--- a/editor/nsIPlaintextEditor.idl
+++ b/editor/nsIPlaintextEditor.idl
@@ -89,10 +89,11 @@ interface nsIPlaintextEditor : nsISuppor
    void insertText(in AString aStringToInsert);
 
   /**
    * Insert a line break into the content model.
    * The interpretation of a break is up to the implementation:
    * 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();
 };