Backed out 5 changesets (bug 1503473) for crashes in Thunderbird on request of jorgk. a=backout
authorCosmin Sabou <csabou@mozilla.com>
Sat, 03 Nov 2018 02:08:42 +0200
changeset 500613 75e4c3050cac5acc38d3031fb97bed8eaca59222
parent 500612 e05552012e193e1effac4c01dd149c6e6b51f30b
child 500651 6655fa7cff4800390e15d164968923da168ce7c8
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1503473
milestone65.0a1
backs outa7f7d9f366b9d19e51c2817dae398c3300a05ccb
d067907793efc8b232e295d4a52b3119bfaa6c64
130ba0de053fd4889ddffdce68d88f999ff72964
ec732243e9ad7cdfea1fad018f1acc400e00f2b0
13511cab2b41922cbae8edce6567535adae85c5d
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
Backed out 5 changesets (bug 1503473) for crashes in Thunderbird on request of jorgk. a=backout Backed out changeset a7f7d9f366b9 (bug 1503473) Backed out changeset d067907793ef (bug 1503473) Backed out changeset 130ba0de053f (bug 1503473) Backed out changeset ec732243e9ad (bug 1503473) Backed out changeset 13511cab2b41 (bug 1503473)
editor/libeditor/EditAction.h
editor/libeditor/EditorCommands.cpp
editor/libeditor/EditorUtils.h
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/HTMLEditRules.h
editor/libeditor/HTMLEditor.cpp
editor/libeditor/HTMLEditor.h
editor/libeditor/TextEditRules.cpp
editor/libeditor/TextEditRules.h
editor/libeditor/TextEditor.cpp
editor/libeditor/TextEditor.h
--- a/editor/libeditor/EditAction.h
+++ b/editor/libeditor/EditAction.h
@@ -21,21 +21,20 @@ enum class EditAction
   // something at creating, destroying or focus move etc, i.e., not edit
   // action is being handled but editor is doing something.
   eNotEditing,
 
   // eInsertText indicates to insert some characters.
   eInsertText,
 
   // eInsertParagraphSeparator indicates to insert a paragraph separator such
-  // as <p>, <div>.
+  // as <p>, <div> or just \n in TextEditor.
   eInsertParagraphSeparator,
 
-  // eInsertLineBreak indicates to insert \n into TextEditor or a <br> element
-  // in HTMLEditor.
+  // eInsertLineBreak indicates to insert a <br> element in HTMLEditor.
   eInsertLineBreak,
 
   // eDeleteSelection indicates to delete selected content or content around
   // caret if selection is collapsed.
   eDeleteSelection,
 
   // eDeleteBackward indicates to remove previous character element of caret.
   // This may be set even when Selection is not collapsed.
@@ -394,22 +393,18 @@ enum class EditSubAction : int32_t
 
   // eComputeTextToOutput indicates to compute the editor value as plain text
   // or something requested format.
   eComputeTextToOutput,
 
   // eSetText indicates to set editor value to new value.
   eSetText,
 
-  // eInsertLineBreak indicates to insert a line break, <br> or \n to break
-  // current line.
-  eInsertLineBreak,
-
   // eInsertParagraphSeparator indicates to insert paragraph separator, <br> or
-  // \n at least to break current line in HTMLEditor.
+  // \n at least to break current line.
   eInsertParagraphSeparator,
 
   // eCreateOrChangeList indicates to create new list or change existing list
   // type.
   eCreateOrChangeList,
 
   // eIndent and eOutdent indicates to indent or outdent the target with
   // using <blockquote>, <ul>, <ol> or just margin of start edge.
--- a/editor/libeditor/EditorCommands.cpp
+++ b/editor/libeditor/EditorCommands.cpp
@@ -1173,21 +1173,21 @@ NS_IMETHODIMP
 InsertParagraphCommand::DoCommand(const char* aCommandName,
                                   nsISupports* aCommandRefCon)
 {
   nsCOMPtr<nsIEditor> editor = do_QueryInterface(aCommandRefCon);
   if (NS_WARN_IF(!editor)) {
     return NS_ERROR_FAILURE;
   }
 
-  HTMLEditor* htmlEditor = editor->AsHTMLEditor();
-  if (!htmlEditor) {
-    return NS_OK; // Do nothing for now.
-  }
-  return htmlEditor->InsertParagraphSeparatorAsAction();
+  TextEditor* textEditor = editor->AsTextEditor();
+  MOZ_ASSERT(textEditor);
+  // XXX OnInputParagraphSeparator() is a handler of user input.  So, this
+  //     call may not be expected.
+  return textEditor->OnInputParagraphSeparator();
 }
 
 NS_IMETHODIMP
 InsertParagraphCommand::DoCommandParams(const char* aCommandName,
                                         nsICommandParams* aParams,
                                         nsISupports* aCommandRefCon)
 {
   return DoCommand(aCommandName, aCommandRefCon);
@@ -1239,17 +1239,19 @@ InsertLineBreakCommand::DoCommand(const 
   if (NS_WARN_IF(!editor)) {
     return NS_ERROR_FAILURE;
   }
 
   HTMLEditor* htmlEditor = editor->AsHTMLEditor();
   if (!htmlEditor) {
     return NS_ERROR_FAILURE;
   }
-  return htmlEditor->InsertLineBreakAsAction();
+  // XXX OnInputLineBreak() is a handler of user input.  So, this call may not
+  //     be expected.
+  return htmlEditor->OnInputLineBreak();
 }
 
 NS_IMETHODIMP
 InsertLineBreakCommand::DoCommandParams(const char* aCommandName,
                                         nsICommandParams* aParams,
                                         nsISupports* aCommandRefCon)
 {
   return DoCommand(aCommandName, aCommandRefCon);
--- a/editor/libeditor/EditorUtils.h
+++ b/editor/libeditor/EditorUtils.h
@@ -43,17 +43,16 @@ class Text;
 class MOZ_STACK_CLASS EditActionResult final
 {
 public:
   bool Succeeded() const { return NS_SUCCEEDED(mRv); }
   bool Failed() const { return NS_FAILED(mRv); }
   nsresult Rv() const { return mRv; }
   bool Canceled() const { return mCanceled; }
   bool Handled() const { return mHandled; }
-  bool Ignored() const { return !mCanceled && !mHandled; }
   bool EditorDestroyed() const { return mRv == NS_ERROR_EDITOR_DESTROYED; }
 
   EditActionResult SetResult(nsresult aRv)
   {
     mRv = aRv;
     return *this;
   }
   EditActionResult MarkAsCanceled()
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -80,17 +80,16 @@ enum
 /********************************************************
  *  first some helpful functors we will use
  ********************************************************/
 
 static bool
 IsStyleCachePreservingSubAction(EditSubAction aEditSubAction)
 {
   return aEditSubAction == EditSubAction::eDeleteSelectedContent ||
-         aEditSubAction == EditSubAction::eInsertLineBreak ||
          aEditSubAction == EditSubAction::eInsertParagraphSeparator ||
          aEditSubAction == EditSubAction::eCreateOrChangeList ||
          aEditSubAction == EditSubAction::eIndent ||
          aEditSubAction == EditSubAction::eOutdent ||
          aEditSubAction == EditSubAction::eSetOrClearAlignment ||
          aEditSubAction == EditSubAction::eCreateOrRemoveBlock ||
          aEditSubAction == EditSubAction::eRemoveList ||
          aEditSubAction == EditSubAction::eCreateOrChangeDefinitionList ||
@@ -557,17 +556,16 @@ HTMLEditRules::AfterEditInner(EditSubAct
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     // attempt to transform any unneeded nbsp's into spaces after doing various operations
     if (aEditSubAction == EditSubAction::eInsertText ||
         aEditSubAction == EditSubAction::eInsertTextComingFromIME ||
         aEditSubAction == EditSubAction::eDeleteSelectedContent ||
-        aEditSubAction == EditSubAction::eInsertLineBreak ||
         aEditSubAction == EditSubAction::eInsertParagraphSeparator ||
         aEditSubAction == EditSubAction::ePasteHTMLContent ||
         aEditSubAction == EditSubAction::eInsertHTMLSource) {
       rv = AdjustWhitespace();
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
@@ -594,17 +592,16 @@ HTMLEditRules::AfterEditInner(EditSubAct
         "Failed to pin selection to the new block");
       mNewBlock = nullptr;
     }
 
     // adjust selection for insert text, html paste, and delete actions
     if (aEditSubAction == EditSubAction::eInsertText ||
         aEditSubAction == EditSubAction::eInsertTextComingFromIME ||
         aEditSubAction == EditSubAction::eDeleteSelectedContent ||
-        aEditSubAction == EditSubAction::eInsertLineBreak ||
         aEditSubAction == EditSubAction::eInsertParagraphSeparator ||
         aEditSubAction == EditSubAction::ePasteHTMLContent ||
         aEditSubAction == EditSubAction::eInsertHTMLSource) {
       rv = AdjustSelection(aDirection);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
@@ -714,27 +711,19 @@ HTMLEditRules::WillDoAction(EditSubActio
     case EditSubAction::eInsertText:
     case EditSubAction::eInsertTextComingFromIME:
       UndefineCaretBidiLevel();
       return WillInsertText(aInfo.mEditSubAction, aCancel, aHandled,
                             aInfo.inString, aInfo.outString,
                             aInfo.maxLength);
     case EditSubAction::eInsertHTMLSource:
       return WillLoadHTML();
-    case EditSubAction::eInsertParagraphSeparator: {
+    case EditSubAction::eInsertParagraphSeparator:
       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;
-    }
+      return WillInsertBreak(aCancel, aHandled);
     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);
@@ -786,17 +775,16 @@ HTMLEditRules::DidDoAction(EditSubAction
   if (NS_WARN_IF(!CanHandleEditAction())) {
     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::eCreateOrRemoveBlock:
     case EditSubAction::eIndent:
     case EditSubAction::eOutdent:
@@ -1703,76 +1691,82 @@ HTMLEditRules::CanContainParagraph(Eleme
     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());
+nsresult
+HTMLEditRules::WillInsertBreak(bool* aCancel,
+                               bool* aHandled)
+{
+  MOZ_ASSERT(IsEditorDataAvailable());
+
+  MOZ_ASSERT(aCancel && aHandled);
+  *aCancel = false;
+  *aHandled = false;
 
   // If the selection isn't collapsed, delete it.
   if (!SelectionRefPtr()->IsCollapsed()) {
     nsresult rv =
       HTMLEditorRef().DeleteSelectionAsSubAction(nsIEditor::eNone,
                                                  nsIEditor::eStrip);
     if (NS_WARN_IF(!CanHandleEditAction())) {
-      return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+      return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      return EditActionIgnored(rv);
+      return rv;
     }
   }
 
   // FYI: Ignore cancel result of WillInsert().
   nsresult rv = WillInsert();
   if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
-    return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+    return 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()) {
-    EditActionResult result = SplitMailCites();
-    if (NS_WARN_IF(result.Failed())) {
-      return result;
-    }
-    if (result.Handled()) {
-      return result;
+    nsresult rv = SplitMailCites(aHandled);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+    if (*aHandled) {
+      return NS_OK;
     }
   }
 
   // Smart splitting rules
   nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0);
   if (NS_WARN_IF(!firstRange)) {
-    return EditActionIgnored(NS_ERROR_FAILURE);
+    return NS_ERROR_FAILURE;
   }
 
   EditorDOMPoint atStartOfSelection(firstRange->StartRef());
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
-    return EditActionIgnored(NS_ERROR_FAILURE);
+    return NS_ERROR_FAILURE;
   }
   MOZ_ASSERT(atStartOfSelection.IsSetAndValid());
 
   // Do nothing if the node is read-only
   if (!HTMLEditorRef().IsModifiableNode(*atStartOfSelection.GetContainer())) {
-    return EditActionCanceled();
+    *aCancel = true;
+    return NS_OK;
   }
 
   // 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)) {
-    return EditActionIgnored(NS_ERROR_FAILURE);
+    return 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);
 
@@ -1808,61 +1802,63 @@ HTMLEditRules::WillInsertParagraphSepara
     }
   }
 
   // If we cannot insert a <p>/<div> element at the selection, we should insert
   // a <br> element instead.
   if (insertBRElement) {
     nsresult rv = InsertBRElement(atStartOfSelection);
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      return EditActionIgnored(rv);
-    }
-    return EditActionHandled();
+      return rv;
+    }
+    *aHandled = true;
+    return NS_OK;
   }
 
   if (host == blockParent && separator != ParagraphSeparator::br) {
     // Insert a new block first
     MOZ_ASSERT(separator == ParagraphSeparator::div ||
                separator == ParagraphSeparator::p);
     // MakeBasicBlock() creates AutoSelectionRestorer.
     // Therefore, even if it returns NS_OK, editor might have been destroyed
     // at restoring Selection.
     nsresult rv = MakeBasicBlock(ParagraphSeparatorElement(separator));
     if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED) ||
         NS_WARN_IF(!CanHandleEditAction())) {
-      return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+      return 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),
                          "HTMLEditRules::MakeBasicBlock() failed");
 
     firstRange = SelectionRefPtr()->GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
-      return EditActionIgnored(NS_ERROR_FAILURE);
+      return NS_ERROR_FAILURE;
     }
 
     atStartOfSelection = firstRange->StartRef();
     if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
-      return EditActionIgnored(NS_ERROR_FAILURE);
+      return NS_ERROR_FAILURE;
     }
     MOZ_ASSERT(atStartOfSelection.IsSetAndValid());
 
     blockParent =
       HTMLEditor::GetBlock(*atStartOfSelection.GetContainer(), host);
     if (NS_WARN_IF(!blockParent)) {
-      return EditActionIgnored(NS_ERROR_UNEXPECTED);
+      return NS_ERROR_UNEXPECTED;
     }
     if (NS_WARN_IF(blockParent == host)) {
       // Didn't create a new block for some reason, fall back to <br>
       rv = InsertBRElement(atStartOfSelection);
       if (NS_WARN_IF(NS_FAILED(rv))) {
-        return EditActionIgnored(rv);
-      }
-      return EditActionHandled();
+        return rv;
+      }
+      *aHandled = true;
+      return NS_OK;
     }
     // Now, mNewBlock 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., MakeBasicBlock() may wrap following
     // inline elements of a <br> element which is next sibling of container
     // of the caret.  So, we need to adjust mNewBlock here for avoiding
     // jumping caret to odd position.
@@ -1875,47 +1871,49 @@ HTMLEditRules::WillInsertParagraphSepara
   // make block have a line.  Then code further below will put in a second br.)
   if (IsEmptyBlockElement(*blockParent, IgnoreSingleBR::eNo)) {
     AutoEditorDOMPointChildInvalidator lockOffset(atStartOfSelection);
     EditorRawDOMPoint endOfBlockParent;
     endOfBlockParent.SetToEndOf(blockParent);
     RefPtr<Element> brElement =
       HTMLEditorRef().InsertBrElementWithTransaction(endOfBlockParent);
     if (NS_WARN_IF(!CanHandleEditAction())) {
-      return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+      return NS_ERROR_EDITOR_DESTROYED;
     }
     if (NS_WARN_IF(!brElement)) {
-      return EditActionIgnored(NS_ERROR_FAILURE);
+      return NS_ERROR_FAILURE;
     }
   }
 
   nsCOMPtr<Element> listItem = IsInListItem(blockParent);
   if (listItem && listItem != host) {
     nsresult rv =
       ReturnInListItem(*listItem, *atStartOfSelection.GetContainer(),
                        atStartOfSelection.Offset());
     if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
-      return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+      return NS_ERROR_EDITOR_DESTROYED;
     }
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
       "Failed to insert break into list item");
-    return EditActionHandled();
+    *aHandled = true;
+    return NS_OK;
   }
 
   if (HTMLEditUtils::IsHeader(*blockParent)) {
     // Headers: close (or split) header
     nsresult rv =
       ReturnInHeader(*blockParent, *atStartOfSelection.GetContainer(),
                      atStartOfSelection.Offset());
     if (NS_WARN_IF(rv == NS_ERROR_EDITOR_DESTROYED)) {
-      return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+      return NS_ERROR_EDITOR_DESTROYED;
     }
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
       "Failed to handle insertParagraph in the heading element");
-    return EditActionHandled();
+    *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
   //     Gmail.  So, let's use traditional odd behavior only when the default
   //     paragraph separator is <br>.  Otherwise, take consistent behavior
@@ -1923,37 +1921,41 @@ HTMLEditRules::WillInsertParagraphSepara
   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 = ReturnInParagraph(*blockParent);
     if (NS_WARN_IF(result.Failed())) {
-      return result;
-    }
+      return result.Rv();
+    }
+    *aHandled = result.Handled();
+    *aCancel = result.Canceled();
     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;
+      return NS_OK;
     }
     // Fall through, if ReturnInParagraph() didn't handle it.
-    MOZ_ASSERT(!result.Canceled(),
-               "ReturnInParagraph canceled this edit action, "
-               "WillInsertBreak() needs to handle such case");
+    MOZ_ASSERT(!*aCancel, "ReturnInParagraph canceled this edit action, "
+                          "WillInsertBreak() needs to handle such case");
   }
 
   // If nobody handles this edit action, let's insert new <br> at the selection.
+  MOZ_ASSERT(!*aHandled, "Reached last resort of WillInsertBreak() "
+                         "after the edit action is handled");
   rv = InsertBRElement(atStartOfSelection);
+  *aHandled = true;
   if (NS_WARN_IF(NS_FAILED(rv))) {
-    return EditActionIgnored(rv);
-  }
-  return EditActionHandled();
+    return rv;
+  }
+  return NS_OK;
 }
 
 nsresult
 HTMLEditRules::InsertBRElement(const EditorDOMPoint& aPointToBreak)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   if (NS_WARN_IF(!aPointToBreak.IsSet())) {
@@ -2094,30 +2096,34 @@ HTMLEditRules::InsertBRElement(const Edi
     return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(error.Failed())) {
     return error.StealNSResult();
   }
   return NS_OK;
 }
 
-EditActionResult
-HTMLEditRules::SplitMailCites()
-{
-  MOZ_ASSERT(IsEditorDataAvailable());
+nsresult
+HTMLEditRules::SplitMailCites(bool* aHandled)
+{
+  MOZ_ASSERT(IsEditorDataAvailable());
+
+  if (NS_WARN_IF(!aHandled)) {
+    return NS_ERROR_INVALID_ARG;
+  }
 
   EditorRawDOMPoint pointToSplit(EditorBase::GetStartPoint(*SelectionRefPtr()));
   if (NS_WARN_IF(!pointToSplit.IsSet())) {
-    return EditActionIgnored(NS_ERROR_FAILURE);
+    return NS_ERROR_FAILURE;
   }
 
   RefPtr<Element> citeNode =
     GetTopEnclosingMailCite(*pointToSplit.GetContainer());
   if (!citeNode) {
-    return EditActionIgnored();
+    return NS_OK;
   }
 
   // If our selection is just before a break, nudge it to be just after it.
   // This does two things for us.  It saves us the trouble of having to add
   // a break here ourselves to preserve the "blockness" of the inline span
   // mailquote (in the inline case), and :
   // it means the break won't end up making an empty line that happens to be
   // inside a mailquote (in either inline or block case).
@@ -2134,28 +2140,28 @@ HTMLEditRules::SplitMailCites()
       visNode != citeNode && citeNode->Contains(visNode)) {
     pointToSplit.Set(visNode);
     DebugOnly<bool> advanced = pointToSplit.AdvanceOffset();
     NS_WARNING_ASSERTION(advanced,
       "Failed to advance offset to after the visible node");
   }
 
   if (NS_WARN_IF(!pointToSplit.GetContainerAsContent())) {
-    return EditActionIgnored(NS_ERROR_FAILURE);
+    return NS_ERROR_FAILURE;
   }
 
   SplitNodeResult splitCiteNodeResult =
     HTMLEditorRef().SplitNodeDeepWithTransaction(
                       *citeNode, pointToSplit,
                       SplitAtEdges::eDoNotCreateEmptyContainer);
   if (NS_WARN_IF(!CanHandleEditAction())) {
-    return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+    return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(splitCiteNodeResult.Failed())) {
-    return EditActionIgnored(splitCiteNodeResult.Rv());
+    return splitCiteNodeResult.Rv();
   }
   pointToSplit.Clear();
 
   // Add an invisible <br> to the end of current cite node (If new left cite
   // has not been created, we're at the end of it.  Otherwise, we're still at
   // the right node) if it was a <span> of style="display: block". This is
   // important, since when serializing the cite to plain text, the span which
   // caused the visual break is discarded.  So the added <br> will guarantee
@@ -2175,53 +2181,53 @@ HTMLEditRules::SplitMailCites()
     if (lastChild && !lastChild->IsHTMLElement(nsGkAtoms::br)) {
       // We ignore the result here.
       EditorRawDOMPoint endOfPreviousNodeOfSplitPoint;
       endOfPreviousNodeOfSplitPoint.SetToEndOf(previousNodeOfSplitPoint);
       RefPtr<Element> invisibleBrElement =
         HTMLEditorRef().InsertBrElementWithTransaction(
                           endOfPreviousNodeOfSplitPoint);
       if (NS_WARN_IF(!CanHandleEditAction())) {
-        return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+        return NS_ERROR_EDITOR_DESTROYED;
       }
       NS_WARNING_ASSERTION(invisibleBrElement,
         "Failed to create an invisible <br> element");
     }
   }
 
   // In most cases, <br> should be inserted after current cite.  However, if
   // left cite hasn't been created because the split point was start of the
   // cite node, <br> should be inserted before the current cite.
   EditorRawDOMPoint pointToInsertBrNode(splitCiteNodeResult.SplitPoint());
   RefPtr<Element> brElement =
     HTMLEditorRef().InsertBrElementWithTransaction(pointToInsertBrNode);
   if (NS_WARN_IF(!CanHandleEditAction())) {
-    return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+    return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(!brElement)) {
-    return EditActionIgnored(NS_ERROR_FAILURE);
+    return NS_ERROR_FAILURE;
   }
   // Now, offset of pointToInsertBrNode is invalid.  Let's clear it.
   pointToInsertBrNode.Clear();
 
   // Want selection before the break, and on same line.
   EditorDOMPoint atBrNode(brElement);
   Unused << atBrNode.Offset(); // Needs offset after collapsing the selection.
   ErrorResult error;
   SelectionRefPtr()->SetInterlinePosition(true, error);
   NS_WARNING_ASSERTION(!error.Failed(),
     "Failed to set interline position");
   error = NS_OK;
   SelectionRefPtr()->Collapse(atBrNode, error);
   if (NS_WARN_IF(!CanHandleEditAction())) {
     error.SuppressException();
-    return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+    return NS_ERROR_EDITOR_DESTROYED;
   }
   if (NS_WARN_IF(error.Failed())) {
-    return EditActionIgnored(error.StealNSResult());
+    return error.StealNSResult();
   }
 
   // if citeNode wasn't a block, we might also want another break before it.
   // We need to examine the content both before the br we just added and also
   // just after it.  If we don't have another br or block boundary adjacent,
   // then we will need a 2nd br added to achieve blank line that user expects.
   if (IsInlineNode(*citeNode)) {
     // Use DOM point which we tried to collapse to.
@@ -2243,66 +2249,67 @@ HTMLEditRules::SplitMailCites()
       if (wsType == WSType::normalWS || wsType == WSType::text ||
           wsType == WSType::special ||
           // In case we're at the very end.
           wsType == WSType::thisBlock) {
         brElement =
           HTMLEditorRef().InsertBrElementWithTransaction(
                             pointToCreateNewBrNode);
         if (NS_WARN_IF(!CanHandleEditAction())) {
-          return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+          return NS_ERROR_EDITOR_DESTROYED;
         }
         if (NS_WARN_IF(!brElement)) {
-          return EditActionIgnored(NS_ERROR_FAILURE);
+          return NS_ERROR_FAILURE;
         }
         // Now, those points may be invalid.
         pointToCreateNewBrNode.Clear();
         pointAfterNewBrNode.Clear();
       }
     }
   }
 
   // delete any empty cites
   bool bEmptyCite = false;
   if (previousNodeOfSplitPoint) {
     nsresult rv =
       HTMLEditorRef().IsEmptyNode(previousNodeOfSplitPoint, &bEmptyCite,
                                   true, false);
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      return EditActionIgnored(rv);
+      return rv;
     }
     if (bEmptyCite) {
       rv = HTMLEditorRef().DeleteNodeWithTransaction(*previousNodeOfSplitPoint);
       if (NS_WARN_IF(!CanHandleEditAction())) {
-        return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+        return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
-        return EditActionIgnored(rv);
+        return rv;
       }
     }
   }
 
   if (citeNode) {
     nsresult rv =
       HTMLEditorRef().IsEmptyNode(citeNode, &bEmptyCite, true, false);
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      return EditActionIgnored(rv);
+      return rv;
     }
     if (bEmptyCite) {
       rv = HTMLEditorRef().DeleteNodeWithTransaction(*citeNode);
       if (NS_WARN_IF(!CanHandleEditAction())) {
-        return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+        return NS_ERROR_EDITOR_DESTROYED;
       }
       if (NS_WARN_IF(NS_FAILED(rv))) {
-        return EditActionIgnored(rv);
-      }
-    }
-  }
-
-  return EditActionHandled();
+        return rv;
+      }
+    }
+  }
+
+  *aHandled = true;
+  return NS_OK;
 }
 
 
 nsresult
 HTMLEditRules::WillDeleteSelection(nsIEditor::EDirection aAction,
                                    nsIEditor::EStripWrappers aStripWrappers,
                                    bool* aCancel,
                                    bool* aHandled)
@@ -7003,17 +7010,16 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
                                 EditSubAction aEditSubAction)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // we do one thing for text actions, something else entirely for other
   // actions
   if (aEditSubAction == EditSubAction::eInsertText ||
       aEditSubAction == EditSubAction::eInsertTextComingFromIME ||
-      aEditSubAction == EditSubAction::eInsertLineBreak ||
       aEditSubAction == EditSubAction::eInsertParagraphSeparator ||
       aEditSubAction == EditSubAction::eDeleteText) {
     bool isSpace, isNBSP;
     nsCOMPtr<nsIContent> content =
       aNode.IsContent() ? aNode.AsContent() : nullptr;
     nsCOMPtr<nsIContent> temp;
     int32_t newOffset = aOffset;
     // for text actions, we want to look backwards (or forwards, as
@@ -7254,17 +7260,16 @@ HTMLEditRules::PromoteRange(nsRange& aRa
         startOffset = 0;
         endOffset = block->Length();
       }
     }
   }
 
   if (aEditSubAction == EditSubAction::eInsertText ||
       aEditSubAction == EditSubAction::eInsertTextComingFromIME ||
-      aEditSubAction == EditSubAction::eInsertLineBreak ||
       aEditSubAction == EditSubAction::eInsertParagraphSeparator ||
       aEditSubAction == EditSubAction::eDeleteText) {
      if (!startNode->IsContent() ||
          !endNode->IsContent()) {
        // GetPromotedPoint cannot promote node when action type is text
        // operation and selected node isn't content node.
        return;
      }
--- a/editor/libeditor/HTMLEditRules.h
+++ b/editor/libeditor/HTMLEditRules.h
@@ -95,17 +95,16 @@ public:
 
   // TextEditRules methods
   virtual nsresult Init(TextEditor* aTextEditor) override;
   virtual nsresult DetachEditor() override;
   virtual nsresult BeforeEdit(EditSubAction aEditSubAction,
                               nsIEditor::EDirection aDirection) override;
   virtual nsresult AfterEdit(EditSubAction aEditSubAction,
                              nsIEditor::EDirection aDirection) override;
-  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   virtual nsresult WillDoAction(EditSubActionInfo& aInfo,
                                 bool* aCancel,
                                 bool* aHandled) override;
   virtual nsresult DidDoAction(EditSubActionInfo& aInfo,
                                nsresult aResult) override;
   virtual bool DocumentIsEmpty() override;
 
   /**
@@ -208,22 +207,24 @@ protected:
 
   /**
    * WillLoadHTML() is called before loading enter document from source.
    * This removes bogus node if there is.
    */
   MOZ_MUST_USE nsresult WillLoadHTML();
 
   /**
-   * WillInsertParagraphSeparator() is called when insertParagraph command is
-   * executed or something equivalent.  This method actually tries to insert
-   * new paragraph or <br> element, etc.
+   * WillInsertBreak() is called when insertParagraph command is executed
+   * or something equivalent.  This method actually tries to insert new
+   * paragraph or <br> element, etc.
+   *
+   * @param aCancel             Returns true if target node is not editable.
+   * @param aHandled            Returns true if actually insert new break.
    */
-  MOZ_CAN_RUN_SCRIPT
-  MOZ_MUST_USE EditActionResult WillInsertParagraphSeparator();
+  nsresult WillInsertBreak(bool* aCancel, bool* aHandled);
 
   /**
    * 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.
@@ -238,19 +239,21 @@ protected:
    */
   MOZ_MUST_USE nsresult InsertBRElement(const EditorDOMPoint& aInsertToBreak);
 
   /**
    * SplitMailCites() splits mail-cite elements at start of Selection if
    * Selection starts from inside a mail-cite element.  Of course, if it's
    * necessary, this inserts <br> node to new left nodes or existing right
    * nodes.
+   *
+   * @param aHandled            Returns true if succeeded to split mail-cite
+   *                            elements.
    */
-  MOZ_CAN_RUN_SCRIPT
-  MOZ_MUST_USE EditActionResult SplitMailCites();
+  MOZ_MUST_USE nsresult SplitMailCites(bool* aHandled);
 
   /**
    * Called before deleting selected contents.  This method actually removes
    * selected contents.
    *
    * @param aAction             Direction of the deletion.
    * @param aStripWrappers      Must be eStrip or eNoStrip.
    * @param aCancel             Returns true if the operation is canceled.
--- a/editor/libeditor/HTMLEditor.cpp
+++ b/editor/libeditor/HTMLEditor.cpp
@@ -866,20 +866,20 @@ HTMLEditor::HandleKeyPressEvent(WidgetKe
     }
     case NS_VK_RETURN:
       if (!aKeyboardEvent->IsInputtingLineBreak()) {
         return NS_OK;
       }
       aKeyboardEvent->PreventDefault(); // consumed
       if (aKeyboardEvent->IsShift()) {
         // Only inserts a <br> element.
-        return InsertLineBreakAsAction();
+        return OnInputLineBreak();
       }
       // uses rules to figure out what to insert
-      return InsertParagraphSeparatorAsAction();
+      return OnInputParagraphSeparator();
   }
 
   if (!aKeyboardEvent->IsInputtingText()) {
     // we don't PreventDefault() here or keybindings like control-x won't work
     return NS_OK;
   }
   aKeyboardEvent->PreventDefault();
   nsAutoString str(aKeyboardEvent->mCharCode);
@@ -1117,102 +1117,33 @@ HTMLEditor::UpdateBaseURL()
   // If no base tag, then set baseURL to the document's URL.  This is very
   // important, else relative URLs for links and images are wrong
   if (!nodeList || !nodeList->Item(0)) {
     doc->SetBaseURI(doc->GetDocumentURI());
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
-HTMLEditor::InsertLineBreak()
-{
-  // XPCOM method's InsertLineBreak() should insert paragraph separator in
-  // HTMLEditor.
-  nsresult rv = InsertParagraphSeparatorAsSubAction();
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  return NS_OK;
-}
-
 nsresult
-HTMLEditor::InsertLineBreakAsAction()
+HTMLEditor::OnInputLineBreak()
 {
   AutoEditActionDataSetter editActionData(*this, EditAction::eInsertLineBreak);
   if (NS_WARN_IF(!editActionData.CanHandle())) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
-  // XXX This method may be called by "insertLineBreak" command.  So, using
-  //     TypingTxnName here is odd in such case.
   AutoPlaceholderBatch treatAsOneTransaction(*this, *nsGkAtoms::TypingTxnName);
   nsresult rv = InsertBrElementAtSelectionWithTransaction();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 nsresult
-HTMLEditor::InsertParagraphSeparatorAsAction()
-{
-  AutoEditActionDataSetter editActionData(
-                             *this,
-                             EditAction::eInsertParagraphSeparator);
-  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 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);
-
-  AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
-                                      *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;
-}
-
-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())) {
@@ -1308,17 +1239,17 @@ HTMLEditor::TabInTable(bool inIsShift,
 
 nsresult
 HTMLEditor::InsertBrElementAtSelectionWithTransaction()
 {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
   // calling it text insertion to trigger moz br treatment by rules
   // XXX Why do we use EditSubAction::eInsertText here?  Looks like
-  //     EditSubAction::eInsertLineBreak or EditSubAction::eInsertNode
+  //     EditSubAction::eInsertParagraphSeparator or EditSubAction::eInsertNode
   //     is better.
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this, EditSubAction::eInsertText,
                                       nsIEditor::eNext);
 
   if (!SelectionRefPtr()->IsCollapsed()) {
     nsresult rv = DeleteSelectionAsSubAction(eNone, eStrip);
     if (NS_WARN_IF(NS_FAILED(rv))) {
--- a/editor/libeditor/HTMLEditor.h
+++ b/editor/libeditor/HTMLEditor.h
@@ -134,18 +134,16 @@ public:
   NS_IMETHOD SetFlags(uint32_t aFlags) override;
 
   NS_IMETHOD CanPaste(int32_t aSelectionType, bool* aCanPaste) override;
 
   NS_IMETHOD PasteTransferable(nsITransferable* aTransferable) override;
 
   NS_IMETHOD DeleteNode(nsINode* aNode) override;
 
-  NS_IMETHOD InsertLineBreak() override;
-
   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;
   virtual Element* FindSelectionRoot(nsINode *aNode) const override;
   virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent) override;
@@ -168,26 +166,20 @@ public:
    * Can we paste |aTransferable| or, if |aTransferable| is null, will a call
    * to pasteTransferable later possibly succeed if given an instance of
    * nsITransferable then? True if the doc is modifiable, and, if
    * |aTransfeable| is non-null, we have pasteable data in |aTransfeable|.
    */
   virtual bool CanPasteTransferable(nsITransferable* aTransferable) override;
 
   /**
-   * InsertLineBreakAsAction() is called when user inputs a line break with
+   * OnInputLineBreak() is called when user inputs a line break with
    * Shift + Enter or something.
    */
-  virtual nsresult InsertLineBreakAsAction() override;
-
-  /**
-   * InsertParagraphSeparatorAsAction() is called when user tries to separate
-   * current paragraph with Enter key press in HTMLEditor or something.
-   */
-  nsresult InsertParagraphSeparatorAsAction();
+  nsresult OnInputLineBreak();
 
   /**
    * CreateElementWithDefaults() creates new element whose name is
    * aTagName with some default attributes are set.  Note that this is a
    * public utility method.  I.e., just creates element, not insert it
    * into the DOM tree.
    * NOTE: This is available for internal use too since this does not change
    *       the DOM tree nor undo transactions, and does not refer Selection,
@@ -1001,22 +993,16 @@ protected: // Called by helper classes.
   virtual void
   OnStartToHandleTopLevelEditSubAction(
     EditSubAction aEditSubAction, nsIEditor::EDirection aDirection) override;
   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();
-
   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/libeditor/TextEditRules.cpp
+++ b/editor/libeditor/TextEditRules.cpp
@@ -47,25 +47,21 @@ using namespace dom;
 template CreateElementResult
 TextEditRules::CreateBRInternal(const EditorDOMPoint& aPointToInsert,
                                 bool aCreateMozBR);
 template CreateElementResult
 TextEditRules::CreateBRInternal(const EditorRawDOMPoint& aPointToInsert,
                                 bool aCreateMozBR);
 
 #define CANCEL_OPERATION_IF_READONLY_OR_DISABLED \
-  if (IsReadonly() || IsDisabled()) {\
+  if (IsReadonly() || IsDisabled()) \
+  {                     \
     *aCancel = true; \
-    return NS_OK; \
-  }
-
-#define CANCEL_OPERATION_AND_RETURN_EDIT_ACTION_RESULT_IF_READONLY_OF_DISABLED \
-  if (IsReadonly() || IsDisabled()) { \
-    return EditActionCanceled(NS_OK); \
-  }
+    return NS_OK;       \
+  };
 
 /********************************************************
  * mozilla::TextEditRules
  ********************************************************/
 
 TextEditRules::TextEditRules()
   : mTextEditor(nullptr)
   , mData(nullptr)
@@ -317,27 +313,19 @@ TextEditRules::WillDoAction(EditSubActio
 
   *aCancel = false;
   *aHandled = false;
 
   AutoSafeEditorData setData(*this, *mTextEditor);
 
   // my kingdom for dynamic cast
   switch (aInfo.mEditSubAction) {
-    case EditSubAction::eInsertLineBreak: {
+    case EditSubAction::eInsertParagraphSeparator:
       UndefineCaretBidiLevel();
-      EditActionResult result = WillInsertLineBreak(aInfo.maxLength);
-      if (NS_WARN_IF(result.Failed())) {
-        return result.Rv();
-      }
-      *aCancel = result.Canceled();
-      *aHandled = result.Handled();
-      MOZ_ASSERT(!result.Ignored());
-      return NS_OK;
-    }
+      return WillInsertBreak(aCancel, aHandled, aInfo.maxLength);
     case EditSubAction::eInsertText:
     case EditSubAction::eInsertTextComingFromIME:
       UndefineCaretBidiLevel();
       return WillInsertText(aInfo.mEditSubAction, aCancel, aHandled,
                             aInfo.inString, aInfo.outString,
                             aInfo.maxLength);
     case EditSubAction::eSetText:
       UndefineCaretBidiLevel();
@@ -431,115 +419,66 @@ TextEditRules::WillInsert(bool* aCancel)
     return NS_ERROR_EDITOR_DESTROYED;
   }
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
     "Failed to remove the bogus node");
   mBogusNode = nullptr;
   return NS_OK;
 }
 
-EditActionResult
-TextEditRules::WillInsertLineBreak(int32_t aMaxLength)
+nsresult
+TextEditRules::WillInsertBreak(bool* aCancel,
+                               bool* aHandled,
+                               int32_t aMaxLength)
 {
   MOZ_ASSERT(IsEditorDataAvailable());
-  MOZ_ASSERT(!IsSingleLineEditor());
-
-  CANCEL_OPERATION_AND_RETURN_EDIT_ACTION_RESULT_IF_READONLY_OF_DISABLED
+  if (NS_WARN_IF(!aCancel) || NS_WARN_IF(!aHandled)) {
+    return NS_ERROR_INVALID_ARG;
+  }
+  CANCEL_OPERATION_IF_READONLY_OR_DISABLED
+  *aHandled = false;
+  if (IsSingleLineEditor()) {
+    *aCancel = true;
+  } else {
+    // handle docs with a max length
+    // NOTE, this function copies inString into outString for us.
+    NS_NAMED_LITERAL_STRING(inString, "\n");
+    nsAutoString outString;
+    bool didTruncate;
+    nsresult rv =
+      TruncateInsertionIfNeeded(&inString.AsString(),
+                                &outString, aMaxLength, &didTruncate);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+    if (didTruncate) {
+      *aCancel = true;
+      return NS_OK;
+    }
 
-  // handle docs with a max length
-  // NOTE, this function copies inString into outString for us.
-  NS_NAMED_LITERAL_STRING(inString, "\n");
-  nsAutoString outString;
-  bool didTruncate;
-  nsresult rv =
-    TruncateInsertionIfNeeded(&inString.AsString(),
-                              &outString, aMaxLength, &didTruncate);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return EditActionIgnored(rv);
-  }
-  if (didTruncate) {
-    return EditActionCanceled();
-  }
+    *aCancel = false;
 
-  // if the selection isn't collapsed, delete it.
-  if (!SelectionRefPtr()->IsCollapsed()) {
-    rv = TextEditorRef().DeleteSelectionAsSubAction(nsIEditor::eNone,
-                                                    nsIEditor::eStrip);
-    if (NS_WARN_IF(!CanHandleEditAction())) {
-      return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
+    // if the selection isn't collapsed, delete it.
+    if (!SelectionRefPtr()->IsCollapsed()) {
+      rv = TextEditorRef().DeleteSelectionAsSubAction(nsIEditor::eNone,
+                                                      nsIEditor::eStrip);
+      if (NS_WARN_IF(!CanHandleEditAction())) {
+        return NS_ERROR_EDITOR_DESTROYED;
+      }
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
     }
+
+    rv = WillInsert();
     if (NS_WARN_IF(NS_FAILED(rv))) {
-      return EditActionIgnored(rv);
+      return rv;
     }
   }
-
-  rv = WillInsert();
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return EditActionIgnored(rv);
-  }
-
-  // get the (collapsed) selection location
-  nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0);
-  if (NS_WARN_IF(!firstRange)) {
-    return EditActionIgnored(NS_ERROR_FAILURE);
-  }
-
-  EditorRawDOMPoint pointToInsert(firstRange->StartRef());
-  if (NS_WARN_IF(!pointToInsert.IsSet())) {
-    return EditActionIgnored(NS_ERROR_FAILURE);
-  }
-  MOZ_ASSERT(pointToInsert.IsSetAndValid());
-
-  // Don't put text in places that can't have it.
-  if (!pointToInsert.IsInTextNode() &&
-      !TextEditorRef().CanContainTag(*pointToInsert.GetContainer(),
-                                     *nsGkAtoms::textTagName)) {
-    return EditActionIgnored(NS_ERROR_FAILURE);
-  }
-
-  nsCOMPtr<nsIDocument> doc = TextEditorRef().GetDocument();
-  if (NS_WARN_IF(!doc)) {
-    return EditActionIgnored(NS_ERROR_NOT_INITIALIZED);
-  }
-
-  // Don't change my selection in sub-transactions.
-  AutoTransactionsConserveSelection dontChangeMySelection(TextEditorRef());
-
-  // Insert a linefeed character.
-  EditorRawDOMPoint pointAfterInsertedLineBreak;
-  rv = TextEditorRef().InsertTextWithTransaction(
-                         *doc, NS_LITERAL_STRING("\n"), pointToInsert,
-                         &pointAfterInsertedLineBreak);
-  if (NS_WARN_IF(!pointAfterInsertedLineBreak.IsSet())) {
-    return EditActionIgnored(NS_ERROR_FAILURE);
-  }
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return EditActionIgnored(rv);
-  }
-
-  // set the selection to the correct location
-  MOZ_ASSERT(!pointAfterInsertedLineBreak.GetChild(),
-    "After inserting text into a text node, pointAfterInsertedLineBreak."
-    "GetChild() should be nullptr");
-  rv = SelectionRefPtr()->Collapse(pointAfterInsertedLineBreak);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return EditActionIgnored(rv);
-  }
-
-  // see if we're at the end of the editor range
-  EditorRawDOMPoint endPoint(EditorBase::GetEndPoint(*SelectionRefPtr()));
-  if (endPoint == pointAfterInsertedLineBreak) {
-    // SetInterlinePosition(true) means we want the caret to stick to the
-    // content on the "right".  We want the caret to stick to whatever is
-    // past the break.  This is because the break is on the same line we
-    // were on, but the next content will be on the following line.
-    SelectionRefPtr()->SetInterlinePosition(true, IgnoreErrors());
-  }
-
-  return EditActionHandled();
+  return NS_OK;
 }
 
 nsresult
 TextEditRules::CollapseSelectionToTrailingBRIfNeeded()
 {
   MOZ_ASSERT(IsEditorDataAvailable());
 
   // we only need to execute the stuff below if we are a plaintext editor.
--- a/editor/libeditor/TextEditRules.h
+++ b/editor/libeditor/TextEditRules.h
@@ -180,21 +180,23 @@ protected:
                  const nsAString* inString, nsAString* outString,
                  int32_t aMaxLength);
 
   /**
    * Called before inserting a line break into the editor.
    * This method removes selected text if selection isn't collapsed.
    * Therefore, this might cause destroying the editor.
    *
+   * @param aCancel             Returns true if the operation is canceled.
+   * @param aHandled            Returns true if the edit action is handled.
    * @param aMaxLength          The maximum string length which the editor
    *                            allows to set.
    */
-  MOZ_CAN_RUN_SCRIPT
-  MOZ_MUST_USE EditActionResult WillInsertLineBreak(int32_t aMaxLength);
+  MOZ_MUST_USE nsresult
+  WillInsertBreak(bool* aCancel, bool* aHandled, int32_t aMaxLength);
 
   /**
    * Called before setting text to the text editor.
    * This method may actually set text to it.  Therefore, this might cause
    * destroying the text editor.
    *
    * @param aCancel             Returns true if the operation is canceled.
    * @param aHandled            Returns true if the edit action is handled.
--- a/editor/libeditor/TextEditor.cpp
+++ b/editor/libeditor/TextEditor.cpp
@@ -409,17 +409,17 @@ TextEditor::HandleKeyPressEvent(WidgetKe
       aKeyboardEvent->PreventDefault();
       return OnInputText(NS_LITERAL_STRING("\t"));
     }
     case NS_VK_RETURN:
       if (IsSingleLineEditor() || !aKeyboardEvent->IsInputtingLineBreak()) {
         return NS_OK;
       }
       aKeyboardEvent->PreventDefault();
-      return InsertLineBreakAsAction();
+      return OnInputParagraphSeparator();
   }
 
   if (!aKeyboardEvent->IsInputtingText()) {
     // we don't PreventDefault() here or keybindings like control-x won't work
     return NS_OK;
   }
   aKeyboardEvent->PreventDefault();
   nsAutoString str(aKeyboardEvent->mCharCode);
@@ -438,27 +438,27 @@ TextEditor::OnInputText(const nsAString&
   nsresult rv = InsertTextAsSubAction(aStringToInsert);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 nsresult
-TextEditor::InsertLineBreakAsAction()
+TextEditor::OnInputParagraphSeparator()
 {
-  AutoEditActionDataSetter editActionData(*this, EditAction::eInsertLineBreak);
+  AutoEditActionDataSetter editActionData(
+                             *this,
+                             EditAction::eInsertParagraphSeparator);
   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 = InsertLineBreakAsSubAction();
+  nsresult rv = InsertParagraphSeparatorAsAction();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 template<typename PT, typename CT>
 already_AddRefed<Element>
@@ -1065,62 +1065,119 @@ TextEditor::InsertTextAsSubAction(const 
     return rv;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TextEditor::InsertLineBreak()
 {
-  AutoEditActionDataSetter editActionData(*this, EditAction::eInsertLineBreak);
+  AutoEditActionDataSetter editActionData(
+                             *this,
+                             EditAction::eInsertParagraphSeparator);
   if (NS_WARN_IF(!editActionData.CanHandle())) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
-  AutoPlaceholderBatch treatAsOneTransaction(*this);
-  nsresult rv = InsertLineBreakAsSubAction();
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-  return NS_OK;
+  return InsertParagraphSeparatorAsAction();
 }
 
 nsresult
-TextEditor::InsertLineBreakAsSubAction()
+TextEditor::InsertParagraphSeparatorAsAction()
 {
   MOZ_ASSERT(IsEditActionDataAvailable());
 
   if (!mRules) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   // Protect the edit rules object from dying
   RefPtr<TextEditRules> rules(mRules);
 
+  AutoPlaceholderBatch treatAsOneTransaction(*this);
   AutoTopLevelEditSubActionNotifier maybeTopLevelEditSubAction(
                                       *this,
-                                      EditSubAction::eInsertLineBreak,
+                                      EditSubAction::eInsertParagraphSeparator,
                                       nsIEditor::eNext);
 
-  EditSubActionInfo subActionInfo(EditSubAction::eInsertLineBreak);
+  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))) {
+    // XXX DidDoAction() won't be called when WillDoAction() returns error.
+    //     Perhaps, we should move the code between WillDoAction() and
+    //     DidDoAction() to a new method and guarantee that DidDoAction() is
+    //     always called after WillDoAction().
     return rv;
   }
-  return NS_OK;
+
+  if (!cancel && !handled) {
+    // get the (collapsed) selection location
+    nsRange* firstRange = SelectionRefPtr()->GetRangeAt(0);
+    if (NS_WARN_IF(!firstRange)) {
+      return NS_ERROR_FAILURE;
+    }
+
+    EditorRawDOMPoint pointToInsert(firstRange->StartRef());
+    if (NS_WARN_IF(!pointToInsert.IsSet())) {
+      return NS_ERROR_FAILURE;
+    }
+    MOZ_ASSERT(pointToInsert.IsSetAndValid());
+
+    // don't put text in places that can't have it
+    if (!pointToInsert.IsInTextNode() &&
+        !CanContainTag(*pointToInsert.GetContainer(),
+                       *nsGkAtoms::textTagName)) {
+      return NS_ERROR_FAILURE;
+    }
+
+    // we need to get the doc
+    nsCOMPtr<nsIDocument> doc = GetDocument();
+    if (NS_WARN_IF(!doc)) {
+      return NS_ERROR_NOT_INITIALIZED;
+    }
+
+    // don't change my selection in subtransactions
+    AutoTransactionsConserveSelection dontChangeMySelection(*this);
+
+    // insert a linefeed character
+    EditorRawDOMPoint pointAfterInsertedLineBreak;
+    rv = InsertTextWithTransaction(*doc, NS_LITERAL_STRING("\n"), pointToInsert,
+                                   &pointAfterInsertedLineBreak);
+    if (NS_WARN_IF(!pointAfterInsertedLineBreak.IsSet())) {
+      rv = NS_ERROR_NULL_POINTER; // don't return here, so DidDoAction is called
+    }
+    if (NS_SUCCEEDED(rv)) {
+      // set the selection to the correct location
+      MOZ_ASSERT(!pointAfterInsertedLineBreak.GetChild(),
+        "After inserting text into a text node, pointAfterInsertedLineBreak."
+        "GetChild() should be nullptr");
+      rv = SelectionRefPtr()->Collapse(pointAfterInsertedLineBreak);
+      if (NS_SUCCEEDED(rv)) {
+        // see if we're at the end of the editor range
+        EditorRawDOMPoint endPoint(EditorBase::GetEndPoint(*SelectionRefPtr()));
+        if (endPoint == pointAfterInsertedLineBreak) {
+          // SetInterlinePosition(true) means we want the caret to stick to the
+          // content on the "right".  We want the caret to stick to whatever is
+          // past the break.  This is because the break is on the same line we
+          // were on, but the next content will be on the following line.
+          SelectionRefPtr()->SetInterlinePosition(true, IgnoreErrors());
+        }
+      }
+    }
+  }
+
+  if (!cancel) {
+    // post-process, always called if WillInsertBreak didn't return cancel==true
+    rv = rules->DidDoAction(subActionInfo, rv);
+    NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                         "TextEditRules::DidDoAction() failed");
+  }
+  return rv;
 }
 
 nsresult
 TextEditor::SetText(const nsAString& aString)
 {
   MOZ_ASSERT(aString.FindChar(static_cast<char16_t>('\r')) == kNotFound);
 
   AutoEditActionDataSetter editActionData(*this, EditAction::eSetText);
--- a/editor/libeditor/TextEditor.h
+++ b/editor/libeditor/TextEditor.h
@@ -182,20 +182,20 @@ public:
    * @param aString             The string to set.
    * @param aReplaceRange       The range to be replaced.
    *                            If nullptr, all contents will be replaced.
    */
   nsresult ReplaceTextAsAction(const nsAString& aString,
                                nsRange* aReplaceRange = nullptr);
 
   /**
-   * InsertLineBreakAsAction() is called when user inputs a line break with
-   * Enter or something.
+   * OnInputParagraphSeparator() is called when user tries to separate current
+   * paragraph with Enter key press or something.
    */
-  virtual nsresult InsertLineBreakAsAction();
+  nsresult OnInputParagraphSeparator();
 
   /**
    * OnCompositionStart() is called when editor receives eCompositionStart
    * event which should be handled in this editor.
    */
   nsresult OnCompositionStart(WidgetCompositionEvent& aCompositionStartEvent);
 
   /**
@@ -371,20 +371,23 @@ protected: // Shouldn't be used by frien
   /**
    * OnInputText() is called when user inputs text with keyboard or something.
    *
    * @param aStringToInsert     The string to insert.
    */
   nsresult OnInputText(const nsAString& aStringToInsert);
 
   /**
-   * InsertLineBreakAsSubAction() inserts a line break, i.e., \n if it's
-   * TextEditor or <br> if it's HTMLEditor.
+   * InsertParagraphSeparatorAsAction() inserts a line break if it's TextEditor
+   * or inserts new paragraph if it's HTMLEditor and it's possible.
+   * Although, this method is implementation of
+   * nsIPlaintextEditor.insertLineBreak(), this treats the input is an edit
+   * action.
    */
-  nsresult InsertLineBreakAsSubAction();
+  nsresult InsertParagraphSeparatorAsAction();
 
   nsresult InsertTextAt(const nsAString& aStringToInsert,
                         nsINode* aDestinationNode,
                         int32_t aDestOffset,
                         bool aDoDeleteSelection);
 
   virtual nsresult InsertFromDataTransfer(dom::DataTransfer* aDataTransfer,
                                           int32_t aIndex,