Bug 1457083 - part 4: Replace mHTMLEditor in HTMLEditRules with HTMLEditorRef() r?m_kato draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 27 Apr 2018 01:42:22 +0900
changeset 797731 e2d749d9b3b3a95d064f897de76818e173d74a62
parent 797659 64f7cf6bcfceb598849572277a48c057573d6493
child 797732 24497df2e459a743efbe7038c2a2fb979988115a
push id110553
push usermasayuki@d-toybox.com
push dateMon, 21 May 2018 14:13:13 +0000
reviewersm_kato
bugs1457083, 1454900
milestone62.0a1
Bug 1457083 - part 4: Replace mHTMLEditor in HTMLEditRules with HTMLEditorRef() r?m_kato Although, this patch removes first check of mHTMLEditor in each method. If this causes some security issues, we should add now. However, automated tests don't indicate it. Anyway, it should be fixed by bug 1454900 in same cycle. MozReview-Commit-ID: 3LAtOQHyR5J
editor/libeditor/HTMLEditRules.cpp
editor/libeditor/TextEditRulesBidi.cpp
--- a/editor/libeditor/HTMLEditRules.cpp
+++ b/editor/libeditor/HTMLEditRules.cpp
@@ -456,23 +456,24 @@ HTMLEditRules::AfterEdit(EditAction aAct
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::AfterEditInner(EditAction aAction,
                               nsIEditor::EDirection aDirection)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   ConfirmSelectionInBody();
   if (aAction == EditAction::ignore) {
     return NS_OK;
   }
 
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<Selection> selection = mHTMLEditor->GetSelection();
+  RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
   NS_ENSURE_STATE(selection);
 
   nsCOMPtr<nsINode> rangeStartContainer, rangeEndContainer;
   uint32_t rangeStartOffset = 0, rangeEndOffset = 0;
   // do we have a real range to act on?
   bool bDamagedRange = false;
   if (mDocChangeRange) {
     rangeStartContainer = mDocChangeRange->GetStartContainer();
@@ -483,18 +484,17 @@ HTMLEditRules::AfterEditInner(EditAction
       bDamagedRange = true;
     }
   }
 
   if (bDamagedRange && !((aAction == EditAction::undo) ||
                          (aAction == EditAction::redo))) {
     // don't let any txns in here move the selection around behind our back.
     // Note that this won't prevent explicit selection setting from working.
-    NS_ENSURE_STATE(mHTMLEditor);
-    AutoTransactionsConserveSelection dontChangeMySelection(mHTMLEditor);
+    AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
 
     // expand the "changed doc range" as needed
     PromoteRange(*mDocChangeRange, aAction);
 
     // if we did a ranged deletion or handling backspace key, make sure we have
     // a place to put caret.
     // Note we only want to do this if the overall operation was deletion,
     // not if deletion was done along the way for EditAction::loadHTML, EditAction::insertText, etc.
@@ -505,19 +505,20 @@ HTMLEditRules::AfterEditInner(EditAction
     }
 
     // add in any needed <br>s, and remove any unneeded ones.
     AdjustSpecialBreaks();
 
     // merge any adjacent text nodes
     if (aAction != EditAction::insertText &&
         aAction != EditAction::insertIMEText) {
-      NS_ENSURE_STATE(mHTMLEditor);
-      nsresult rv = mHTMLEditor->CollapseAdjacentTextNodes(mDocChangeRange);
-      NS_ENSURE_SUCCESS(rv, rv);
+      nsresult rv = HTMLEditorRef().CollapseAdjacentTextNodes(mDocChangeRange);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
     }
 
     // clean up any empty nodes in the selection
     nsresult rv = RemoveEmptyNodes();
     NS_ENSURE_SUCCESS(rv, rv);
 
     // attempt to transform any unneeded nbsp's into spaces after doing various operations
     if (aAction == EditAction::insertText ||
@@ -525,26 +526,24 @@ HTMLEditRules::AfterEditInner(EditAction
         aAction == EditAction::deleteSelection ||
         aAction == EditAction::insertBreak ||
         aAction == EditAction::htmlPaste ||
         aAction == EditAction::loadHTML) {
       rv = AdjustWhitespace(selection);
       NS_ENSURE_SUCCESS(rv, rv);
 
       // also do this for original selection endpoints.
-      NS_ENSURE_STATE(mHTMLEditor);
       NS_ENSURE_STATE(mRangeItem->mStartContainer);
       NS_ENSURE_STATE(mRangeItem->mEndContainer);
-      WSRunObject(mHTMLEditor, mRangeItem->mStartContainer,
+      WSRunObject(&HTMLEditorRef(), mRangeItem->mStartContainer,
                   mRangeItem->mStartOffset).AdjustWhitespace();
       // we only need to handle old selection endpoint if it was different from start
       if (mRangeItem->mStartContainer != mRangeItem->mEndContainer ||
           mRangeItem->mStartOffset != mRangeItem->mEndOffset) {
-        NS_ENSURE_STATE(mHTMLEditor);
-        WSRunObject(mHTMLEditor, mRangeItem->mEndContainer,
+        WSRunObject(&HTMLEditorRef(), mRangeItem->mEndContainer,
                     mRangeItem->mEndOffset).AdjustWhitespace();
       }
     }
 
     // if we created a new block, make sure selection lands in it
     if (mNewBlock) {
       rv = PinSelectionToNewBlock(selection);
       mNewBlock = nullptr;
@@ -561,36 +560,35 @@ HTMLEditRules::AfterEditInner(EditAction
       NS_ENSURE_SUCCESS(rv, rv);
     }
 
     // check for any styles which were removed inappropriately
     if (aAction == EditAction::insertText ||
         aAction == EditAction::insertIMEText ||
         aAction == EditAction::deleteSelection ||
         IsStyleCachePreservingAction(aAction)) {
-      NS_ENSURE_STATE(mHTMLEditor);
-      mHTMLEditor->mTypeInState->UpdateSelState(selection);
+      HTMLEditorRef().mTypeInState->UpdateSelState(selection);
       rv = ReapplyCachedStyles();
       NS_ENSURE_SUCCESS(rv, rv);
       ClearCachedStyles();
     }
   }
 
-  NS_ENSURE_STATE(mHTMLEditor);
-
   nsresult rv =
-    mHTMLEditor->HandleInlineSpellCheck(
-                   aAction, *selection,
-                   mRangeItem->mStartContainer,
-                   mRangeItem->mStartOffset,
-                   rangeStartContainer,
-                   rangeStartOffset,
-                   rangeEndContainer,
-                   rangeEndOffset);
-  NS_ENSURE_SUCCESS(rv, rv);
+    HTMLEditorRef().HandleInlineSpellCheck(
+                      aAction, *selection,
+                      mRangeItem->mStartContainer,
+                      mRangeItem->mStartOffset,
+                      rangeStartContainer,
+                      rangeStartOffset,
+                      rangeEndContainer,
+                      rangeEndOffset);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   // detect empty doc
   rv = CreateBogusNodeIfNeeded(selection);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // adjust selection HINT if needed
   if (!mDidExplicitlySetInterline) {
     CheckInterlinePosition(*selection);
@@ -1314,23 +1312,21 @@ HTMLEditRules::GetFormatString(nsINode* 
   }
   return NS_OK;
 }
 
 void
 HTMLEditRules::WillInsert(Selection& aSelection,
                           bool* aCancel)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aCancel);
 
   TextEditRules::WillInsert(aSelection, aCancel);
 
-  NS_ENSURE_TRUE_VOID(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   // Adjust selection to prevent insertion after a moz-BR.  This next only
   // works for collapsed selections right now, because selection is a pain to
   // work with when not collapsed.  (no good way to extend start or end of
   // selection), so we ignore those types of selections.
   if (!aSelection.IsCollapsed()) {
     return;
   }
 
@@ -1344,21 +1340,21 @@ HTMLEditRules::WillInsert(Selection& aSe
   EditorRawDOMPoint atStartOfSelection(firstRange->StartRef());
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return;
   }
   MOZ_ASSERT(atStartOfSelection.IsSetAndValid());
 
   // Get prior node
   nsCOMPtr<nsIContent> priorNode =
-    htmlEditor->GetPreviousEditableHTMLNode(atStartOfSelection);
+    HTMLEditorRef().GetPreviousEditableHTMLNode(atStartOfSelection);
   if (priorNode && TextEditUtils::IsMozBR(priorNode)) {
     RefPtr<Element> block1 =
-      htmlEditor->GetBlock(*atStartOfSelection.GetContainer());
-    RefPtr<Element> block2 = htmlEditor->GetBlockNodeParent(priorNode);
+      HTMLEditorRef().GetBlock(*atStartOfSelection.GetContainer());
+    RefPtr<Element> block2 = HTMLEditorRef().GetBlockNodeParent(priorNode);
 
     if (block1 && block1 == block2) {
       // If we are here then the selection is right after a mozBR that is in
       // the same block as the selection.  We need to move the selection start
       // to be before the mozBR.
       EditorRawDOMPoint point(priorNode);
       IgnoredErrorResult error;
       aSelection.Collapse(point, error);
@@ -1386,48 +1382,45 @@ nsresult
 HTMLEditRules::WillInsertText(EditAction aAction,
                               Selection* aSelection,
                               bool* aCancel,
                               bool* aHandled,
                               const nsAString* inString,
                               nsAString* outString,
                               int32_t aMaxLength)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (NS_WARN_IF(!aSelection) ||
       NS_WARN_IF(!aCancel) ||
       NS_WARN_IF(!aHandled)) {
     return NS_ERROR_NULL_POINTER;
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   // initialize out param
   *aCancel = false;
   *aHandled = true;
   // If the selection isn't collapsed, delete it.  Don't delete existing inline
   // tags, because we're hopefully going to insert text (bug 787432).
   if (!aSelection->IsCollapsed()) {
     nsresult rv =
-      htmlEditor->DeleteSelectionAsAction(nsIEditor::eNone,
-                                          nsIEditor::eNoStrip);
+      HTMLEditorRef().DeleteSelectionAsAction(nsIEditor::eNone,
+                                              nsIEditor::eNoStrip);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   WillInsert(*aSelection, aCancel);
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
 
   // we need to get the doc
-  nsCOMPtr<nsIDocument> doc = htmlEditor->GetDocument();
+  nsCOMPtr<nsIDocument> doc = HTMLEditorRef().GetDocument();
   if (NS_WARN_IF(!doc)) {
     return NS_ERROR_FAILURE;
   }
 
   // for every property that is set, insert a new inline style node
   nsresult rv = CreateStyleForInsertText(*aSelection, *doc);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
@@ -1441,43 +1434,44 @@ HTMLEditRules::WillInsertText(EditAction
   EditorDOMPoint pointToInsert(firstRange->StartRef());
   if (NS_WARN_IF(!pointToInsert.IsSet())) {
     return NS_ERROR_FAILURE;
   }
   MOZ_ASSERT(pointToInsert.IsSetAndValid());
 
   // dont put text in places that can't have it
   if (!EditorBase::IsTextNode(pointToInsert.GetContainer()) &&
-      !htmlEditor->CanContainTag(*pointToInsert.GetContainer(),
-                                 *nsGkAtoms::textTagName)) {
+      !HTMLEditorRef().CanContainTag(*pointToInsert.GetContainer(),
+                                     *nsGkAtoms::textTagName)) {
     return NS_ERROR_FAILURE;
   }
 
   if (aAction == EditAction::insertIMEText) {
     // Right now the WSRunObject code bails on empty strings, but IME needs
     // the InsertTextWithTransaction() call to still happen since empty strings
     // are meaningful there.
     // If there is one or more IME selections, its minimum offset should be
     // the insertion point.
     int32_t IMESelectionOffset =
-      htmlEditor->GetIMESelectionStartOffsetIn(pointToInsert.GetContainer());
+      HTMLEditorRef().GetIMESelectionStartOffsetIn(
+                        pointToInsert.GetContainer());
     if (IMESelectionOffset >= 0) {
       pointToInsert.Set(pointToInsert.GetContainer(), IMESelectionOffset);
     }
 
     if (inString->IsEmpty()) {
-      rv = htmlEditor->InsertTextWithTransaction(
-                         *doc, *inString, EditorRawDOMPoint(pointToInsert));
+      rv = HTMLEditorRef().InsertTextWithTransaction(
+                             *doc, *inString, EditorRawDOMPoint(pointToInsert));
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       return NS_OK;
     }
 
-    WSRunObject wsObj(htmlEditor, pointToInsert);
+    WSRunObject wsObj(&HTMLEditorRef(), pointToInsert);
     rv = wsObj.InsertText(*doc, *inString, pointToInsert);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
 
   // aAction == kInsertText
@@ -1491,24 +1485,24 @@ HTMLEditRules::WillInsertText(EditAction
 
   // turn off the edit listener: we know how to
   // build the "doc changed range" ourselves, and it's
   // must faster to do it once here than to track all
   // the changes one at a time.
   AutoLockListener lockit(&mListenerEnabled);
 
   // don't change my selection in subtransactions
-  AutoTransactionsConserveSelection dontChangeMySelection(htmlEditor);
+  AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
   nsAutoString tString(*inString);
   const char16_t *unicodeBuf = tString.get();
   int32_t pos = 0;
   NS_NAMED_LITERAL_STRING(newlineStr, LFSTR);
 
   {
-    AutoTrackDOMPoint tracker(htmlEditor->mRangeUpdater, &pointToInsert);
+    AutoTrackDOMPoint tracker(HTMLEditorRef().mRangeUpdater, &pointToInsert);
 
     // for efficiency, break out the pre case separately.  This is because
     // its a lot cheaper to search the input string for only newlines than
     // it is to search for both tabs and newlines.
     if (isPRE || IsPlaintextEditor()) {
       while (unicodeBuf && pos != -1 &&
              pos < static_cast<int32_t>(inString->Length())) {
         int32_t oldPos = pos;
@@ -1526,19 +1520,19 @@ HTMLEditRules::WillInsertText(EditAction
           pos = tString.Length();
         }
 
         nsDependentSubstring subStr(tString, oldPos, subStrLen);
 
         // is it a return?
         if (subStr.Equals(newlineStr)) {
           RefPtr<Element> brElement =
-            htmlEditor->InsertBrElementWithTransaction(*aSelection,
-                                                       currentPoint,
-                                                       nsIEditor::eNone);
+            HTMLEditorRef().InsertBrElementWithTransaction(*aSelection,
+                                                           currentPoint,
+                                                           nsIEditor::eNone);
           if (NS_WARN_IF(!brElement)) {
             return NS_ERROR_FAILURE;
           }
           pos++;
           if (brElement->GetNextSibling()) {
             pointToInsert.Set(brElement->GetNextSibling());
           } else {
             pointToInsert.SetToEndOf(currentPoint.GetContainer());
@@ -1550,20 +1544,20 @@ HTMLEditRules::WillInsertText(EditAction
           DebugOnly<bool> advanced = currentPoint.AdvanceOffset();
           NS_WARNING_ASSERTION(advanced,
             "Failed to advance offset after the new <br> element");
           NS_WARNING_ASSERTION(currentPoint == pointToInsert,
             "Perhaps, <br> element position has been moved to different point "
             "by mutation observer");
         } else {
           EditorRawDOMPoint pointAfterInsertedString;
-          rv = htmlEditor->InsertTextWithTransaction(
-                             *doc, subStr,
-                             EditorRawDOMPoint(currentPoint),
-                             &pointAfterInsertedString);
+          rv = HTMLEditorRef().InsertTextWithTransaction(
+                                 *doc, subStr,
+                                 EditorRawDOMPoint(currentPoint),
+                                 &pointAfterInsertedString);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
           currentPoint = pointAfterInsertedString;
           pointToInsert = pointAfterInsertedString;
         }
       }
     } else {
@@ -1583,17 +1577,17 @@ HTMLEditRules::WillInsertText(EditAction
             subStrLen = 1;
           }
         } else {
           subStrLen = tString.Length() - oldPos;
           pos = tString.Length();
         }
 
         nsDependentSubstring subStr(tString, oldPos, subStrLen);
-        WSRunObject wsObj(htmlEditor, currentPoint);
+        WSRunObject wsObj(&HTMLEditorRef(), currentPoint);
 
         // is it a tab?
         if (subStr.Equals(tabStr)) {
           EditorRawDOMPoint pointAfterInsertedSpaces;
           rv = wsObj.InsertText(*doc, spacesStr, currentPoint,
                                 &pointAfterInsertedSpaces);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
@@ -1672,45 +1666,42 @@ HTMLEditRules::WillInsertText(EditAction
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::WillLoadHTML(Selection* aSelection,
                             bool* aCancel)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   NS_ENSURE_TRUE(aSelection && aCancel, NS_ERROR_NULL_POINTER);
 
   *aCancel = false;
 
   // Delete mBogusNode if it exists. If we really need one,
   // it will be added during post-processing in AfterEditInner().
 
   if (mBogusNode) {
-    if (NS_WARN_IF(!mHTMLEditor)) {
-      return NS_ERROR_UNEXPECTED;
-    }
-    RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-    DebugOnly<nsresult> rv = htmlEditor->DeleteNodeWithTransaction(*mBogusNode);
+    DebugOnly<nsresult> rv =
+      HTMLEditorRef().DeleteNodeWithTransaction(*mBogusNode);
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
       "Failed to remove the bogus node");
     mBogusNode = nullptr;
   }
 
   return NS_OK;
 }
 
 bool
 HTMLEditRules::CanContainParagraph(Element& aElement) const
 {
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return false;
-  }
-
-  if (mHTMLEditor->CanContainTag(aElement, *nsGkAtoms::p)) {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
+  if (HTMLEditorRef().CanContainTag(aElement, *nsGkAtoms::p)) {
     return true;
   }
 
   // Even if the element cannot have a <p> element as a child, it can contain
   // <p> element as a descendant if it's one of the following elements.
   if (aElement.IsAnyOfHTMLElements(nsGkAtoms::ol,
                                    nsGkAtoms::ul,
                                    nsGkAtoms::dl,
@@ -1727,27 +1718,27 @@ HTMLEditRules::CanContainParagraph(Eleme
   return false;
 }
 
 nsresult
 HTMLEditRules::WillInsertBreak(Selection& aSelection,
                                bool* aCancel,
                                bool* aHandled)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   MOZ_ASSERT(aCancel && aHandled);
   *aCancel = false;
   *aHandled = false;
 
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   // If the selection isn't collapsed, delete it.
   if (!aSelection.IsCollapsed()) {
     nsresult rv =
-      htmlEditor->DeleteSelectionAsAction(nsIEditor::eNone, nsIEditor::eStrip);
+      HTMLEditorRef().DeleteSelectionAsAction(nsIEditor::eNone,
+                                              nsIEditor::eStrip);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   WillInsert(aSelection, aCancel);
 
   // Initialize out param.  We want to ignore result of WillInsert().
@@ -1771,36 +1762,36 @@ HTMLEditRules::WillInsertBreak(Selection
 
   EditorDOMPoint atStartOfSelection(firstRange->StartRef());
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return NS_ERROR_FAILURE;
   }
   MOZ_ASSERT(atStartOfSelection.IsSetAndValid());
 
   // Do nothing if the node is read-only
-  if (!htmlEditor->IsModifiableNode(atStartOfSelection.GetContainer())) {
+  if (!HTMLEditorRef().IsModifiableNode(atStartOfSelection.GetContainer())) {
     *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>.
-  nsCOMPtr<Element> host = htmlEditor->GetActiveEditingHost();
+  RefPtr<Element> host = HTMLEditorRef().GetActiveEditingHost();
   if (NS_WARN_IF(!host)) {
     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);
 
-  ParagraphSeparator separator = htmlEditor->GetDefaultParagraphSeparator();
+  ParagraphSeparator separator = HTMLEditorRef().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.
     insertBRElement = true;
   }
   // If only the editing host is block, and the default paragraph separator
@@ -1888,17 +1879,18 @@ HTMLEditRules::WillInsertBreak(Selection
   // 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 (IsEmptyBlockElement(*blockParent, IgnoreSingleBR::eNo)) {
     AutoEditorDOMPointChildInvalidator lockOffset(atStartOfSelection);
     EditorRawDOMPoint endOfBlockParent;
     endOfBlockParent.SetToEndOf(blockParent);
     RefPtr<Element> brElement =
-      htmlEditor->InsertBrElementWithTransaction(aSelection, endOfBlockParent);
+      HTMLEditorRef().InsertBrElementWithTransaction(aSelection,
+                                                     endOfBlockParent);
     if (NS_WARN_IF(!brElement)) {
       return NS_ERROR_FAILURE;
     }
   }
 
   nsCOMPtr<Element> listItem = IsInListItem(blockParent);
   if (listItem && listItem != host) {
     ReturnInListItem(aSelection, *listItem, *atStartOfSelection.GetContainer(),
@@ -1956,65 +1948,62 @@ HTMLEditRules::WillInsertBreak(Selection
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::InsertBRElement(Selection& aSelection,
                                const EditorDOMPoint& aPointToBreak)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (NS_WARN_IF(!aPointToBreak.IsSet())) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   bool brElementIsAfterBlock = false;
   bool brElementIsBeforeBlock = false;
 
   // First, insert a <br> element.
   RefPtr<Element> brElement;
   if (IsPlaintextEditor()) {
     brElement =
-      htmlEditor->InsertBrElementWithTransaction(aSelection, aPointToBreak);
+      HTMLEditorRef().InsertBrElementWithTransaction(aSelection, aPointToBreak);
     if (NS_WARN_IF(!brElement)) {
       return NS_ERROR_FAILURE;
     }
   } else {
     EditorDOMPoint pointToBreak(aPointToBreak);
-    WSRunObject wsObj(htmlEditor, pointToBreak);
+    WSRunObject wsObj(&HTMLEditorRef(), pointToBreak);
     int32_t visOffset = 0;
     WSType wsType;
     nsCOMPtr<nsINode> visNode;
     wsObj.PriorVisibleNode(pointToBreak,
                            address_of(visNode), &visOffset, &wsType);
     if (wsType & WSType::block) {
       brElementIsAfterBlock = true;
     }
     wsObj.NextVisibleNode(pointToBreak,
                           address_of(visNode), &visOffset, &wsType);
     if (wsType & WSType::block) {
       brElementIsBeforeBlock = true;
     }
     // If the container of the break is a link, we need to split it and
     // insert new <br> between the split links.
     nsCOMPtr<nsINode> linkDOMNode;
-    if (htmlEditor->IsInLink(pointToBreak.GetContainer(),
-                             address_of(linkDOMNode))) {
+    if (HTMLEditorRef().IsInLink(pointToBreak.GetContainer(),
+                                 address_of(linkDOMNode))) {
       nsCOMPtr<Element> linkNode = do_QueryInterface(linkDOMNode);
       if (NS_WARN_IF(!linkNode)) {
         return NS_ERROR_FAILURE;
       }
       SplitNodeResult splitLinkNodeResult =
-        htmlEditor->SplitNodeDeepWithTransaction(
-                      *linkNode, pointToBreak,
-                      SplitAtEdges::eDoNotCreateEmptyContainer);
+        HTMLEditorRef().SplitNodeDeepWithTransaction(
+                          *linkNode, pointToBreak,
+                          SplitAtEdges::eDoNotCreateEmptyContainer);
       if (NS_WARN_IF(splitLinkNodeResult.Failed())) {
         return splitLinkNodeResult.Rv();
       }
       pointToBreak = splitLinkNodeResult.SplitPoint();
     }
     brElement = wsObj.InsertBreak(aSelection, pointToBreak, nsIEditor::eNone);
     if (NS_WARN_IF(!brElement)) {
       return NS_ERROR_FAILURE;
@@ -2043,34 +2032,34 @@ HTMLEditRules::InsertBRElement(Selection
     }
     return NS_OK;
   }
 
   EditorDOMPoint afterBRElement(brElement);
   DebugOnly<bool> advanced = afterBRElement.AdvanceOffset();
   NS_WARNING_ASSERTION(advanced,
     "Failed to advance offset after the new <br> element");
-  WSRunObject wsObj(htmlEditor, afterBRElement);
+  WSRunObject wsObj(&HTMLEditorRef(), afterBRElement);
   nsCOMPtr<nsINode> maybeSecondBRNode;
   int32_t visOffset = 0;
   WSType wsType;
   wsObj.NextVisibleNode(afterBRElement,
                         address_of(maybeSecondBRNode), &visOffset, &wsType);
   if (wsType == WSType::br) {
     // The next thing after the break we inserted is another break.  Move the
     // second break to be the first break's sibling.  This will prevent them
     // from being in different inline nodes, which would break
     // SetInterlinePosition().  It will also assure that if the user clicks
     // away and then clicks back on their new blank line, they will still get
     // the style from the line above.
     EditorDOMPoint atSecondBRElement(maybeSecondBRNode);
     if (brElement->GetNextSibling() != maybeSecondBRNode) {
       nsresult rv =
-        htmlEditor->MoveNodeWithTransaction(*maybeSecondBRNode->AsContent(),
-                                            afterBRElement);
+        HTMLEditorRef().MoveNodeWithTransaction(*maybeSecondBRNode->AsContent(),
+                                                afterBRElement);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
   }
 
   // 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
@@ -2097,25 +2086,22 @@ HTMLEditRules::DidInsertBreak(Selection*
 {
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::SplitMailCites(Selection* aSelection,
                               bool* aHandled)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (NS_WARN_IF(!aSelection) || NS_WARN_IF(!aHandled)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   EditorRawDOMPoint pointToSplit(EditorBase::GetStartPoint(aSelection));
   if (NS_WARN_IF(!pointToSplit.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   RefPtr<Element> citeNode =
     GetTopEnclosingMailCite(*pointToSplit.GetContainer());
   if (!citeNode) {
@@ -2126,17 +2112,17 @@ HTMLEditRules::SplitMailCites(Selection*
   // 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).
   // The latter can confuse a user if they click there and start typing,
   // because being in the mailquote may affect wrapping behavior, or font
   // color, etc.
-  WSRunObject wsObj(htmlEditor, pointToSplit);
+  WSRunObject wsObj(&HTMLEditorRef(), pointToSplit);
   nsCOMPtr<nsINode> visNode;
   int32_t visOffset=0;
   WSType wsType;
   wsObj.NextVisibleNode(pointToSplit, address_of(visNode), &visOffset, &wsType);
   // If selection start point is before a break and it's inside the mailquote,
   // let's split it after the visible node.
   if (wsType == WSType::br &&
       visNode != citeNode && citeNode->Contains(visNode)) {
@@ -2146,19 +2132,19 @@ HTMLEditRules::SplitMailCites(Selection*
       "Failed to advance offset to after the visible node");
   }
 
   if (NS_WARN_IF(!pointToSplit.GetContainerAsContent())) {
     return NS_ERROR_FAILURE;
   }
 
   SplitNodeResult splitCiteNodeResult =
-    htmlEditor->SplitNodeDeepWithTransaction(
-                  *citeNode, pointToSplit,
-                  SplitAtEdges::eDoNotCreateEmptyContainer);
+    HTMLEditorRef().SplitNodeDeepWithTransaction(
+                      *citeNode, pointToSplit,
+                      SplitAtEdges::eDoNotCreateEmptyContainer);
   if (NS_WARN_IF(splitCiteNodeResult.Failed())) {
     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
@@ -2176,31 +2162,31 @@ HTMLEditRules::SplitMailCites(Selection*
                                   IsFrameOfType(nsIFrame::eBlockFrame)) {
     nsCOMPtr<nsINode> lastChild =
       previousNodeOfSplitPoint->GetLastChild();
     if (lastChild && !lastChild->IsHTMLElement(nsGkAtoms::br)) {
       // We ignore the result here.
       EditorRawDOMPoint endOfPreviousNodeOfSplitPoint;
       endOfPreviousNodeOfSplitPoint.SetToEndOf(previousNodeOfSplitPoint);
       RefPtr<Element> invisibleBrElement =
-        htmlEditor->InsertBrElementWithTransaction(
-                      *aSelection,
-                      endOfPreviousNodeOfSplitPoint);
+        HTMLEditorRef().InsertBrElementWithTransaction(
+                          *aSelection,
+                          endOfPreviousNodeOfSplitPoint);
       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 =
-    htmlEditor->InsertBrElementWithTransaction(*aSelection,
-                                               pointToInsertBrNode);
+    HTMLEditorRef().InsertBrElementWithTransaction(*aSelection,
+                                                   pointToInsertBrNode);
   if (NS_WARN_IF(!brElement)) {
     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);
@@ -2216,72 +2202,73 @@ HTMLEditRules::SplitMailCites(Selection*
   // 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.
     EditorRawDOMPoint pointToCreateNewBrNode(atBrNode.GetContainer(),
                                              atBrNode.Offset());
 
-    WSRunObject wsObj(htmlEditor, pointToCreateNewBrNode);
+    WSRunObject wsObj(&HTMLEditorRef(), pointToCreateNewBrNode);
     nsCOMPtr<nsINode> visNode;
     int32_t visOffset=0;
     WSType wsType;
     wsObj.PriorVisibleNode(pointToCreateNewBrNode,
                            address_of(visNode), &visOffset, &wsType);
     if (wsType == WSType::normalWS || wsType == WSType::text ||
         wsType == WSType::special) {
       EditorRawDOMPoint pointAfterNewBrNode(pointToCreateNewBrNode);
       DebugOnly<bool> advanced = pointAfterNewBrNode.AdvanceOffset();
       NS_WARNING_ASSERTION(advanced,
         "Failed to advance offset after the <br> node");
-      WSRunObject wsObjAfterBR(htmlEditor, pointAfterNewBrNode);
+      WSRunObject wsObjAfterBR(&HTMLEditorRef(), pointAfterNewBrNode);
       wsObjAfterBR.NextVisibleNode(pointAfterNewBrNode,
                                    address_of(visNode), &visOffset, &wsType);
       if (wsType == WSType::normalWS || wsType == WSType::text ||
           wsType == WSType::special ||
           // In case we're at the very end.
           wsType == WSType::thisBlock) {
         brElement =
-          htmlEditor->InsertBrElementWithTransaction(*aSelection,
-                                                     pointToCreateNewBrNode);
+          HTMLEditorRef().InsertBrElementWithTransaction(
+                            *aSelection, pointToCreateNewBrNode);
         if (NS_WARN_IF(!brElement)) {
           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 =
-      htmlEditor->IsEmptyNode(previousNodeOfSplitPoint, &bEmptyCite,
-                              true, false);
+      HTMLEditorRef().IsEmptyNode(previousNodeOfSplitPoint, &bEmptyCite,
+                                  true, false);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     if (bEmptyCite) {
-      rv = htmlEditor->DeleteNodeWithTransaction(*previousNodeOfSplitPoint);
+      rv = HTMLEditorRef().DeleteNodeWithTransaction(*previousNodeOfSplitPoint);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
   }
 
   if (citeNode) {
-    nsresult rv = htmlEditor->IsEmptyNode(citeNode, &bEmptyCite, true, false);
+    nsresult rv =
+      HTMLEditorRef().IsEmptyNode(citeNode, &bEmptyCite, true, false);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     if (bEmptyCite) {
-      rv = htmlEditor->DeleteNodeWithTransaction(*citeNode);
+      rv = HTMLEditorRef().DeleteNodeWithTransaction(*citeNode);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
   }
 
   *aHandled = true;
   return NS_OK;
@@ -2290,16 +2277,17 @@ HTMLEditRules::SplitMailCites(Selection*
 
 nsresult
 HTMLEditRules::WillDeleteSelection(Selection* aSelection,
                                    nsIEditor::EDirection aAction,
                                    nsIEditor::EStripWrappers aStripWrappers,
                                    bool* aCancel,
                                    bool* aHandled)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aStripWrappers == nsIEditor::eStrip ||
              aStripWrappers == nsIEditor::eNoStrip);
 
   if (!aSelection || !aCancel || !aHandled) {
     return NS_ERROR_NULL_POINTER;
   }
   // Initialize out params
   *aCancel = false;
@@ -2311,22 +2299,20 @@ HTMLEditRules::WillDeleteSelection(Selec
   // If there is only bogus content, cancel the operation
   if (mBogusNode) {
     *aCancel = true;
     return NS_OK;
   }
 
   // First check for table selection mode.  If so, hand off to table editor.
   RefPtr<Element> cell;
-  NS_ENSURE_STATE(mHTMLEditor);
   nsresult rv =
-    mHTMLEditor->GetFirstSelectedCell(nullptr, getter_AddRefs(cell));
+    HTMLEditorRef().GetFirstSelectedCell(nullptr, getter_AddRefs(cell));
   if (NS_SUCCEEDED(rv) && cell) {
-    NS_ENSURE_STATE(mHTMLEditor);
-    rv = mHTMLEditor->DeleteTableCellContents();
+    rv = HTMLEditorRef().DeleteTableCellContents();
     *aHandled = true;
     return rv;
   }
   cell = nullptr;
 
   // origCollapsed is used later to determine whether we should join blocks. We
   // don't really care about bCollapsed because it will be modified by
   // ExtendSelectionForDelete later. TryToJoinBlocksWithTransaction() should
@@ -2342,39 +2328,43 @@ HTMLEditRules::WillDeleteSelection(Selec
 
   NS_ENSURE_STATE(aSelection->GetRangeAt(0));
   nsCOMPtr<nsINode> startNode = aSelection->GetRangeAt(0)->GetStartContainer();
   int32_t startOffset = aSelection->GetRangeAt(0)->StartOffset();
   NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
 
   if (bCollapsed) {
     // If we are inside an empty block, delete it.
-    NS_ENSURE_STATE(mHTMLEditor);
-    nsCOMPtr<Element> host = mHTMLEditor->GetActiveEditingHost();
-    NS_ENSURE_TRUE(host, NS_ERROR_FAILURE);
+    RefPtr<Element> host = HTMLEditorRef().GetActiveEditingHost();
+    if (NS_WARN_IF(!host)) {
+      return NS_ERROR_FAILURE;
+    }
     rv = CheckForEmptyBlock(startNode, host, aSelection, aAction, aHandled);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
     if (*aHandled) {
       return NS_OK;
     }
 
     // Test for distance between caret and text that will be deleted
     rv = CheckBidiLevelForDeletion(aSelection,
                                    EditorRawDOMPoint(startNode, startOffset),
                                    aAction, aCancel);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     if (*aCancel) {
       return NS_OK;
     }
 
-    NS_ENSURE_STATE(mHTMLEditor);
-    rv = mHTMLEditor->ExtendSelectionForDelete(aSelection, &aAction);
-    NS_ENSURE_SUCCESS(rv, rv);
+    rv = HTMLEditorRef().ExtendSelectionForDelete(aSelection, &aAction);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
 
     // We should delete nothing.
     if (aAction == nsIEditor::eNone) {
       return NS_OK;
     }
 
     // ExtendSelectionForDelete() may have changed the selection, update it
     NS_ENSURE_STATE(aSelection->GetRangeAt(0));
@@ -2382,35 +2372,34 @@ HTMLEditRules::WillDeleteSelection(Selec
     startOffset = aSelection->GetRangeAt(0)->StartOffset();
     NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
 
     bCollapsed = aSelection->IsCollapsed();
   }
 
   if (bCollapsed) {
     // What's in the direction we are deleting?
-    NS_ENSURE_STATE(mHTMLEditor);
-    WSRunObject wsObj(mHTMLEditor, startNode, startOffset);
+    WSRunObject wsObj(&HTMLEditorRef(), startNode, startOffset);
     nsCOMPtr<nsINode> visNode;
     int32_t visOffset;
     WSType wsType;
 
     // Find next visible node
     if (aAction == nsIEditor::eNext) {
       wsObj.NextVisibleNode(EditorRawDOMPoint(startNode, startOffset),
                             address_of(visNode), &visOffset, &wsType);
     } else {
       wsObj.PriorVisibleNode(EditorRawDOMPoint(startNode, startOffset),
                              address_of(visNode), &visOffset, &wsType);
     }
 
     if (!visNode) {
       // Can't find anything to delete!
       *aCancel = true;
-      // XXX This is the result of mHTMLEditor->GetFirstSelectedCell().
+      // XXX This is the result of HTMLEditorRef().GetFirstSelectedCell().
       //     The value could be both an error and NS_OK.
       return rv;
     }
 
     if (wsType == WSType::normalWS) {
       // We found some visible ws to delete.  Let ws code handle it.
       *aHandled = true;
       if (aAction == nsIEditor::eNext) {
@@ -2453,28 +2442,26 @@ HTMLEditRules::WillDeleteSelection(Selec
         NS_ASSERTION(range->GetStartContainer() == visNode,
                      "selection start not in visNode");
         NS_ASSERTION(range->GetEndContainer() == visNode,
                      "selection end not in visNode");
 
         so = range->StartOffset();
         eo = range->EndOffset();
       }
-      if (NS_WARN_IF(!mHTMLEditor)) {
-        return NS_ERROR_FAILURE;
-      }
-      RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-      rv = WSRunObject::PrepareToDeleteRange(htmlEditor, address_of(visNode),
+      rv = WSRunObject::PrepareToDeleteRange(&HTMLEditorRef(),
+                                             address_of(visNode),
                                              &so, address_of(visNode), &eo);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       *aHandled = true;
-      rv = htmlEditor->DeleteTextWithTransaction(nodeAsText, std::min(so, eo),
-                                                 DeprecatedAbs(eo - so));
+      rv = HTMLEditorRef().DeleteTextWithTransaction(nodeAsText,
+                                                     std::min(so, eo),
+                                                     DeprecatedAbs(eo - so));
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       // XXX When Backspace key is pressed, Chromium removes following empty
       //     text nodes when removing the last character of the non-empty text
       //     node.  However, Edge never removes empty text nodes even if
       //     selection is in the following empty text node(s).  For now, we
@@ -2498,22 +2485,18 @@ HTMLEditRules::WillDeleteSelection(Selec
 
       return NS_OK;
     }
 
     if (wsType == WSType::special || wsType == WSType::br ||
         visNode->IsHTMLElement(nsGkAtoms::hr)) {
       // Short circuit for invisible breaks.  delete them and recurse.
       if (visNode->IsHTMLElement(nsGkAtoms::br) &&
-          (!mHTMLEditor || !mHTMLEditor->IsVisibleBRElement(visNode))) {
-        if (NS_WARN_IF(!mHTMLEditor)) {
-          return NS_ERROR_FAILURE;
-        }
-        RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-        rv = htmlEditor->DeleteNodeWithTransaction(*visNode);
+          !HTMLEditorRef().IsVisibleBRElement(visNode)) {
+        rv = HTMLEditorRef().DeleteNodeWithTransaction(*visNode);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         return WillDeleteSelection(aSelection, aAction, aStripWrappers,
                                    aCancel, aHandled);
       }
 
       // Special handling for backspace when positioned after <hr>
@@ -2569,60 +2552,59 @@ HTMLEditRules::WillDeleteSelection(Selec
           int32_t otherOffset;
 
           wsObj.NextVisibleNode(EditorRawDOMPoint(startNode, startOffset),
                                 address_of(otherNode),
                                 &otherOffset, &otherWSType);
 
           if (otherWSType == WSType::br) {
             // Delete the <br>
-            if (NS_WARN_IF(!mHTMLEditor) ||
-                NS_WARN_IF(!otherNode->IsContent())) {
+            if (NS_WARN_IF(!otherNode->IsContent())) {
               return NS_ERROR_FAILURE;
             }
             nsIContent* otherContent = otherNode->AsContent();
-            RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-            rv = WSRunObject::PrepareToDeleteNode(htmlEditor, otherContent);
+            rv = WSRunObject::PrepareToDeleteNode(&HTMLEditorRef(),
+                                                  otherContent);
             if (NS_WARN_IF(NS_FAILED(rv))) {
               return rv;
             }
-            rv = htmlEditor->DeleteNodeWithTransaction(*otherContent);
+            rv = HTMLEditorRef().DeleteNodeWithTransaction(*otherContent);
             if (NS_WARN_IF(NS_FAILED(rv))) {
               return rv;
             }
           }
 
           return NS_OK;
         }
         // Else continue with normal delete code
       }
 
-      if (NS_WARN_IF(!mHTMLEditor) ||
-          NS_WARN_IF(!visNode->IsContent())) {
+      if (NS_WARN_IF(!visNode->IsContent())) {
         return NS_ERROR_FAILURE;
       }
-      RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
       // Found break or image, or hr.
-      rv = WSRunObject::PrepareToDeleteNode(htmlEditor, visNode->AsContent());
+      rv = WSRunObject::PrepareToDeleteNode(&HTMLEditorRef(),
+                                            visNode->AsContent());
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       // Remember sibling to visnode, if any
-      nsCOMPtr<nsIContent> sibling = htmlEditor->GetPriorHTMLSibling(visNode);
+      nsCOMPtr<nsIContent> sibling =
+        HTMLEditorRef().GetPriorHTMLSibling(visNode);
       // Delete the node, and join like nodes if appropriate
-      rv = htmlEditor->DeleteNodeWithTransaction(*visNode);
+      rv = HTMLEditorRef().DeleteNodeWithTransaction(*visNode);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       // We did something, so let's say so.
       *aHandled = true;
       // Is there a prior node and are they siblings?
       nsCOMPtr<nsINode> stepbrother;
       if (sibling) {
-        stepbrother = htmlEditor->GetNextHTMLSibling(sibling);
+        stepbrother = HTMLEditorRef().GetNextHTMLSibling(sibling);
       }
       // Are they both text nodes?  If so, join them!
       if (startNode == stepbrother && startNode->GetAsText() &&
           sibling->GetAsText()) {
         EditorDOMPoint pt =
           JoinNearestEditableNodesWithTransaction(*sibling,
                                                   *startNode->AsContent());
         if (NS_WARN_IF(!pt.IsSet())) {
@@ -2666,33 +2648,27 @@ HTMLEditRules::WillDeleteSelection(Selec
                               address_of(otherNode),
                               &otherOffset, &otherWSType);
       }
 
       // First find the adjacent node in the block
       nsCOMPtr<nsIContent> leafNode;
       nsCOMPtr<nsINode> leftNode, rightNode;
       if (aAction == nsIEditor::ePrevious) {
-        NS_ENSURE_STATE(mHTMLEditor);
-        leafNode = mHTMLEditor->GetLastEditableLeaf(*visNode);
+        leafNode = HTMLEditorRef().GetLastEditableLeaf(*visNode);
         leftNode = leafNode;
         rightNode = startNode;
       } else {
-        NS_ENSURE_STATE(mHTMLEditor);
-        leafNode = mHTMLEditor->GetFirstEditableLeaf(*visNode);
+        leafNode = HTMLEditorRef().GetFirstEditableLeaf(*visNode);
         leftNode = startNode;
         rightNode = leafNode;
       }
 
       if (otherNode->IsHTMLElement(nsGkAtoms::br)) {
-        if (NS_WARN_IF(!mHTMLEditor)) {
-          return NS_ERROR_FAILURE;
-        }
-        RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-        rv = htmlEditor->DeleteNodeWithTransaction(*otherNode);
+        rv = HTMLEditorRef().DeleteNodeWithTransaction(*otherNode);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         // XXX Only in this case, setting "handled" to true only when it
         //     succeeds?
         *aHandled = true;
         bDeletedBR = true;
       }
@@ -2714,21 +2690,24 @@ HTMLEditRules::WillDeleteSelection(Selec
         return NS_OK;
       }
 
       // Else we are joining content to block
 
       nsCOMPtr<nsINode> selPointNode = startNode;
       int32_t selPointOffset = startOffset;
       {
-        NS_ENSURE_STATE(mHTMLEditor);
-        AutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater,
+        AutoTrackDOMPoint tracker(HTMLEditorRef().mRangeUpdater,
                                   address_of(selPointNode), &selPointOffset);
-        NS_ENSURE_STATE(leftNode && leftNode->IsContent() &&
-                        rightNode && rightNode->IsContent());
+        if (NS_WARN_IF(!leftNode) ||
+            NS_WARN_IF(!leftNode->IsContent()) ||
+            NS_WARN_IF(!rightNode) ||
+            NS_WARN_IF(!rightNode->IsContent())) {
+          return NS_ERROR_FAILURE;
+        }
         EditActionResult ret =
           TryToJoinBlocksWithTransaction(*leftNode->AsContent(),
                                          *rightNode->AsContent());
         *aHandled |= ret.Handled();
         *aCancel |= ret.Canceled();
         if (NS_WARN_IF(ret.Failed())) {
           return ret.Rv();
         }
@@ -2760,22 +2739,20 @@ HTMLEditRules::WillDeleteSelection(Selec
       if (HTMLEditUtils::IsTableElement(visNode)) {
         *aCancel = true;
         return NS_OK;
       }
 
       // First find the relevant nodes
       nsCOMPtr<nsINode> leftNode, rightNode;
       if (aAction == nsIEditor::ePrevious) {
-        NS_ENSURE_STATE(mHTMLEditor);
-        leftNode = mHTMLEditor->GetPreviousEditableHTMLNode(*visNode);
+        leftNode = HTMLEditorRef().GetPreviousEditableHTMLNode(*visNode);
         rightNode = startNode;
       } else {
-        NS_ENSURE_STATE(mHTMLEditor);
-        rightNode = mHTMLEditor->GetNextEditableHTMLNode(*visNode);
+        rightNode = HTMLEditorRef().GetNextEditableHTMLNode(*visNode);
         leftNode = startNode;
       }
 
       // Nothing to join
       if (!leftNode || !rightNode) {
         *aCancel = true;
         return NS_OK;
       }
@@ -2784,20 +2761,22 @@ HTMLEditRules::WillDeleteSelection(Selec
       if (InDifferentTableElements(leftNode, rightNode)) {
         *aCancel = true;
         return NS_OK;
       }
 
       nsCOMPtr<nsINode> selPointNode = startNode;
       int32_t selPointOffset = startOffset;
       {
-        NS_ENSURE_STATE(mHTMLEditor);
-        AutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater,
+        AutoTrackDOMPoint tracker(HTMLEditorRef().mRangeUpdater,
                                   address_of(selPointNode), &selPointOffset);
-        NS_ENSURE_STATE(leftNode->IsContent() && rightNode->IsContent());
+        if (NS_WARN_IF(!leftNode->IsContent()) ||
+            NS_WARN_IF(!rightNode->IsContent())) {
+          return NS_ERROR_FAILURE;
+        }
         EditActionResult ret =
           TryToJoinBlocksWithTransaction(*leftNode->AsContent(),
                                          *rightNode->AsContent());
         // This should claim that trying to join the block means that
         // this handles the action because the caller shouldn't do anything
         // anymore in this case.
         *aHandled = true;
         *aCancel |= ret.Canceled();
@@ -2825,40 +2804,37 @@ HTMLEditRules::WillDeleteSelection(Selec
   NS_ENSURE_TRUE(startNode, NS_ERROR_FAILURE);
   nsCOMPtr<nsINode> endNode = aSelection->GetRangeAt(0)->GetEndContainer();
   int32_t endOffset = aSelection->GetRangeAt(0)->EndOffset();
   NS_ENSURE_TRUE(endNode, NS_ERROR_FAILURE);
 
   // Figure out if the endpoints are in nodes that can be merged.  Adjust
   // surrounding whitespace in preparation to delete selection.
   if (!IsPlaintextEditor()) {
-    NS_ENSURE_STATE(mHTMLEditor);
-    AutoTransactionsConserveSelection dontChangeMySelection(mHTMLEditor);
-    rv = WSRunObject::PrepareToDeleteRange(mHTMLEditor,
+    AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
+    rv = WSRunObject::PrepareToDeleteRange(&HTMLEditorRef(),
                                            address_of(startNode), &startOffset,
                                            address_of(endNode), &endOffset);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
   }
 
   {
-    if (NS_WARN_IF(!mHTMLEditor)) {
-      return NS_ERROR_FAILURE;
-    }
-    RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
     // Track location of where we are deleting
-    AutoTrackDOMPoint startTracker(htmlEditor->mRangeUpdater,
+    AutoTrackDOMPoint startTracker(HTMLEditorRef().mRangeUpdater,
                                    address_of(startNode), &startOffset);
-    AutoTrackDOMPoint endTracker(htmlEditor->mRangeUpdater,
+    AutoTrackDOMPoint endTracker(HTMLEditorRef().mRangeUpdater,
                                  address_of(endNode), &endOffset);
     // We are handling all ranged deletions directly now.
     *aHandled = true;
 
     if (endNode == startNode) {
-      rv = htmlEditor->DeleteSelectionWithTransaction(aAction, aStripWrappers);
+      rv = HTMLEditorRef().DeleteSelectionWithTransaction(aAction,
+                                                          aStripWrappers);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     } else {
       // Figure out mailcite ancestors
       nsCOMPtr<Element> startCiteNode = GetTopEnclosingMailCite(*startNode);
       nsCOMPtr<Element> endCiteNode = GetTopEnclosingMailCite(*endNode);
 
@@ -2872,43 +2848,44 @@ HTMLEditRules::WillDeleteSelection(Selec
       }
 
       // Figure out block parents
       nsCOMPtr<Element> leftParent = HTMLEditor::GetBlock(*startNode);
       nsCOMPtr<Element> rightParent = HTMLEditor::GetBlock(*endNode);
 
       // Are endpoint block parents the same?  Use default deletion
       if (leftParent && leftParent == rightParent) {
-        NS_ENSURE_STATE(mHTMLEditor);
-        htmlEditor->DeleteSelectionWithTransaction(aAction, aStripWrappers);
+        HTMLEditorRef().DeleteSelectionWithTransaction(aAction, aStripWrappers);
       } else {
         // Deleting across blocks.  Are the blocks of same type?
-        NS_ENSURE_STATE(leftParent && rightParent);
+        if (NS_WARN_IF(!leftParent) || NS_WARN_IF(!rightParent)) {
+          return NS_ERROR_FAILURE;
+        }
 
         // Are the blocks siblings?
         nsCOMPtr<nsINode> leftBlockParent = leftParent->GetParentNode();
         nsCOMPtr<nsINode> rightBlockParent = rightParent->GetParentNode();
 
         // MOOSE: this could conceivably screw up a table.. fix me.
         if (leftBlockParent == rightBlockParent &&
-            htmlEditor->AreNodesSameType(leftParent, rightParent) &&
+            HTMLEditorRef().AreNodesSameType(leftParent, rightParent) &&
             // XXX What's special about these three types of block?
             (leftParent->IsHTMLElement(nsGkAtoms::p) ||
              HTMLEditUtils::IsListItem(leftParent) ||
              HTMLEditUtils::IsHeader(*leftParent))) {
           // First delete the selection
-          rv = htmlEditor->DeleteSelectionWithTransaction(aAction,
-                                                          aStripWrappers);
+          rv = HTMLEditorRef().DeleteSelectionWithTransaction(aAction,
+                                                              aStripWrappers);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
           // Join blocks
           EditorDOMPoint pt =
-            htmlEditor->JoinNodesDeepWithTransaction(*leftParent,
-                                                     *rightParent);
+            HTMLEditorRef().JoinNodesDeepWithTransaction(*leftParent,
+                                                         *rightParent);
           if (NS_WARN_IF(!pt.IsSet())) {
             return NS_ERROR_FAILURE;
           }
           // Fix up selection
           ErrorResult error;
           aSelection->Collapse(pt, error);
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
@@ -2922,65 +2899,70 @@ HTMLEditRules::WillDeleteSelection(Selec
 
         AutoRangeArray arrayOfRanges(aSelection);
         for (auto& range : arrayOfRanges.mRanges) {
           // Build a list of nodes in the range
           nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
           TrivialFunctor functor;
           DOMSubtreeIterator iter;
           nsresult rv = iter.Init(*range);
-          NS_ENSURE_SUCCESS(rv, rv);
+          if (NS_WARN_IF(NS_FAILED(rv))) {
+            return rv;
+          }
           iter.AppendList(functor, arrayOfNodes);
 
           // Now that we have the list, delete non-table elements
           int32_t listCount = arrayOfNodes.Length();
           for (int32_t j = 0; j < listCount; j++) {
             nsCOMPtr<nsINode> somenode = do_QueryInterface(arrayOfNodes[0]);
-            NS_ENSURE_STATE(somenode);
+            if (NS_WARN_IF(!somenode)) {
+              return NS_ERROR_FAILURE;
+            }
             DeleteNonTableElements(somenode);
             arrayOfNodes.RemoveElementAt(0);
             // If something visible is deleted, no need to join.  Visible means
             // all nodes except non-visible textnodes and breaks.
             if (join && origCollapsed) {
               if (!somenode->IsContent()) {
                 join = false;
                 continue;
               }
               nsCOMPtr<nsIContent> content = somenode->AsContent();
               if (Text* text = content->GetAsText()) {
-                join = !htmlEditor->IsInVisibleTextFrames(*text);
+                join = !HTMLEditorRef().IsInVisibleTextFrames(*text);
               } else {
                 join = content->IsHTMLElement(nsGkAtoms::br) &&
-                       !htmlEditor->IsVisibleBRElement(somenode);
+                       !HTMLEditorRef().IsVisibleBRElement(somenode);
               }
             }
           }
         }
 
         // Check endpoints for possible text deletion.  We can assume that if
         // text node is found, we can delete to end or to begining as
         // appropriate, since the case where both sel endpoints in same text
         // node was already handled (we wouldn't be here)
         if (startNode->GetAsText() &&
             startNode->Length() > static_cast<uint32_t>(startOffset)) {
           // Delete to last character
           OwningNonNull<CharacterData> dataNode =
             *static_cast<CharacterData*>(startNode.get());
-          rv = htmlEditor->DeleteTextWithTransaction(
-                             dataNode, startOffset,
-                             startNode->Length() - startOffset);
+          rv = HTMLEditorRef().DeleteTextWithTransaction(
+                                 dataNode, startOffset,
+                                 startNode->Length() - startOffset);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
         }
         if (endNode->GetAsText() && endOffset) {
           // Delete to first character
           OwningNonNull<CharacterData> dataNode =
             *static_cast<CharacterData*>(endNode.get());
-          rv = htmlEditor->DeleteTextWithTransaction(dataNode, 0, endOffset);
+          rv = HTMLEditorRef().DeleteTextWithTransaction(dataNode, 0,
+                                                         endOffset);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
         }
 
         if (join) {
           EditActionResult ret =
             TryToJoinBlocksWithTransaction(*leftParent, *rightParent);
@@ -2991,19 +2973,19 @@ HTMLEditRules::WillDeleteSelection(Selec
           }
         }
       }
     }
   }
 
   // We might have left only collapsed whitespace in the start/end nodes
   {
-    AutoTrackDOMPoint startTracker(mHTMLEditor->mRangeUpdater,
+    AutoTrackDOMPoint startTracker(HTMLEditorRef().mRangeUpdater,
                                    address_of(startNode), &startOffset);
-    AutoTrackDOMPoint endTracker(mHTMLEditor->mRangeUpdater,
+    AutoTrackDOMPoint endTracker(HTMLEditorRef().mRangeUpdater,
                                  address_of(endNode), &endOffset);
 
     DeleteNodeIfCollapsedText(*startNode);
     DeleteNodeIfCollapsedText(*endNode);
   }
 
   // If we're joining blocks: if deleting forward the selection should be
   // collapsed to the end of the selection, if deleting backward the selection
@@ -3033,75 +3015,69 @@ HTMLEditRules::WillDeleteSelection(Selec
  * 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.
  */
 void
 HTMLEditRules::DeleteNodeIfCollapsedText(nsINode& aNode)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   Text* text = aNode.GetAsText();
   if (!text) {
     return;
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return;
-  }
-
-  if (!mHTMLEditor->IsVisibleTextNode(*text)) {
-    RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-    DebugOnly<nsresult> rv = htmlEditor->DeleteNodeWithTransaction(aNode);
+  if (!HTMLEditorRef().IsVisibleTextNode(*text)) {
+    DebugOnly<nsresult> rv = HTMLEditorRef().DeleteNodeWithTransaction(aNode);
     NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to remove aNode");
   }
 }
 
 
 /**
  * InsertBRIfNeeded() determines if a br is needed for current selection to not
  * be spastic.  If so, it inserts one.  Callers responsibility to only call
  * with collapsed selection.
  *
  * @param aSelection        The collapsed selection.
  */
 nsresult
 HTMLEditRules::InsertBRIfNeeded(Selection* aSelection)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (NS_WARN_IF(!aSelection)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   EditorRawDOMPoint atStartOfSelection(EditorBase::GetStartPoint(aSelection));
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // inline elements don't need any br
   if (!IsBlockNode(*atStartOfSelection.GetContainer())) {
     return NS_OK;
   }
 
   // examine selection
-  WSRunObject wsObj(htmlEditor, atStartOfSelection);
+  WSRunObject wsObj(&HTMLEditorRef(), atStartOfSelection);
   if (((wsObj.mStartReason & WSType::block) ||
        (wsObj.mStartReason & WSType::br)) &&
       (wsObj.mEndReason & WSType::block)) {
     // if we are tucked between block boundaries then insert a br
     // first check that we are allowed to
-    if (htmlEditor->CanContainTag(*atStartOfSelection.GetContainer(),
-                                  *nsGkAtoms::br)) {
+    if (HTMLEditorRef().CanContainTag(*atStartOfSelection.GetContainer(),
+                                      *nsGkAtoms::br)) {
       RefPtr<Element> brElement =
-        htmlEditor->InsertBrElementWithTransaction(*aSelection,
-                                                   atStartOfSelection,
-                                                   nsIEditor::ePrevious);
+        HTMLEditorRef().InsertBrElementWithTransaction(*aSelection,
+                                                       atStartOfSelection,
+                                                       nsIEditor::ePrevious);
       if (NS_WARN_IF(!brElement)) {
         return NS_ERROR_FAILURE;
       }
       return NS_OK;
     }
   }
   return NS_OK;
 }
@@ -3115,60 +3091,53 @@ HTMLEditRules::InsertBRIfNeeded(Selectio
  * @param aAction       Which edge to find:
  *                        eNext/eNextWord/eToEndOfLine indicates beginning,
  *                        ePrevious/PreviousWord/eToBeginningOfLine ending.
  */
 EditorDOMPoint
 HTMLEditRules::GetGoodSelPointForNode(nsINode& aNode,
                                       nsIEditor::EDirection aAction)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aAction == nsIEditor::eNext ||
              aAction == nsIEditor::eNextWord ||
              aAction == nsIEditor::ePrevious ||
              aAction == nsIEditor::ePreviousWord ||
              aAction == nsIEditor::eToBeginningOfLine ||
              aAction == nsIEditor::eToEndOfLine);
 
   bool isPreviousAction = (aAction == nsIEditor::ePrevious ||
                            aAction == nsIEditor::ePreviousWord ||
                            aAction == nsIEditor::eToBeginningOfLine);
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return EditorDOMPoint();
-  }
-  if (aNode.GetAsText() || mHTMLEditor->IsContainer(&aNode) ||
+  if (aNode.GetAsText() || HTMLEditorRef().IsContainer(&aNode) ||
       NS_WARN_IF(!aNode.GetParentNode())) {
     return EditorDOMPoint(&aNode, isPreviousAction ? aNode.Length() : 0);
   }
 
-  if (NS_WARN_IF(!mHTMLEditor) ||
-      NS_WARN_IF(!aNode.IsContent())) {
+  if (NS_WARN_IF(!aNode.IsContent())) {
     return EditorDOMPoint();
   }
 
   EditorDOMPoint ret(&aNode);
   if ((!aNode.IsHTMLElement(nsGkAtoms::br) ||
-       mHTMLEditor->IsVisibleBRElement(&aNode)) && isPreviousAction) {
+       HTMLEditorRef().IsVisibleBRElement(&aNode)) && isPreviousAction) {
     ret.AdvanceOffset();
   }
   return ret;
 }
 
 EditActionResult
 HTMLEditRules::TryToJoinBlocksWithTransaction(nsIContent& aLeftNode,
                                               nsIContent& aRightNode)
 {
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return EditActionIgnored(NS_ERROR_UNEXPECTED);
-  }
-
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
-  nsCOMPtr<Element> leftBlock = htmlEditor->GetBlock(aLeftNode);
-  nsCOMPtr<Element> rightBlock = htmlEditor->GetBlock(aRightNode);
+  MOZ_ASSERT(IsEditorDataAvailable());
+
+  RefPtr<Element> leftBlock = HTMLEditorRef().GetBlock(aLeftNode);
+  RefPtr<Element> rightBlock = HTMLEditorRef().GetBlock(aRightNode);
 
   // Sanity checks
   if (NS_WARN_IF(!leftBlock) || NS_WARN_IF(!rightBlock)) {
     return EditActionIgnored(NS_ERROR_NULL_POINTER);
   }
   if (NS_WARN_IF(leftBlock == rightBlock)) {
     return EditActionIgnored(NS_ERROR_UNEXPECTED);
   }
@@ -3177,23 +3146,23 @@ HTMLEditRules::TryToJoinBlocksWithTransa
       HTMLEditUtils::IsTableElement(rightBlock)) {
     // Do not try to merge table elements
     return EditActionCanceled();
   }
 
   // Make sure we don't try to move things into HR's, which look like blocks
   // but aren't containers
   if (leftBlock->IsHTMLElement(nsGkAtoms::hr)) {
-    leftBlock = htmlEditor->GetBlockNodeParent(leftBlock);
+    leftBlock = HTMLEditorRef().GetBlockNodeParent(leftBlock);
     if (NS_WARN_IF(!leftBlock)) {
       return EditActionIgnored(NS_ERROR_UNEXPECTED);
     }
   }
   if (rightBlock->IsHTMLElement(nsGkAtoms::hr)) {
-    rightBlock = htmlEditor->GetBlockNodeParent(rightBlock);
+    rightBlock = HTMLEditorRef().GetBlockNodeParent(rightBlock);
     if (NS_WARN_IF(!rightBlock)) {
       return EditActionIgnored(NS_ERROR_UNEXPECTED);
     }
   }
 
   // Bail if both blocks the same
   if (leftBlock == rightBlock) {
     return EditActionIgnored();
@@ -3226,40 +3195,41 @@ HTMLEditRules::TryToJoinBlocksWithTransa
       MOZ_DIAGNOSTIC_ASSERT(!atChildInBlock.IsSet());
       leftBlock = leftList;
       rightBlock = rightList;
       mergeLists = true;
       existingList = leftList->NodeInfo()->NameAtom();
     }
   }
 
-  AutoTransactionsConserveSelection dontChangeMySelection(htmlEditor);
+  AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
 
   // offset below is where you find yourself in rightBlock when you traverse
   // upwards from leftBlock
   EditorDOMPoint atRightBlockChild;
   if (EditorUtils::IsDescendantOf(*leftBlock, *rightBlock,
                                   &atRightBlockChild)) {
     // Tricky case.  Left block is inside right block.  Do ws adjustment.  This
     // just destroys non-visible ws at boundaries we will be joining.
     DebugOnly<bool> advanced = atRightBlockChild.AdvanceOffset();
     NS_WARNING_ASSERTION(advanced,
       "Failed to advance offset to after child of rightBlock, "
       "leftBlock is a descendant of the child");
-    nsresult rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
+    nsresult rv = WSRunObject::ScrubBlockBoundary(&HTMLEditorRef(),
                                                   WSRunObject::kBlockEnd,
                                                   leftBlock);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return EditActionIgnored(rv);
     }
 
     {
       // We can't just track rightBlock because it's an Element.
-      AutoTrackDOMPoint tracker(htmlEditor->mRangeUpdater, &atRightBlockChild);
-      rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
+      AutoTrackDOMPoint tracker(HTMLEditorRef().mRangeUpdater,
+                                &atRightBlockChild);
+      rv = WSRunObject::ScrubBlockBoundary(&HTMLEditorRef(),
                                            WSRunObject::kAfterBlock,
                                            atRightBlockChild.GetContainer(),
                                            atRightBlockChild.Offset());
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return EditActionIgnored(rv);
       }
 
       // XXX AutoTrackDOMPoint instance, tracker, hasn't been destroyed here.
@@ -3304,42 +3274,42 @@ HTMLEditRules::TryToJoinBlocksWithTransa
       if (retMoveBlock.Handled()) {
         ret.MarkAsHandled();
       }
       // Now, all children of rightBlock were moved to leftBlock.  So,
       // atRightBlockChild is now invalid.
       atRightBlockChild.Clear();
     }
     if (brNode &&
-        NS_SUCCEEDED(htmlEditor->DeleteNodeWithTransaction(*brNode))) {
+        NS_SUCCEEDED(HTMLEditorRef().DeleteNodeWithTransaction(*brNode))) {
       ret.MarkAsHandled();
     }
     return ret;
   }
 
   MOZ_DIAGNOSTIC_ASSERT(!atRightBlockChild.IsSet());
 
   // Offset below is where you find yourself in leftBlock when you traverse
   // upwards from rightBlock
   EditorDOMPoint leftBlockChild;
   if (EditorUtils::IsDescendantOf(*rightBlock, *leftBlock, &leftBlockChild)) {
     // Tricky case.  Right block is inside left block.  Do ws adjustment.  This
     // just destroys non-visible ws at boundaries we will be joining.
-    nsresult rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
+    nsresult rv = WSRunObject::ScrubBlockBoundary(&HTMLEditorRef(),
                                                   WSRunObject::kBlockStart,
                                                   rightBlock);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return EditActionIgnored(rv);
     }
 
     {
       // We can't just track leftBlock because it's an Element, so track
       // something else.
-      AutoTrackDOMPoint tracker(htmlEditor->mRangeUpdater, &leftBlockChild);
-      rv = WSRunObject::ScrubBlockBoundary(htmlEditor,
+      AutoTrackDOMPoint tracker(HTMLEditorRef().mRangeUpdater, &leftBlockChild);
+      rv = WSRunObject::ScrubBlockBoundary(&HTMLEditorRef(),
                                            WSRunObject::kBeforeBlock,
                                            leftBlock, leftBlockChild.Offset());
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return EditActionIgnored(rv);
       }
       // XXX AutoTrackDOMPoint instance, tracker, hasn't been destroyed here.
       //     Do we really need to do update rightBlock here??
       MOZ_DIAGNOSTIC_ASSERT(leftBlock == leftBlockChild.GetContainer());
@@ -3392,27 +3362,27 @@ HTMLEditRules::TryToJoinBlocksWithTransa
 
         // We want to move our content just after the previous visible node.
         previousContent.AdvanceOffset();
       }
 
       // Because we don't want the moving content to receive the style of the
       // previous content, we split the previous content's style.
 
-      nsCOMPtr<Element> editorRoot = htmlEditor->GetEditorRoot();
+      RefPtr<Element> editorRoot = HTMLEditorRef().GetEditorRoot();
       if (!editorRoot || &aLeftNode != editorRoot) {
         nsCOMPtr<nsIContent> splittedPreviousContent;
         nsCOMPtr<nsINode> previousContentParent =
           previousContent.GetContainer();
         int32_t previousContentOffset = previousContent.Offset();
-        rv = htmlEditor->SplitStyleAbovePoint(
-                           address_of(previousContentParent),
-                           &previousContentOffset,
-                           nullptr, nullptr, nullptr,
-                           getter_AddRefs(splittedPreviousContent));
+        rv = HTMLEditorRef().SplitStyleAbovePoint(
+                               address_of(previousContentParent),
+                               &previousContentOffset,
+                               nullptr, nullptr, nullptr,
+                               getter_AddRefs(splittedPreviousContent));
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return EditActionIgnored(rv);
         }
 
         if (splittedPreviousContent) {
           previousContent.Set(splittedPreviousContent);
         } else {
           previousContent.Set(previousContentParent, previousContentOffset);
@@ -3425,33 +3395,33 @@ HTMLEditRules::TryToJoinBlocksWithTransa
 
       ret |= MoveBlock(*previousContent.GetContainerAsElement(), *rightBlock,
                        previousContent.Offset(), 0);
       if (NS_WARN_IF(ret.Failed())) {
         return ret;
       }
     }
     if (brNode &&
-        NS_SUCCEEDED(htmlEditor->DeleteNodeWithTransaction(*brNode))) {
+        NS_SUCCEEDED(HTMLEditorRef().DeleteNodeWithTransaction(*brNode))) {
       ret.MarkAsHandled();
     }
     return ret;
   }
 
   MOZ_DIAGNOSTIC_ASSERT(!atRightBlockChild.IsSet());
   MOZ_DIAGNOSTIC_ASSERT(!leftBlockChild.IsSet());
 
   // Normal case.  Blocks are siblings, or at least close enough.  An example
   // of the latter is <p>paragraph</p><ul><li>one<li>two<li>three</ul>.  The
   // first li and the p are not true siblings, but we still want to join them
   // if you backspace from li into p.
 
   // Adjust whitespace at block boundaries
   nsresult rv =
-    WSRunObject::PrepareToJoinBlocks(htmlEditor, leftBlock, rightBlock);
+    WSRunObject::PrepareToJoinBlocks(&HTMLEditorRef(), leftBlock, rightBlock);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return EditActionIgnored(rv);
   }
   // Do br adjustment.
   nsCOMPtr<Element> brNode =
     CheckForInvisibleBR(*leftBlock, BRLocation::blockEnd);
   EditActionResult ret(NS_OK);
   if (mergeLists || leftBlock->NodeInfo()->NameAtom() ==
@@ -3467,17 +3437,17 @@ HTMLEditRules::TryToJoinBlocksWithTransa
   } else {
     // Nodes are dissimilar types.
     ret |= MoveBlock(*leftBlock, *rightBlock, -1, 0);
     if (NS_WARN_IF(ret.Failed())) {
       return ret;
     }
   }
   if (brNode) {
-    rv = htmlEditor->DeleteNodeWithTransaction(*brNode);
+    rv = HTMLEditorRef().DeleteNodeWithTransaction(*brNode);
     // XXX In other top level if blocks, the result of
     //     DeleteNodeWithTransaction() is ignored.  Why does only this result
     //     is respected?
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return ret.SetResult(rv);
     }
     ret.MarkAsHandled();
   }
@@ -3485,43 +3455,38 @@ HTMLEditRules::TryToJoinBlocksWithTransa
 }
 
 EditActionResult
 HTMLEditRules::MoveBlock(Element& aLeftBlock,
                          Element& aRightBlock,
                          int32_t aLeftOffset,
                          int32_t aRightOffset)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
   // GetNodesFromPoint is the workhorse that figures out what we wnat to move.
   nsresult rv = GetNodesFromPoint(EditorDOMPoint(&aRightBlock, aRightOffset),
                                   EditAction::makeList, arrayOfNodes,
                                   TouchContent::yes);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return EditActionIgnored(rv);
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return EditActionIgnored(NS_ERROR_NOT_AVAILABLE);
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
   EditActionResult ret(NS_OK);
   for (uint32_t i = 0; i < arrayOfNodes.Length(); i++) {
     // get the node to act on
     if (IsBlockNode(arrayOfNodes[i])) {
       // For block nodes, move their contents only, then delete block.
       ret |=
         MoveContents(*arrayOfNodes[i]->AsElement(), aLeftBlock, &aLeftOffset);
       if (NS_WARN_IF(ret.Failed())) {
         return ret;
       }
-      if (NS_WARN_IF(!mHTMLEditor)) {
-        return ret.SetResult(NS_ERROR_UNEXPECTED);
-      }
-      rv = htmlEditor->DeleteNodeWithTransaction(*arrayOfNodes[i]);
+      rv = HTMLEditorRef().DeleteNodeWithTransaction(*arrayOfNodes[i]);
       NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
         "Failed to remove a block node");
       ret.MarkAsHandled();
     } else {
       // Otherwise move the content as is, checking against the DTD.
       ret |=
         MoveNodeSmart(*arrayOfNodes[i]->AsContent(), aLeftBlock, &aLeftOffset);
     }
@@ -3535,37 +3500,32 @@ HTMLEditRules::MoveBlock(Element& aLeftB
   return ret;
 }
 
 EditActionResult
 HTMLEditRules::MoveNodeSmart(nsIContent& aNode,
                              Element& aDestElement,
                              int32_t* aInOutDestOffset)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aInOutDestOffset);
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return EditActionIgnored(NS_ERROR_UNEXPECTED);
-  }
-
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   // Check if this node can go into the destination node
-  if (htmlEditor->CanContain(aDestElement, aNode)) {
+  if (HTMLEditorRef().CanContain(aDestElement, aNode)) {
     // If it can, move it there.
     if (*aInOutDestOffset == -1) {
       nsresult rv =
-        htmlEditor->MoveNodeToEndWithTransaction(aNode, aDestElement);
+        HTMLEditorRef().MoveNodeToEndWithTransaction(aNode, aDestElement);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return EditActionIgnored(rv);
       }
     } else {
       EditorRawDOMPoint pointToInsert(&aDestElement, *aInOutDestOffset);
       nsresult rv =
-        htmlEditor->MoveNodeWithTransaction(aNode, pointToInsert);
+        HTMLEditorRef().MoveNodeWithTransaction(aNode, pointToInsert);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return EditActionIgnored(rv);
       }
     }
     if (*aInOutDestOffset != -1) {
       (*aInOutDestOffset)++;
     }
     // XXX Should we check if the node is actually moved in this case?
@@ -3576,17 +3536,17 @@ HTMLEditRules::MoveNodeSmart(nsIContent&
   EditActionResult ret(NS_OK);
   if (aNode.IsElement()) {
     ret = MoveContents(*aNode.AsElement(), aDestElement, aInOutDestOffset);
     if (NS_WARN_IF(ret.Failed())) {
       return ret;
     }
   }
 
-  nsresult rv = htmlEditor->DeleteNodeWithTransaction(aNode);
+  nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(aNode);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return ret.SetResult(rv);
   }
   return ret.MarkAsHandled();
 }
 
 EditActionResult
 HTMLEditRules::MoveContents(Element& aElement,
@@ -3609,23 +3569,20 @@ HTMLEditRules::MoveContents(Element& aEl
   }
   return ret;
 }
 
 
 nsresult
 HTMLEditRules::DeleteNonTableElements(nsINode* aNode)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aNode);
   if (!HTMLEditUtils::IsTableElementButNotTable(aNode)) {
-    if (NS_WARN_IF(!mHTMLEditor)) {
-      return NS_ERROR_NOT_AVAILABLE;
-    }
-    RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-    nsresult rv = htmlEditor->DeleteNodeWithTransaction(*aNode);
+    nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(*aNode);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     return NS_OK;
   }
 
   AutoTArray<nsCOMPtr<nsIContent>, 10> childList;
   for (nsIContent* child = aNode->GetFirstChild();
@@ -3640,50 +3597,48 @@ HTMLEditRules::DeleteNonTableElements(ns
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::DidDeleteSelection(Selection* aSelection,
                                   nsIEditor::EDirection aDir,
                                   nsresult aResult)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (!aSelection) {
     return NS_ERROR_NULL_POINTER;
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   // find where we are
   EditorDOMPoint atStartOfSelection(EditorBase::GetStartPoint(aSelection));
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // find any enclosing mailcite
   RefPtr<Element> citeNode =
     GetTopEnclosingMailCite(*atStartOfSelection.GetContainer());
   if (citeNode) {
     bool isEmpty = true, seenBR = false;
-    htmlEditor->IsEmptyNodeImpl(citeNode, &isEmpty, true, true, false,
-                                &seenBR);
+    HTMLEditorRef().IsEmptyNodeImpl(citeNode, &isEmpty, true, true, false,
+                                    &seenBR);
     if (isEmpty) {
       EditorDOMPoint atCiteNode(citeNode);
       {
         AutoEditorDOMPointChildInvalidator lockOffset(atCiteNode);
-        nsresult rv = htmlEditor->DeleteNodeWithTransaction(*citeNode);
+        nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(*citeNode);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
       if (atCiteNode.IsSet() && seenBR) {
         RefPtr<Element> brElement =
-          htmlEditor->InsertBrElementWithTransaction(*aSelection, atCiteNode);
+          HTMLEditorRef().InsertBrElementWithTransaction(*aSelection,
+                                                         atCiteNode);
         if (NS_WARN_IF(!brElement)) {
           return NS_ERROR_FAILURE;
         }
         IgnoredErrorResult error;
         aSelection->Collapse(EditorRawDOMPoint(brElement), error);
         NS_WARNING_ASSERTION(!error.Failed(),
           "Failed to collapse selection at the new <br> element");
       }
@@ -3698,23 +3653,21 @@ nsresult
 HTMLEditRules::WillMakeList(Selection* aSelection,
                             const nsAString* aListType,
                             bool aEntireList,
                             const nsAString* aBulletType,
                             bool* aCancel,
                             bool* aHandled,
                             const nsAString* aItemType)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (!aSelection || !aListType || !aCancel || !aHandled) {
     return NS_ERROR_NULL_POINTER;
   }
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
 
   OwningNonNull<nsAtom> listType = NS_Atomize(*aListType);
 
   WillInsert(*aSelection, aCancel);
 
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
@@ -3736,17 +3689,17 @@ HTMLEditRules::WillMakeList(Selection* a
   // block parent, and then further expands to include any ancestors
   // whose children are all in the range
 
   *aHandled = true;
 
   nsresult rv = NormalizeSelection(aSelection);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  AutoSelectionRestorer selectionRestorer(aSelection, htmlEditor);
+  AutoSelectionRestorer selectionRestorer(aSelection, &HTMLEditorRef());
 
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
   rv = GetListActionNodes(arrayOfNodes,
                           aEntireList ? EntireList::yes : EntireList::no);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // check if all our nodes are <br>s, or empty inlines
   bool bOnlyBreaks = true;
@@ -3760,17 +3713,17 @@ HTMLEditRules::WillMakeList(Selection* a
   }
 
   // if no nodes, we make empty list.  Ditto if the user tried to make a list
   // of some # of breaks.
   if (arrayOfNodes.IsEmpty() || bOnlyBreaks) {
     // if only breaks, delete them
     if (bOnlyBreaks) {
       for (auto& node : arrayOfNodes) {
-        rv = htmlEditor->DeleteNodeWithTransaction(*node);
+        rv = HTMLEditorRef().DeleteNodeWithTransaction(*node);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
     }
 
     nsRange* firstRange = aSelection->GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
@@ -3778,39 +3731,39 @@ HTMLEditRules::WillMakeList(Selection* a
     }
 
     EditorDOMPoint atStartOfSelection(firstRange->StartRef());
     if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
       return NS_ERROR_FAILURE;
     }
 
     // Make sure we can put a list here.
-    if (!htmlEditor->CanContainTag(*atStartOfSelection.GetContainer(),
-                                   listType)) {
+    if (!HTMLEditorRef().CanContainTag(*atStartOfSelection.GetContainer(),
+                                       listType)) {
       *aCancel = true;
       return NS_OK;
     }
 
     SplitNodeResult splitAtSelectionStartResult =
       MaybeSplitAncestorsForInsertWithTransaction(listType, atStartOfSelection);
     if (NS_WARN_IF(splitAtSelectionStartResult.Failed())) {
       return splitAtSelectionStartResult.Rv();
     }
     RefPtr<Element> theList =
-      htmlEditor->CreateNodeWithTransaction(
-                    *listType,
-                    splitAtSelectionStartResult.SplitPoint());
+      HTMLEditorRef().CreateNodeWithTransaction(
+                        *listType,
+                        splitAtSelectionStartResult.SplitPoint());
     if (NS_WARN_IF(!theList)) {
       return NS_ERROR_FAILURE;
     }
 
     EditorRawDOMPoint atFirstListItemToInsertBefore(theList, 0);
     RefPtr<Element> theListItem =
-      htmlEditor->CreateNodeWithTransaction(*itemType,
-                                            atFirstListItemToInsertBefore);
+      HTMLEditorRef().CreateNodeWithTransaction(*itemType,
+                                                atFirstListItemToInsertBefore);
     if (NS_WARN_IF(!theListItem)) {
       return NS_ERROR_FAILURE;
     }
 
     // remember our new block for postprocessing
     mNewBlock = theListItem;
     // put selection in new list item
     *aHandled = true;
@@ -3845,43 +3798,47 @@ HTMLEditRules::WillMakeList(Selection* a
     // into the same list.  respect table cell boundaries when listifying.
     if (curList && InDifferentTableElements(curList, curNode)) {
       curList = nullptr;
     }
 
     // If curNode is a break, delete it, and quit remembering prev list item.
     // If an empty inline container, delete it, but still remember the previous
     // item.
-    if (htmlEditor->IsEditable(curNode) && (TextEditUtils::IsBreak(curNode) ||
-                                            IsEmptyInline(curNode))) {
-      rv = htmlEditor->DeleteNodeWithTransaction(*curNode);
-      NS_ENSURE_SUCCESS(rv, rv);
+    if (HTMLEditorRef().IsEditable(curNode) &&
+        (TextEditUtils::IsBreak(curNode) || IsEmptyInline(curNode))) {
+      rv = HTMLEditorRef().DeleteNodeWithTransaction(*curNode);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
       if (TextEditUtils::IsBreak(curNode)) {
         prevListItem = nullptr;
       }
       continue;
     }
 
     if (HTMLEditUtils::IsList(curNode)) {
       // do we have a curList already?
       if (curList && !EditorUtils::IsDescendantOf(*curNode, *curList)) {
         // move all of our children into curList.  cheezy way to do it: move
         // whole list and then RemoveContainerWithTransaction() on the list.
         // ConvertListType first: that routine handles converting the list
         // item types, if needed.
-        rv = htmlEditor->MoveNodeToEndWithTransaction(*curNode, *curList);
+        rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode, *curList);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         newBlock = ConvertListType(curNode->AsElement(), listType, itemType);
         if (NS_WARN_IF(!newBlock)) {
           return NS_ERROR_FAILURE;
         }
-        rv = htmlEditor->RemoveBlockContainerWithTransaction(*newBlock);
-        NS_ENSURE_SUCCESS(rv, rv);
+        rv = HTMLEditorRef().RemoveBlockContainerWithTransaction(*newBlock);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
       } else {
         // replace list with new list type
         curList = ConvertListType(curNode->AsElement(), listType, itemType);
         if (NS_WARN_IF(!curList)) {
           return NS_ERROR_FAILURE;
         }
       }
       prevListItem = nullptr;
@@ -3898,106 +3855,110 @@ HTMLEditRules::WillMakeList(Selection* a
         // list item is in wrong type of list. if we don't have a curList,
         // split the old list and make a new list of correct type.
         if (!curList || EditorUtils::IsDescendantOf(*curNode, *curList)) {
           if (NS_WARN_IF(!atCurNode.GetContainerAsContent())) {
             return NS_ERROR_FAILURE;
           }
           ErrorResult error;
           nsCOMPtr<nsIContent> newLeftNode =
-            htmlEditor->SplitNodeWithTransaction(atCurNode, error);
+            HTMLEditorRef().SplitNodeWithTransaction(atCurNode, error);
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
           newBlock = newLeftNode ? newLeftNode->AsElement() : nullptr;
           EditorRawDOMPoint atParentOfCurNode(atCurNode.GetContainer());
-          curList = htmlEditor->CreateNodeWithTransaction(*listType,
-                                                          atParentOfCurNode);
+          curList =
+            HTMLEditorRef().CreateNodeWithTransaction(*listType,
+                                                      atParentOfCurNode);
           if (NS_WARN_IF(!curList)) {
             return NS_ERROR_FAILURE;
           }
         }
         // move list item to new list
-        rv = htmlEditor->MoveNodeToEndWithTransaction(*curNode, *curList);
+        rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode, *curList);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         // convert list item type if needed
         if (!curNode->IsHTMLElement(itemType)) {
           newBlock =
-            htmlEditor->ReplaceContainerWithTransaction(*curNode->AsElement(),
-                                                        *itemType);
+            HTMLEditorRef().ReplaceContainerWithTransaction(
+                              *curNode->AsElement(), *itemType);
           if (NS_WARN_IF(!newBlock)) {
             return NS_ERROR_FAILURE;
           }
         }
       } else {
         // item is in right type of list.  But we might still have to move it.
         // and we might need to convert list item types.
         if (!curList) {
           curList = atCurNode.GetContainerAsElement();
         } else if (atCurNode.GetContainer() != curList) {
           // move list item to new list
-          rv = htmlEditor->MoveNodeToEndWithTransaction(*curNode, *curList);
+          rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode, *curList);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
         }
         if (!curNode->IsHTMLElement(itemType)) {
           newBlock =
-            htmlEditor->ReplaceContainerWithTransaction(*curNode->AsElement(),
-                                                        *itemType);
+            HTMLEditorRef().ReplaceContainerWithTransaction(
+                              *curNode->AsElement(), *itemType);
           if (NS_WARN_IF(!newBlock)) {
             return NS_ERROR_FAILURE;
           }
         }
       }
       nsCOMPtr<Element> curElement = do_QueryInterface(curNode);
       if (NS_WARN_IF(!curElement)) {
         return NS_ERROR_FAILURE;
       }
       if (aBulletType && !aBulletType->IsEmpty()) {
-        rv = htmlEditor->SetAttributeWithTransaction(*curElement,
-                                                     *nsGkAtoms::type,
-                                                     *aBulletType);
+        rv = HTMLEditorRef().SetAttributeWithTransaction(*curElement,
+                                                         *nsGkAtoms::type,
+                                                         *aBulletType);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       } else {
-        rv = htmlEditor->RemoveAttributeWithTransaction(*curElement,
-                                                        *nsGkAtoms::type);
+        rv = HTMLEditorRef().RemoveAttributeWithTransaction(*curElement,
+                                                            *nsGkAtoms::type);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
       continue;
     }
 
     // if we hit a div clear our prevListItem, insert divs contents
     // into our node array, and remove the div
     if (curNode->IsHTMLElement(nsGkAtoms::div)) {
       prevListItem = nullptr;
       int32_t j = i + 1;
       GetInnerContent(*curNode, arrayOfNodes, &j);
-      rv = htmlEditor->RemoveContainerWithTransaction(*curNode->AsElement());
-      NS_ENSURE_SUCCESS(rv, rv);
+      rv = HTMLEditorRef().RemoveContainerWithTransaction(
+                             *curNode->AsElement());
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
       listCount = arrayOfNodes.Length();
       continue;
     }
 
     // need to make a list to put things in if we haven't already,
     if (!curList) {
       SplitNodeResult splitCurNodeResult =
         MaybeSplitAncestorsForInsertWithTransaction(listType, atCurNode);
       if (NS_WARN_IF(splitCurNodeResult.Failed())) {
         return splitCurNodeResult.Rv();
       }
       curList =
-        htmlEditor->CreateNodeWithTransaction(*listType,
-                                              splitCurNodeResult.SplitPoint());
+        HTMLEditorRef().CreateNodeWithTransaction(
+                          *listType, splitCurNodeResult.SplitPoint());
       if (NS_WARN_IF(!curList)) {
         return NS_ERROR_FAILURE;
       }
       // remember our new block for postprocessing
       mNewBlock = curList;
       // curList is now the correct thing to put curNode in
       prevListItem = nullptr;
 
@@ -4007,30 +3968,33 @@ HTMLEditRules::WillMakeList(Selection* a
     }
 
     // if curNode isn't a list item, we must wrap it in one
     nsCOMPtr<Element> listItem;
     if (!HTMLEditUtils::IsListItem(curNode)) {
       if (IsInlineNode(curNode) && prevListItem) {
         // this is a continuation of some inline nodes that belong together in
         // the same list item.  use prevListItem
-        rv = htmlEditor->MoveNodeToEndWithTransaction(*curNode, *prevListItem);
-        NS_ENSURE_SUCCESS(rv, rv);
+        rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode,
+                                                          *prevListItem);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
       } else {
         // don't wrap li around a paragraph.  instead replace paragraph with li
         if (curNode->IsHTMLElement(nsGkAtoms::p)) {
           listItem =
-            htmlEditor->ReplaceContainerWithTransaction(*curNode->AsElement(),
-                                                        *itemType);
+            HTMLEditorRef().ReplaceContainerWithTransaction(
+                              *curNode->AsElement(), *itemType);
           if (NS_WARN_IF(!listItem)) {
             return NS_ERROR_FAILURE;
           }
         } else {
           listItem =
-            htmlEditor->InsertContainerWithTransaction(*curNode, *itemType);
+            HTMLEditorRef().InsertContainerWithTransaction(*curNode, *itemType);
           if (NS_WARN_IF(!listItem)) {
             return NS_ERROR_FAILURE;
           }
         }
         if (IsInlineNode(curNode)) {
           prevListItem = listItem;
         } else {
           prevListItem = nullptr;
@@ -4038,58 +4002,63 @@ HTMLEditRules::WillMakeList(Selection* a
       }
     } else {
       listItem = curNode->AsElement();
     }
 
     if (listItem) {
       // if we made a new list item, deal with it: tuck the listItem into the
       // end of the active list
-      rv = htmlEditor->MoveNodeToEndWithTransaction(*listItem, *curList);
+      rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*listItem, *curList);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
   }
 
   return NS_OK;
 }
 
 
 nsresult
 HTMLEditRules::WillRemoveList(Selection* aSelection,
                               bool aOrdered,
                               bool* aCancel,
                               bool* aHandled)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (!aSelection || !aCancel || !aHandled) {
     return NS_ERROR_NULL_POINTER;
   }
   // initialize out param
   *aCancel = false;
   *aHandled = true;
 
   nsresult rv = NormalizeSelection(aSelection);
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_STATE(mHTMLEditor);
-  AutoSelectionRestorer selectionRestorer(aSelection, mHTMLEditor);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  AutoSelectionRestorer selectionRestorer(aSelection, &HTMLEditorRef());
 
   nsTArray<RefPtr<nsRange>> arrayOfRanges;
   GetPromotedRanges(*aSelection, arrayOfRanges, EditAction::makeList);
 
   // use these ranges to contruct a list of nodes to act on.
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
   rv = GetListActionNodes(arrayOfNodes, EntireList::no);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   // Remove all non-editable nodes.  Leave them be.
   for (int32_t i = arrayOfNodes.Length() - 1; i >= 0; i--) {
     OwningNonNull<nsINode> testNode = arrayOfNodes[i];
-    NS_ENSURE_STATE(mHTMLEditor);
-    if (!mHTMLEditor->IsEditable(testNode)) {
+    if (!HTMLEditorRef().IsEditable(testNode)) {
       arrayOfNodes.RemoveElementAt(i);
     }
   }
 
   // Only act on lists or list items in the array
   for (auto& curNode : arrayOfNodes) {
     // here's where we actually figure out what to do
     if (HTMLEditUtils::IsListItem(curNode)) {
@@ -4097,17 +4066,19 @@ HTMLEditRules::WillRemoveList(Selection*
       bool bOutOfList;
       do {
         rv = PopListItem(*curNode->AsContent(), &bOutOfList);
         NS_ENSURE_SUCCESS(rv, rv);
       } while (!bOutOfList); // keep popping it out until it's not in a list anymore
     } else if (HTMLEditUtils::IsList(curNode)) {
       // node is a list, move list items out
       rv = RemoveListStructure(*curNode->AsElement());
-      NS_ENSURE_SUCCESS(rv, rv);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
     }
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::WillMakeDefListItem(Selection* aSelection,
                                    const nsAString *aItemType,
@@ -4139,23 +4110,22 @@ HTMLEditRules::WillMakeBasicBlock(Select
   nsresult rv = MakeBasicBlock(aSelection, blockType);
   Unused << NS_WARN_IF(NS_FAILED(rv));
   return rv;
 }
 
 nsresult
 HTMLEditRules::MakeBasicBlock(Selection& aSelection, nsAtom& blockType)
 {
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   nsresult rv = NormalizeSelection(&aSelection);
   NS_ENSURE_SUCCESS(rv, rv);
-  AutoSelectionRestorer selectionRestorer(&aSelection, htmlEditor);
-  AutoTransactionsConserveSelection dontChangeMySelection(htmlEditor);
+  AutoSelectionRestorer selectionRestorer(&aSelection, &HTMLEditorRef());
+  AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
 
   // Contruct a list of nodes to act on.
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
   rv = GetNodesFromSelection(aSelection, EditAction::makeBasicBlock,
                              arrayOfNodes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If nothing visible in list, make an empty block
@@ -4165,49 +4135,49 @@ HTMLEditRules::MakeBasicBlock(Selection&
       return NS_ERROR_FAILURE;
     }
 
     EditorDOMPoint pointToInsertBlock(firstRange->StartRef());
     if (&blockType == nsGkAtoms::normal ||
         &blockType == nsGkAtoms::_empty) {
       // We are removing blocks (going to "body text")
       RefPtr<Element> curBlock =
-        htmlEditor->GetBlock(*pointToInsertBlock.GetContainer());
+        HTMLEditorRef().GetBlock(*pointToInsertBlock.GetContainer());
       if (NS_WARN_IF(!curBlock)) {
         return NS_ERROR_FAILURE;
       }
       if (!HTMLEditUtils::IsFormatNode(curBlock)) {
         return NS_OK;
       }
 
       // If the first editable node after selection is a br, consume it.
       // Otherwise it gets pushed into a following block after the split,
       // which is visually bad.
       nsCOMPtr<nsIContent> brContent =
-        htmlEditor->GetNextEditableHTMLNode(pointToInsertBlock);
+        HTMLEditorRef().GetNextEditableHTMLNode(pointToInsertBlock);
       if (brContent && brContent->IsHTMLElement(nsGkAtoms::br)) {
         AutoEditorDOMPointChildInvalidator lockOffset(pointToInsertBlock);
-        rv = htmlEditor->DeleteNodeWithTransaction(*brContent);
+        rv = HTMLEditorRef().DeleteNodeWithTransaction(*brContent);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
       // Do the splits!
       SplitNodeResult splitNodeResult =
-        htmlEditor->SplitNodeDeepWithTransaction(
-                      *curBlock, pointToInsertBlock,
-                      SplitAtEdges::eDoNotCreateEmptyContainer);
+        HTMLEditorRef().SplitNodeDeepWithTransaction(
+                          *curBlock, pointToInsertBlock,
+                          SplitAtEdges::eDoNotCreateEmptyContainer);
       if (NS_WARN_IF(splitNodeResult.Failed())) {
         return splitNodeResult.Rv();
       }
       EditorRawDOMPoint pointToInsertBrNode(splitNodeResult.SplitPoint());
       // Put a <br> element at the split point
       brContent =
-        htmlEditor->InsertBrElementWithTransaction(aSelection,
-                                                   pointToInsertBrNode);
+        HTMLEditorRef().InsertBrElementWithTransaction(aSelection,
+                                                       pointToInsertBrNode);
       if (NS_WARN_IF(!brContent)) {
         return NS_ERROR_FAILURE;
       }
       // Put selection at the split point
       EditorRawDOMPoint atBrNode(brContent);
       ErrorResult error;
       aSelection.Collapse(atBrNode, error);
       // Don't restore the selection
@@ -4215,45 +4185,45 @@ HTMLEditRules::MakeBasicBlock(Selection&
       if (NS_WARN_IF(error.Failed())) {
         return error.StealNSResult();
       }
       return NS_OK;
     }
 
     // We are making a block.  Consume a br, if needed.
     nsCOMPtr<nsIContent> brNode =
-      htmlEditor->GetNextEditableHTMLNodeInBlock(pointToInsertBlock);
+      HTMLEditorRef().GetNextEditableHTMLNodeInBlock(pointToInsertBlock);
     if (brNode && brNode->IsHTMLElement(nsGkAtoms::br)) {
       AutoEditorDOMPointChildInvalidator lockOffset(pointToInsertBlock);
-      rv = htmlEditor->DeleteNodeWithTransaction(*brNode);
+      rv = HTMLEditorRef().DeleteNodeWithTransaction(*brNode);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       // We don't need to act on this node any more
       arrayOfNodes.RemoveElement(brNode);
     }
     // Make sure we can put a block here.
     SplitNodeResult splitNodeResult =
       MaybeSplitAncestorsForInsertWithTransaction(blockType,
                                                   pointToInsertBlock);
     if (NS_WARN_IF(splitNodeResult.Failed())) {
       return splitNodeResult.Rv();
     }
     RefPtr<Element> block =
-      htmlEditor->CreateNodeWithTransaction(blockType,
-                                            splitNodeResult.SplitPoint());
+      HTMLEditorRef().CreateNodeWithTransaction(blockType,
+                                                splitNodeResult.SplitPoint());
     if (NS_WARN_IF(!block)) {
       return NS_ERROR_FAILURE;
     }
     // Remember our new block for postprocessing
     mNewBlock = block;
     // Delete anything that was in the list of nodes
     while (!arrayOfNodes.IsEmpty()) {
       OwningNonNull<nsINode> curNode = arrayOfNodes[0];
-      rv = htmlEditor->DeleteNodeWithTransaction(*curNode);
+      rv = HTMLEditorRef().DeleteNodeWithTransaction(*curNode);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       arrayOfNodes.RemoveElementAt(0);
     }
     // Put selection in new block
     rv = aSelection.Collapse(block, 0);
     // Don't restore the selection
@@ -4297,18 +4267,19 @@ HTMLEditRules::DidMakeBasicBlock(Selecti
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::WillIndent(Selection* aSelection,
                           bool* aCancel,
                           bool* aHandled)
 {
-  NS_ENSURE_STATE(mHTMLEditor);
-  if (mHTMLEditor->IsCSSEnabled()) {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
+  if (HTMLEditorRef().IsCSSEnabled()) {
     nsresult rv = WillCSSIndent(aSelection, aCancel, aHandled);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   } else {
     nsresult rv = WillHTMLIndent(aSelection, aCancel, aHandled);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
@@ -4317,50 +4288,47 @@ HTMLEditRules::WillIndent(Selection* aSe
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::WillCSSIndent(Selection* aSelection,
                              bool* aCancel,
                              bool* aHandled)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (!aSelection || !aCancel || !aHandled) {
     return NS_ERROR_NULL_POINTER;
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   WillInsert(*aSelection, aCancel);
 
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
   *aHandled = true;
 
   nsresult rv = NormalizeSelection(aSelection);
   NS_ENSURE_SUCCESS(rv, rv);
-  AutoSelectionRestorer selectionRestorer(aSelection, htmlEditor);
+  AutoSelectionRestorer selectionRestorer(aSelection, &HTMLEditorRef());
   nsTArray<OwningNonNull<nsRange>> arrayOfRanges;
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
 
   // short circuit: detect case of collapsed selection inside an <li>.
   // just sublist that <li>.  This prevents bug 97797.
 
   nsCOMPtr<Element> liNode;
   if (aSelection->IsCollapsed()) {
     EditorRawDOMPoint selectionStartPoint(
                         EditorBase::GetStartPoint(aSelection));
     if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
       return NS_ERROR_FAILURE;
     }
     Element* block =
-      htmlEditor->GetBlock(*selectionStartPoint.GetContainer());
+      HTMLEditorRef().GetBlock(*selectionStartPoint.GetContainer());
     if (block && HTMLEditUtils::IsListItem(block)) {
       liNode = block;
     }
   }
 
   if (liNode) {
     arrayOfNodes.AppendElement(*liNode);
   } else {
@@ -4388,28 +4356,28 @@ HTMLEditRules::WillCSSIndent(Selection* 
     // make sure we can put a block here
     SplitNodeResult splitNodeResult =
       MaybeSplitAncestorsForInsertWithTransaction(*nsGkAtoms::div,
                                                   atStartOfSelection);
     if (NS_WARN_IF(splitNodeResult.Failed())) {
       return splitNodeResult.Rv();
     }
     RefPtr<Element> theBlock =
-      htmlEditor->CreateNodeWithTransaction(*nsGkAtoms::div,
-                                            splitNodeResult.SplitPoint());
+      HTMLEditorRef().CreateNodeWithTransaction(*nsGkAtoms::div,
+                                                splitNodeResult.SplitPoint());
     if (NS_WARN_IF(!theBlock)) {
       return NS_ERROR_FAILURE;
     }
     // remember our new block for postprocessing
     mNewBlock = theBlock;
     ChangeIndentation(*theBlock, Change::plus);
     // delete anything that was in the list of nodes
     while (!arrayOfNodes.IsEmpty()) {
       OwningNonNull<nsINode> curNode = arrayOfNodes[0];
-      rv = htmlEditor->DeleteNodeWithTransaction(*curNode);
+      rv = HTMLEditorRef().DeleteNodeWithTransaction(*curNode);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       arrayOfNodes.RemoveElementAt(0);
     }
     // put selection in new block
     *aHandled = true;
     EditorRawDOMPoint atStartOfTheBlock(theBlock, 0);
@@ -4430,157 +4398,157 @@ HTMLEditRules::WillCSSIndent(Selection* 
   for (OwningNonNull<nsINode>& curNode : arrayOfNodes) {
     // Here's where we actually figure out what to do.
     EditorDOMPoint atCurNode(curNode);
     if (NS_WARN_IF(!atCurNode.IsSet())) {
       continue;
     }
 
     // Ignore all non-editable nodes.  Leave them be.
-    if (!htmlEditor->IsEditable(curNode)) {
+    if (!HTMLEditorRef().IsEditable(curNode)) {
       continue;
     }
 
     // some logic for putting list items into nested lists...
     if (HTMLEditUtils::IsList(atCurNode.GetContainer())) {
       // Check for whether we should join a list that follows curNode.
       // We do this if the next element is a list, and the list is of the
       // same type (li/ol) as curNode was a part it.
-      sibling = htmlEditor->GetNextHTMLSibling(curNode);
+      sibling = HTMLEditorRef().GetNextHTMLSibling(curNode);
       if (sibling && HTMLEditUtils::IsList(sibling) &&
           atCurNode.GetContainer()->NodeInfo()->NameAtom() ==
             sibling->NodeInfo()->NameAtom() &&
           atCurNode.GetContainer()->NodeInfo()->NamespaceID() ==
             sibling->NodeInfo()->NamespaceID()) {
-        rv = htmlEditor->MoveNodeWithTransaction(*curNode->AsContent(),
-                                                 EditorRawDOMPoint(sibling, 0));
-        NS_ENSURE_SUCCESS(rv, rv);
+        rv = HTMLEditorRef().MoveNodeWithTransaction(
+                               *curNode->AsContent(),
+                               EditorRawDOMPoint(sibling, 0));
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
         continue;
       }
 
       // Check for whether we should join a list that preceeds curNode.
       // We do this if the previous element is a list, and the list is of
       // the same type (li/ol) as curNode was a part of.
-      sibling = htmlEditor->GetPriorHTMLSibling(curNode);
+      sibling = HTMLEditorRef().GetPriorHTMLSibling(curNode);
       if (sibling && HTMLEditUtils::IsList(sibling) &&
           atCurNode.GetContainer()->NodeInfo()->NameAtom() ==
             sibling->NodeInfo()->NameAtom() &&
           atCurNode.GetContainer()->NodeInfo()->NamespaceID() ==
             sibling->NodeInfo()->NamespaceID()) {
-        rv = htmlEditor->MoveNodeToEndWithTransaction(*curNode->AsContent(),
-                                                      *sibling);
+        rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode->AsContent(),
+                                                          *sibling);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         continue;
       }
 
       // check to see if curList is still appropriate.  Which it is if
       // curNode is still right after it in the same list.
       sibling = nullptr;
       if (curList) {
-        sibling = htmlEditor->GetPriorHTMLSibling(curNode);
+        sibling = HTMLEditorRef().GetPriorHTMLSibling(curNode);
       }
 
       if (!curList || (sibling && sibling != curList)) {
         nsAtom* containerName =
           atCurNode.GetContainer()->NodeInfo()->NameAtom();
         // Create a new nested list of correct type.
         SplitNodeResult splitNodeResult =
           MaybeSplitAncestorsForInsertWithTransaction(*containerName,
                                                       atCurNode);
         if (NS_WARN_IF(splitNodeResult.Failed())) {
           return splitNodeResult.Rv();
         }
         curList =
-          htmlEditor->CreateNodeWithTransaction(*containerName,
-                                                splitNodeResult.SplitPoint());
+          HTMLEditorRef().CreateNodeWithTransaction(
+                            *containerName, splitNodeResult.SplitPoint());
         if (NS_WARN_IF(!curList)) {
           return NS_ERROR_FAILURE;
         }
         // curList is now the correct thing to put curNode in
         // remember our new block for postprocessing
         mNewBlock = curList;
       }
       // tuck the node into the end of the active list
-      rv = htmlEditor->MoveNodeToEndWithTransaction(*curNode->AsContent(),
-                                                    *curList);
+      rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode->AsContent(),
+                                                        *curList);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       continue;
     }
 
     // Not a list item.
 
     if (IsBlockNode(*curNode)) {
       ChangeIndentation(*curNode->AsElement(), Change::plus);
       curQuote = nullptr;
       continue;
     }
 
     if (!curQuote) {
       // First, check that our element can contain a div.
-      if (!htmlEditor->CanContainTag(*atCurNode.GetContainer(),
-                                     *nsGkAtoms::div)) {
+      if (!HTMLEditorRef().CanContainTag(*atCurNode.GetContainer(),
+                                         *nsGkAtoms::div)) {
         return NS_OK; // cancelled
       }
 
       SplitNodeResult splitNodeResult =
         MaybeSplitAncestorsForInsertWithTransaction(*nsGkAtoms::div, atCurNode);
       if (NS_WARN_IF(splitNodeResult.Failed())) {
         return splitNodeResult.Rv();
       }
       curQuote =
-        htmlEditor->CreateNodeWithTransaction(*nsGkAtoms::div,
-                                              splitNodeResult.SplitPoint());
+        HTMLEditorRef().CreateNodeWithTransaction(*nsGkAtoms::div,
+                                                  splitNodeResult.SplitPoint());
       if (NS_WARN_IF(!curQuote)) {
         return NS_ERROR_FAILURE;
       }
       ChangeIndentation(*curQuote, Change::plus);
       // remember our new block for postprocessing
       mNewBlock = curQuote;
       // curQuote is now the correct thing to put curNode in
     }
 
     // tuck the node into the end of the active blockquote
-    rv = htmlEditor->MoveNodeToEndWithTransaction(*curNode->AsContent(),
-                                                  *curQuote);
+    rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode->AsContent(),
+                                                      *curQuote);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::WillHTMLIndent(Selection* aSelection,
                               bool* aCancel,
                               bool* aHandled)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (!aSelection || !aCancel || !aHandled) {
     return NS_ERROR_NULL_POINTER;
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   WillInsert(*aSelection, aCancel);
 
   // initialize out param
   // we want to ignore result of WillInsert()
   *aCancel = false;
   *aHandled = true;
 
   nsresult rv = NormalizeSelection(aSelection);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  AutoSelectionRestorer selectionRestorer(aSelection, htmlEditor);
+  AutoSelectionRestorer selectionRestorer(aSelection, &HTMLEditorRef());
 
   // convert the selection ranges into "promoted" selection ranges:
   // this basically just expands the range to include the immediate
   // block parent, and then further expands to include any ancestors
   // whose children are all in the range
 
   nsTArray<RefPtr<nsRange>> arrayOfRanges;
   GetPromotedRanges(*aSelection, arrayOfRanges, EditAction::indent);
@@ -4605,27 +4573,27 @@ HTMLEditRules::WillHTMLIndent(Selection*
     // Make sure we can put a block here.
     SplitNodeResult splitNodeResult =
       MaybeSplitAncestorsForInsertWithTransaction(*nsGkAtoms::blockquote,
                                                   atStartOfSelection);
     if (NS_WARN_IF(splitNodeResult.Failed())) {
       return splitNodeResult.Rv();
     }
     RefPtr<Element> theBlock =
-      htmlEditor->CreateNodeWithTransaction(*nsGkAtoms::blockquote,
-                                            splitNodeResult.SplitPoint());
+      HTMLEditorRef().CreateNodeWithTransaction(*nsGkAtoms::blockquote,
+                                                splitNodeResult.SplitPoint());
     if (NS_WARN_IF(!theBlock)) {
       return NS_ERROR_FAILURE;
     }
     // remember our new block for postprocessing
     mNewBlock = theBlock;
     // delete anything that was in the list of nodes
     while (!arrayOfNodes.IsEmpty()) {
       OwningNonNull<nsINode> curNode = arrayOfNodes[0];
-      rv = htmlEditor->DeleteNodeWithTransaction(*curNode);
+      rv = HTMLEditorRef().DeleteNodeWithTransaction(*curNode);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       arrayOfNodes.RemoveElementAt(0);
     }
     // put selection in new block
     *aHandled = true;
     EditorRawDOMPoint atStartOfTheBlock(theBlock, 0);
@@ -4646,86 +4614,87 @@ HTMLEditRules::WillHTMLIndent(Selection*
   for (OwningNonNull<nsINode>& curNode: arrayOfNodes) {
     // Here's where we actually figure out what to do.
     EditorDOMPoint atCurNode(curNode);
     if (NS_WARN_IF(!atCurNode.IsSet())) {
       continue;
     }
 
     // Ignore all non-editable nodes.  Leave them be.
-    if (!htmlEditor->IsEditable(curNode)) {
+    if (!HTMLEditorRef().IsEditable(curNode)) {
       continue;
     }
 
     // some logic for putting list items into nested lists...
     if (HTMLEditUtils::IsList(atCurNode.GetContainer())) {
       // Check for whether we should join a list that follows curNode.
       // We do this if the next element is a list, and the list is of the
       // same type (li/ol) as curNode was a part it.
-      sibling = htmlEditor->GetNextHTMLSibling(curNode);
+      sibling = HTMLEditorRef().GetNextHTMLSibling(curNode);
       if (sibling && HTMLEditUtils::IsList(sibling) &&
           atCurNode.GetContainer()->NodeInfo()->NameAtom() ==
             sibling->NodeInfo()->NameAtom() &&
           atCurNode.GetContainer()->NodeInfo()->NamespaceID() ==
             sibling->NodeInfo()->NamespaceID()) {
-        rv = htmlEditor->MoveNodeWithTransaction(*curNode->AsContent(),
-                                                 EditorRawDOMPoint(sibling, 0));
+        rv = HTMLEditorRef().MoveNodeWithTransaction(
+                               *curNode->AsContent(),
+                               EditorRawDOMPoint(sibling, 0));
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         continue;
       }
 
       // Check for whether we should join a list that preceeds curNode.
       // We do this if the previous element is a list, and the list is of
       // the same type (li/ol) as curNode was a part of.
-      sibling = htmlEditor->GetPriorHTMLSibling(curNode);
+      sibling = HTMLEditorRef().GetPriorHTMLSibling(curNode);
       if (sibling && HTMLEditUtils::IsList(sibling) &&
           atCurNode.GetContainer()->NodeInfo()->NameAtom() ==
             sibling->NodeInfo()->NameAtom() &&
           atCurNode.GetContainer()->NodeInfo()->NamespaceID() ==
             sibling->NodeInfo()->NamespaceID()) {
-        rv = htmlEditor->MoveNodeToEndWithTransaction(*curNode->AsContent(),
-                                                      *sibling);
+        rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode->AsContent(),
+                                                          *sibling);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         continue;
       }
 
       // check to see if curList is still appropriate.  Which it is if
       // curNode is still right after it in the same list.
       sibling = nullptr;
       if (curList) {
-        sibling = htmlEditor->GetPriorHTMLSibling(curNode);
+        sibling = HTMLEditorRef().GetPriorHTMLSibling(curNode);
       }
 
       if (!curList || (sibling && sibling != curList)) {
         nsAtom* containerName =
           atCurNode.GetContainer()->NodeInfo()->NameAtom();
         // Create a new nested list of correct type.
         SplitNodeResult splitNodeResult =
           MaybeSplitAncestorsForInsertWithTransaction(*containerName,
                                                       atCurNode);
         if (NS_WARN_IF(splitNodeResult.Failed())) {
           return splitNodeResult.Rv();
         }
         curList =
-          htmlEditor->CreateNodeWithTransaction(*containerName,
-                                                splitNodeResult.SplitPoint());
+          HTMLEditorRef().CreateNodeWithTransaction(
+                            *containerName, splitNodeResult.SplitPoint());
         if (NS_WARN_IF(!curList)) {
           return NS_ERROR_FAILURE;
         }
         // curList is now the correct thing to put curNode in
         // remember our new block for postprocessing
         mNewBlock = curList;
       }
       // tuck the node into the end of the active list
-      rv = htmlEditor->MoveNodeToEndWithTransaction(*curNode->AsContent(),
-                                                    *curList);
+      rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode->AsContent(),
+                                                        *curList);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       // forget curQuote, if any
       curQuote = nullptr;
 
       continue;
     }
@@ -4742,17 +4711,17 @@ HTMLEditRules::WillHTMLIndent(Selection*
     if (listItem) {
       if (indentedLI == listItem) {
         // already indented this list item
         continue;
       }
       // check to see if curList is still appropriate.  Which it is if
       // curNode is still right after it in the same list.
       if (curList) {
-        sibling = htmlEditor->GetPriorHTMLSibling(listItem);
+        sibling = HTMLEditorRef().GetPriorHTMLSibling(listItem);
       }
 
       if (!curList || (sibling && sibling != curList)) {
         EditorDOMPoint atListItem(listItem);
         if (NS_WARN_IF(!listItem)) {
           return NS_ERROR_FAILURE;
         }
         nsAtom* containerName =
@@ -4760,24 +4729,24 @@ HTMLEditRules::WillHTMLIndent(Selection*
         // Create a new nested list of correct type.
         SplitNodeResult splitNodeResult =
           MaybeSplitAncestorsForInsertWithTransaction(*containerName,
                                                       atListItem);
         if (NS_WARN_IF(splitNodeResult.Failed())) {
           return splitNodeResult.Rv();
         }
         curList =
-          htmlEditor->CreateNodeWithTransaction(*containerName,
-                                                splitNodeResult.SplitPoint());
+          HTMLEditorRef().CreateNodeWithTransaction(
+                            *containerName, splitNodeResult.SplitPoint());
         if (NS_WARN_IF(!curList)) {
           return NS_ERROR_FAILURE;
         }
       }
 
-      rv = htmlEditor->MoveNodeToEndWithTransaction(*listItem, *curList);
+      rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*listItem, *curList);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       // remember we indented this li
       indentedLI = listItem;
 
       continue;
@@ -4788,70 +4757,70 @@ HTMLEditRules::WillHTMLIndent(Selection*
     // One reason it might not go in prio blockquote is if we are now
     // in a different table cell.
     if (curQuote && InDifferentTableElements(curQuote, curNode)) {
       curQuote = nullptr;
     }
 
     if (!curQuote) {
       // First, check that our element can contain a blockquote.
-      if (!htmlEditor->CanContainTag(*atCurNode.GetContainer(),
-                                     *nsGkAtoms::blockquote)) {
+      if (!HTMLEditorRef().CanContainTag(*atCurNode.GetContainer(),
+                                         *nsGkAtoms::blockquote)) {
         return NS_OK; // cancelled
       }
 
       SplitNodeResult splitNodeResult =
         MaybeSplitAncestorsForInsertWithTransaction(*nsGkAtoms::blockquote,
                                                     atCurNode);
       if (NS_WARN_IF(splitNodeResult.Failed())) {
         return splitNodeResult.Rv();
       }
       curQuote =
-        htmlEditor->CreateNodeWithTransaction(*nsGkAtoms::blockquote,
-                                              splitNodeResult.SplitPoint());
+        HTMLEditorRef().CreateNodeWithTransaction(*nsGkAtoms::blockquote,
+                                                  splitNodeResult.SplitPoint());
       if (NS_WARN_IF(!curQuote)) {
         return NS_ERROR_FAILURE;
       }
       // remember our new block for postprocessing
       mNewBlock = curQuote;
       // curQuote is now the correct thing to put curNode in
     }
 
     // tuck the node into the end of the active blockquote
-    rv = htmlEditor->MoveNodeToEndWithTransaction(*curNode->AsContent(),
-                                                  *curQuote);
+    rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode->AsContent(),
+                                                      *curQuote);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     // forget curList, if any
     curList = nullptr;
   }
   return NS_OK;
 }
 
 
 nsresult
 HTMLEditRules::WillOutdent(Selection& aSelection,
                            bool* aCancel,
                            bool* aHandled)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aCancel && aHandled);
   *aCancel = false;
   *aHandled = true;
   nsCOMPtr<nsIContent> rememberedLeftBQ, rememberedRightBQ;
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-  bool useCSS = htmlEditor->IsCSSEnabled();
+
+  bool useCSS = HTMLEditorRef().IsCSSEnabled();
 
   nsresult rv = NormalizeSelection(&aSelection);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Some scoping for selection resetting - we may need to tweak it
   {
-    AutoSelectionRestorer selectionRestorer(&aSelection, htmlEditor);
+    AutoSelectionRestorer selectionRestorer(&aSelection, &HTMLEditorRef());
 
     // Convert the selection ranges into "promoted" selection ranges: this
     // basically just expands the range to include the immediate block parent,
     // and then further expands to include any ancestors whose children are all
     // in the range
     nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
     rv = GetNodesFromSelection(aSelection, EditAction::outdent, arrayOfNodes);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -4886,18 +4855,18 @@ HTMLEditRules::WillOutdent(Selection& aS
                                   getter_AddRefs(rememberedLeftBQ),
                                   getter_AddRefs(rememberedRightBQ));
           NS_ENSURE_SUCCESS(rv, rv);
           curBlockQuote = nullptr;
           firstBQChild = nullptr;
           lastBQChild = nullptr;
           curBlockQuoteIsIndentedWithCSS = false;
         }
-        rv = htmlEditor->RemoveBlockContainerWithTransaction(
-                           *curNode->AsElement());
+        rv = HTMLEditorRef().RemoveBlockContainerWithTransaction(
+                               *curNode->AsElement());
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         continue;
       }
       // Is it a block with a 'margin' property?
       if (useCSS && IsBlockNode(curNode)) {
         nsAtom& marginProperty = MarginPropertyAtomForIndent(curNode);
@@ -4955,17 +4924,17 @@ HTMLEditRules::WillOutdent(Selection& aS
       }
 
       // Are we inside a blockquote?
       OwningNonNull<nsINode> n = curNode;
       curBlockQuoteIsIndentedWithCSS = false;
       // Keep looking up the hierarchy as long as we don't hit the body or the
       // active editing host or a table element (other than an entire table)
       while (!n->IsHTMLElement(nsGkAtoms::body) && 
-             htmlEditor->IsDescendantOfEditorRoot(n) &&
+             HTMLEditorRef().IsDescendantOfEditorRoot(n) &&
              (n->IsHTMLElement(nsGkAtoms::table) ||
               !HTMLEditUtils::IsTableElement(n))) {
         if (!n->GetParentNode()) {
           break;
         }
         n = *n->GetParentNode();
         if (n->IsHTMLElement(nsGkAtoms::blockquote)) {
           // If so, remember it and the first node we are taking out of it.
@@ -4992,18 +4961,18 @@ HTMLEditRules::WillOutdent(Selection& aS
       }
 
       if (!curBlockQuote) {
         // Couldn't find enclosing blockquote.  Handle list cases.
         if (HTMLEditUtils::IsList(curParent)) {
           // Move node out of list
           if (HTMLEditUtils::IsList(curNode)) {
             // Just unwrap this sublist
-            rv = htmlEditor->RemoveBlockContainerWithTransaction(
-                               *curNode->AsElement());
+            rv = HTMLEditorRef().RemoveBlockContainerWithTransaction(
+                                   *curNode->AsElement());
             if (NS_WARN_IF(NS_FAILED(rv))) {
               return rv;
             }
           }
           // handled list item case above
         } else if (HTMLEditUtils::IsList(curNode)) {
           // node is a list, but parent is non-list: move list items out
           nsCOMPtr<nsIContent> child = curNode->GetLastChild();
@@ -5011,33 +4980,33 @@ HTMLEditRules::WillOutdent(Selection& aS
             if (HTMLEditUtils::IsListItem(child)) {
               rv = PopListItem(*child);
               NS_ENSURE_SUCCESS(rv, rv);
             } else if (HTMLEditUtils::IsList(child)) {
               // We have an embedded list, so move it out from under the parent
               // list. Be sure to put it after the parent list because this
               // loop iterates backwards through the parent's list of children.
               EditorRawDOMPoint afterCurrentList(curParent, offset + 1);
-              rv = htmlEditor->MoveNodeWithTransaction(*child,
-                                                       afterCurrentList);
+              rv = HTMLEditorRef().MoveNodeWithTransaction(*child,
+                                                           afterCurrentList);
               if (NS_WARN_IF(NS_FAILED(rv))) {
                 return rv;
               }
             } else {
               // Delete any non-list items for now
-              rv = htmlEditor->DeleteNodeWithTransaction(*child);
+              rv = HTMLEditorRef().DeleteNodeWithTransaction(*child);
               if (NS_WARN_IF(NS_FAILED(rv))) {
                 return rv;
               }
             }
             child = curNode->GetLastChild();
           }
           // Delete the now-empty list
-          rv = htmlEditor->RemoveBlockContainerWithTransaction(
-                             *curNode->AsElement());
+          rv = HTMLEditorRef().RemoveBlockContainerWithTransaction(
+                                 *curNode->AsElement());
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
         } else if (useCSS) {
           nsCOMPtr<Element> element;
           if (curNode->GetAsText()) {
             // We want to outdent the parent of text nodes
             element = curNode->GetParentElement();
@@ -5095,57 +5064,58 @@ HTMLEditRules::WillOutdent(Selection& aS
  * RemovePartOfBlock() splits aBlock and move aStartChild to aEndChild out of
  * aBlock.
  */
 nsresult
 HTMLEditRules::RemovePartOfBlock(Element& aBlock,
                                  nsIContent& aStartChild,
                                  nsIContent& aEndChild)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   SplitBlock(aBlock, aStartChild, aEndChild);
   // Get rid of part of blockquote we are outdenting
-
-  NS_ENSURE_STATE(mHTMLEditor);
-  nsresult rv = mHTMLEditor->RemoveBlockContainerWithTransaction(aBlock);
-  NS_ENSURE_SUCCESS(rv, rv);
-
+  nsresult rv = HTMLEditorRef().RemoveBlockContainerWithTransaction(aBlock);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
   return NS_OK;
 }
 
 void
 HTMLEditRules::SplitBlock(Element& aBlock,
                           nsIContent& aStartChild,
                           nsIContent& aEndChild,
                           nsIContent** aOutLeftNode,
                           nsIContent** aOutRightNode,
                           nsIContent** aOutMiddleNode)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   // aStartChild and aEndChild must be exclusive descendants of aBlock
   MOZ_ASSERT(EditorUtils::IsDescendantOf(aStartChild, aBlock) &&
              EditorUtils::IsDescendantOf(aEndChild, aBlock));
-  NS_ENSURE_TRUE_VOID(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
 
   // Split at the start.
   SplitNodeResult splitAtStartResult =
-    htmlEditor->SplitNodeDeepWithTransaction(
-                  aBlock, EditorRawDOMPoint(&aStartChild),
-                  SplitAtEdges::eDoNotCreateEmptyContainer);
+    HTMLEditorRef().SplitNodeDeepWithTransaction(
+                      aBlock, EditorRawDOMPoint(&aStartChild),
+                      SplitAtEdges::eDoNotCreateEmptyContainer);
   NS_WARNING_ASSERTION(splitAtStartResult.Succeeded(),
     "Failed to split aBlock at start");
 
   // Split at after the end
   EditorRawDOMPoint atAfterEnd(&aEndChild);
   DebugOnly<bool> advanced = atAfterEnd.AdvanceOffset();
   NS_WARNING_ASSERTION(advanced,
     "Failed to advance offset after the end node");
   SplitNodeResult splitAtEndResult =
-    htmlEditor->SplitNodeDeepWithTransaction(
-                  aBlock, atAfterEnd,
-                  SplitAtEdges::eDoNotCreateEmptyContainer);
+    HTMLEditorRef().SplitNodeDeepWithTransaction(
+                      aBlock, atAfterEnd,
+                      SplitAtEdges::eDoNotCreateEmptyContainer);
   NS_WARNING_ASSERTION(splitAtEndResult.Succeeded(),
     "Failed to split aBlock at after end");
 
   if (aOutLeftNode) {
     NS_IF_ADDREF(*aOutLeftNode = splitAtStartResult.GetPreviousNode());
   }
 
   if (aOutRightNode) {
@@ -5164,61 +5134,70 @@ HTMLEditRules::SplitBlock(Element& aBloc
 nsresult
 HTMLEditRules::OutdentPartOfBlock(Element& aBlock,
                                   nsIContent& aStartChild,
                                   nsIContent& aEndChild,
                                   bool aIsBlockIndentedWithCSS,
                                   nsIContent** aOutLeftNode,
                                   nsIContent** aOutRightNode)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aOutLeftNode && aOutRightNode);
 
   nsCOMPtr<nsIContent> middleNode;
   SplitBlock(aBlock, aStartChild, aEndChild, aOutLeftNode, aOutRightNode,
              getter_AddRefs(middleNode));
 
   if (NS_WARN_IF(!middleNode) || NS_WARN_IF(!middleNode->IsElement())) {
     return NS_ERROR_FAILURE;
   }
 
   if (!aIsBlockIndentedWithCSS) {
-    NS_ENSURE_STATE(mHTMLEditor);
     nsresult rv =
-      mHTMLEditor->RemoveBlockContainerWithTransaction(
-                     *middleNode->AsElement());
-    NS_ENSURE_SUCCESS(rv, rv);
-  } else if (middleNode->IsElement()) {
+      HTMLEditorRef().RemoveBlockContainerWithTransaction(
+                        *middleNode->AsElement());
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+    return NS_OK;
+  }
+
+  if (middleNode->IsElement()) {
     // We do nothing if middleNode isn't an element
     nsresult rv = ChangeIndentation(*middleNode->AsElement(), Change::minus);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+    return NS_OK;
   }
 
   return NS_OK;
 }
 
 /**
  * ConvertListType() converts list type and list item type.
  */
 already_AddRefed<Element>
 HTMLEditRules::ConvertListType(Element* aList,
                                nsAtom* aListType,
                                nsAtom* aItemType)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aList);
   MOZ_ASSERT(aListType);
   MOZ_ASSERT(aItemType);
 
   nsCOMPtr<nsINode> child = aList->GetFirstChild();
   while (child) {
     if (child->IsElement()) {
-      dom::Element* element = child->AsElement();
+      Element* element = child->AsElement();
       if (HTMLEditUtils::IsListItem(element) &&
           !element->IsHTMLElement(aItemType)) {
         child =
-          mHTMLEditor->ReplaceContainerWithTransaction(*element, *aItemType);
+          HTMLEditorRef().ReplaceContainerWithTransaction(*element, *aItemType);
         if (NS_WARN_IF(!child)) {
           return nullptr;
         }
       } else if (HTMLEditUtils::IsList(element) &&
                  !element->IsHTMLElement(aListType)) {
         child = ConvertListType(child->AsElement(), aListType, aItemType);
         if (NS_WARN_IF(!child)) {
           return nullptr;
@@ -5228,160 +5207,165 @@ HTMLEditRules::ConvertListType(Element* 
     child = child->GetNextSibling();
   }
 
   if (aList->IsHTMLElement(aListType)) {
     RefPtr<dom::Element> list = aList;
     return list.forget();
   }
 
-  return mHTMLEditor->ReplaceContainerWithTransaction(*aList, *aListType);
+  RefPtr<Element> listElement =
+    HTMLEditorRef().ReplaceContainerWithTransaction(*aList, *aListType);
+  NS_WARNING_ASSERTION(listElement != nullptr, "Failed to create list element");
+  return listElement.forget();
 }
 
 
 /**
  * CreateStyleForInsertText() takes care of clearing and setting appropriate
  * style nodes for text insertion.
  */
 nsresult
 HTMLEditRules::CreateStyleForInsertText(Selection& aSelection,
                                         nsIDocument& aDoc)
 {
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
-  MOZ_ASSERT(htmlEditor->mTypeInState);
+  MOZ_ASSERT(IsEditorDataAvailable());
+  MOZ_ASSERT(HTMLEditorRef().mTypeInState);
 
   bool weDidSomething = false;
   NS_ENSURE_STATE(aSelection.GetRangeAt(0));
   nsCOMPtr<nsINode> node = aSelection.GetRangeAt(0)->GetStartContainer();
   int32_t offset = aSelection.GetRangeAt(0)->StartOffset();
 
   nsCOMPtr<Element> rootElement = aDoc.GetRootElement();
   NS_ENSURE_STATE(rootElement);
 
   // process clearing any styles first
   UniquePtr<PropItem> item =
-    Move(htmlEditor->mTypeInState->TakeClearProperty());
+    Move(HTMLEditorRef().mTypeInState->TakeClearProperty());
 
   {
     // Transactions may set selection, but we will set selection if necessary.
-    AutoTransactionsConserveSelection dontChangeMySelection(htmlEditor);
+    AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
 
     while (item && node != rootElement) {
       // XXX If we redesign ClearStyle(), we can use EditorDOMPoint in this
       //     method.
       nsresult rv =
-        htmlEditor->ClearStyle(address_of(node), &offset,
-                               item->tag, item->attr);
-      NS_ENSURE_SUCCESS(rv, rv);
-      item = Move(htmlEditor->mTypeInState->TakeClearProperty());
+        HTMLEditorRef().ClearStyle(address_of(node), &offset,
+                                   item->tag, item->attr);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      item = Move(HTMLEditorRef().mTypeInState->TakeClearProperty());
       weDidSomething = true;
     }
   }
 
   // then process setting any styles
-  int32_t relFontSize = htmlEditor->mTypeInState->TakeRelativeFontSize();
-  item = Move(htmlEditor->mTypeInState->TakeSetProperty());
+  int32_t relFontSize = HTMLEditorRef().mTypeInState->TakeRelativeFontSize();
+  item = Move(HTMLEditorRef().mTypeInState->TakeSetProperty());
 
   if (item || relFontSize) {
     // we have at least one style to add; make a new text node to insert style
     // nodes above.
     if (RefPtr<Text> text = node->GetAsText()) {
       // if we are in a text node, split it
       SplitNodeResult splitTextNodeResult =
-        htmlEditor->SplitNodeDeepWithTransaction(
-                       *text, EditorRawDOMPoint(text, offset),
-                       SplitAtEdges::eAllowToCreateEmptyContainer);
+        HTMLEditorRef().SplitNodeDeepWithTransaction(
+                          *text, EditorRawDOMPoint(text, offset),
+                          SplitAtEdges::eAllowToCreateEmptyContainer);
       if (NS_WARN_IF(splitTextNodeResult.Failed())) {
         return splitTextNodeResult.Rv();
       }
       EditorRawDOMPoint splitPoint(splitTextNodeResult.SplitPoint());
       node = splitPoint.GetContainer();
       offset = splitPoint.Offset();
     }
-    if (!htmlEditor->IsContainer(node)) {
+    if (!HTMLEditorRef().IsContainer(node)) {
       return NS_OK;
     }
     OwningNonNull<Text> newNode =
       EditorBase::CreateTextNode(aDoc, EmptyString());
     nsresult rv =
-      htmlEditor->InsertNodeWithTransaction(*newNode,
-                                            EditorRawDOMPoint(node, offset));
+      HTMLEditorRef().InsertNodeWithTransaction(
+                        *newNode, EditorRawDOMPoint(node, offset));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     node = newNode;
     offset = 0;
     weDidSomething = true;
 
     if (relFontSize) {
       // dir indicated bigger versus smaller.  1 = bigger, -1 = smaller
       HTMLEditor::FontSize dir = relFontSize > 0 ?
         HTMLEditor::FontSize::incr : HTMLEditor::FontSize::decr;
       for (int32_t j = 0; j < DeprecatedAbs(relFontSize); j++) {
-        rv = htmlEditor->RelativeFontChangeOnTextNode(dir, newNode, 0, -1);
-        NS_ENSURE_SUCCESS(rv, rv);
+        rv = HTMLEditorRef().RelativeFontChangeOnTextNode(dir, newNode, 0, -1);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
       }
     }
 
     while (item) {
-      rv = htmlEditor->SetInlinePropertyOnNode(*node->AsContent(),
-                                               *item->tag, item->attr,
-                                               item->value);
-      NS_ENSURE_SUCCESS(rv, rv);
-      item = htmlEditor->mTypeInState->TakeSetProperty();
+      rv = HTMLEditorRef().SetInlinePropertyOnNode(*node->AsContent(),
+                                                   *item->tag, item->attr,
+                                                   item->value);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+      item = HTMLEditorRef().mTypeInState->TakeSetProperty();
     }
   }
   if (weDidSomething) {
     return aSelection.Collapse(node, offset);
   }
 
   return NS_OK;
 }
 
 bool
 HTMLEditRules::IsEmptyBlockElement(Element& aElement,
                                    IgnoreSingleBR aIgnoreSingleBR)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (NS_WARN_IF(!IsBlockNode(aElement))) {
     return false;
   }
   bool isEmpty = true;
   nsresult rv =
-    mHTMLEditor->IsEmptyNode(&aElement, &isEmpty,
-                             aIgnoreSingleBR == IgnoreSingleBR::eYes);
+    HTMLEditorRef().IsEmptyNode(&aElement, &isEmpty,
+                                aIgnoreSingleBR == IgnoreSingleBR::eYes);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return false;
   }
   return isEmpty;
 }
 
 nsresult
 HTMLEditRules::WillAlign(Selection& aSelection,
                          const nsAString& aAlignType,
                          bool* aCancel,
                          bool* aHandled)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aCancel && aHandled);
 
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   WillInsert(aSelection, aCancel);
 
   // Initialize out param.  We want to ignore result of WillInsert().
   *aCancel = false;
   *aHandled = false;
 
   nsresult rv = NormalizeSelection(&aSelection);
   NS_ENSURE_SUCCESS(rv, rv);
-  AutoSelectionRestorer selectionRestorer(&aSelection, htmlEditor);
+  AutoSelectionRestorer selectionRestorer(&aSelection, &HTMLEditorRef());
 
   // Convert the selection ranges into "promoted" selection ranges: This
   // basically just expands the range to include the immediate block parent,
   // and then further expands to include any ancestors whose children are all
   // in the range
   *aHandled = true;
   nsTArray<OwningNonNull<nsINode>> nodeArray;
   rv = GetNodesFromSelection(aSelection, EditAction::align, nodeArray);
@@ -5442,36 +5426,39 @@ HTMLEditRules::WillAlign(Selection& aSel
                                                   atStartOfSelection);
     if (NS_WARN_IF(splitNodeResult.Failed())) {
       return splitNodeResult.Rv();
     }
 
     // Consume a trailing br, if any.  This is to keep an alignment from
     // creating extra lines, if possible.
     nsCOMPtr<nsIContent> brContent =
-      htmlEditor->GetNextEditableHTMLNodeInBlock(splitNodeResult.SplitPoint());
+      HTMLEditorRef().GetNextEditableHTMLNodeInBlock(
+                        splitNodeResult.SplitPoint());
     EditorDOMPoint pointToInsertDiv(splitNodeResult.SplitPoint());
     if (brContent && TextEditUtils::IsBreak(brContent)) {
       // Making use of html structure... if next node after where we are
       // putting our div is not a block, then the br we found is in same block
       // we are, so it's safe to consume it.
       nsCOMPtr<nsIContent> sibling;
       if (pointToInsertDiv.GetChild()) {
-        sibling = htmlEditor->GetNextHTMLSibling(pointToInsertDiv.GetChild());
+        sibling =
+          HTMLEditorRef().GetNextHTMLSibling(pointToInsertDiv.GetChild());
       }
       if (sibling && !IsBlockNode(*sibling)) {
         AutoEditorDOMPointChildInvalidator lockOffset(pointToInsertDiv);
-        rv = htmlEditor->DeleteNodeWithTransaction(*brContent);
+        rv = HTMLEditorRef().DeleteNodeWithTransaction(*brContent);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
     }
     RefPtr<Element> div =
-      htmlEditor->CreateNodeWithTransaction(*nsGkAtoms::div, pointToInsertDiv);
+      HTMLEditorRef().CreateNodeWithTransaction(*nsGkAtoms::div,
+                                                pointToInsertDiv);
     if (NS_WARN_IF(!div)) {
       return NS_ERROR_FAILURE;
     }
     // Remember our new block for postprocessing
     mNewBlock = div;
     // Set up the alignment on the div, using HTML or CSS
     rv = AlignBlock(*div, aAlignType, ContentsOnly::yes);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -5497,23 +5484,23 @@ HTMLEditRules::WillAlign(Selection& aSel
 
   nsTArray<bool> transitionList;
   MakeTransitionList(nodeArray, transitionList);
 
   // Okay, now go through all the nodes and give them an align attrib or put
   // them in a div, or whatever is appropriate.  Woohoo!
 
   nsCOMPtr<Element> curDiv;
-  bool useCSS = htmlEditor->IsCSSEnabled();
+  bool useCSS = HTMLEditorRef().IsCSSEnabled();
   int32_t indexOfTransitionList = -1;
   for (OwningNonNull<nsINode>& curNode : nodeArray) {
     ++indexOfTransitionList;
 
     // Ignore all non-editable nodes.  Leave them be.
-    if (!htmlEditor->IsEditable(curNode)) {
+    if (!HTMLEditorRef().IsEditable(curNode)) {
       continue;
     }
 
     // The node is a table element, an hr, a paragraph, a div or a section
     // header; in HTML 4, it can directly carry the ALIGN attribute and we
     // don't need to nest it, just set the alignment.  In CSS, assign the
     // corresponding CSS styles in AlignBlock
     if (HTMLEditUtils::SupportsAlignAttr(*curNode)) {
@@ -5531,32 +5518,33 @@ HTMLEditRules::WillAlign(Selection& aSel
 
     // Skip insignificant formatting text nodes to prevent unnecessary
     // structure splitting!
     bool isEmptyTextNode = false;
     if (curNode->GetAsText() &&
         ((HTMLEditUtils::IsTableElement(atCurNode.GetContainer()) &&
           !HTMLEditUtils::IsTableCellOrCaption(*atCurNode.GetContainer())) ||
          HTMLEditUtils::IsList(atCurNode.GetContainer()) ||
-         (NS_SUCCEEDED(htmlEditor->IsEmptyNode(curNode, &isEmptyTextNode)) &&
+         (NS_SUCCEEDED(HTMLEditorRef().IsEmptyNode(curNode,
+                                                   &isEmptyTextNode)) &&
           isEmptyTextNode))) {
       continue;
     }
 
     // If it's a list item, or a list inside a list, forget any "current" div,
     // and instead put divs inside the appropriate block (td, li, etc.)
     if (HTMLEditUtils::IsListItem(curNode) ||
         HTMLEditUtils::IsList(curNode)) {
       AutoEditorDOMPointOffsetInvalidator lockChild(atCurNode);
       rv = RemoveAlignment(*curNode, aAlignType, true);
       NS_ENSURE_SUCCESS(rv, rv);
       if (useCSS) {
-        htmlEditor->mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
-            curNode->AsElement(), nullptr,
-            nsGkAtoms::align, &aAlignType, false);
+        HTMLEditorRef().mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
+                                         curNode->AsElement(), nullptr,
+                                         nsGkAtoms::align, &aAlignType, false);
         curDiv = nullptr;
         continue;
       }
       if (HTMLEditUtils::IsList(atCurNode.GetContainer())) {
         // If we don't use CSS, add a contraint to list element: they have to
         // be inside another list, i.e., >= second level of nesting
         rv = AlignInnerBlocks(*curNode, aAlignType);
         NS_ENSURE_SUCCESS(rv, rv);
@@ -5565,58 +5553,60 @@ HTMLEditRules::WillAlign(Selection& aSel
       }
       // Clear out curDiv so that we don't put nodes after this one into it
     }
 
     // Need to make a div to put things in if we haven't already, or if this
     // node doesn't go in div we used earlier.
     if (!curDiv || transitionList[indexOfTransitionList]) {
       // First, check that our element can contain a div.
-      if (!htmlEditor->CanContainTag(*atCurNode.GetContainer(),
-                                     *nsGkAtoms::div)) {
+      if (!HTMLEditorRef().CanContainTag(*atCurNode.GetContainer(),
+                                         *nsGkAtoms::div)) {
         // Cancelled
         return NS_OK;
       }
 
       SplitNodeResult splitNodeResult =
         MaybeSplitAncestorsForInsertWithTransaction(*nsGkAtoms::div, atCurNode);
       if (NS_WARN_IF(splitNodeResult.Failed())) {
         return splitNodeResult.Rv();
       }
       curDiv =
-        htmlEditor->CreateNodeWithTransaction(*nsGkAtoms::div,
-                                              splitNodeResult.SplitPoint());
+        HTMLEditorRef().CreateNodeWithTransaction(*nsGkAtoms::div,
+                                                  splitNodeResult.SplitPoint());
       if (NS_WARN_IF(!curDiv)) {
         return NS_ERROR_FAILURE;
       }
       // Remember our new block for postprocessing
       mNewBlock = curDiv;
       // Set up the alignment on the div
       rv = AlignBlock(*curDiv, aAlignType, ContentsOnly::yes);
     }
 
     // Tuck the node into the end of the active div
-    rv = htmlEditor->MoveNodeToEndWithTransaction(*curNode->AsContent(),
-                                                  *curDiv);
+    rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode->AsContent(),
+                                                      *curDiv);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   return NS_OK;
 }
 
 
 /**
  * AlignInnerBlocks() aligns inside table cells or list items.
  */
 nsresult
 HTMLEditRules::AlignInnerBlocks(nsINode& aNode,
                                 const nsAString& aAlignType)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   // Gather list of table cells or list items
   nsTArray<OwningNonNull<nsINode>> nodeArray;
   TableCellAndListItemFunctor functor;
   DOMIterator iter(aNode);
   iter.AppendList(functor, nodeArray);
 
   // Now that we have the list, align their contents as requested
   for (auto& node : nodeArray) {
@@ -5632,122 +5622,122 @@ HTMLEditRules::AlignInnerBlocks(nsINode&
 
 /**
  * AlignBlockContents() aligns contents of a block element.
  */
 nsresult
 HTMLEditRules::AlignBlockContents(nsINode& aNode,
                                   const nsAString& aAlignType)
 {
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
-  nsCOMPtr<nsIContent> firstChild = htmlEditor->GetFirstEditableChild(aNode);
+  MOZ_ASSERT(IsEditorDataAvailable());
+
+  nsCOMPtr<nsIContent> firstChild =
+    HTMLEditorRef().GetFirstEditableChild(aNode);
   if (!firstChild) {
     // this cell has no content, nothing to align
     return NS_OK;
   }
 
-  nsCOMPtr<nsIContent> lastChild = htmlEditor->GetLastEditableChild(aNode);
+  nsCOMPtr<nsIContent> lastChild = HTMLEditorRef().GetLastEditableChild(aNode);
   if (firstChild == lastChild && firstChild->IsHTMLElement(nsGkAtoms::div)) {
     // the cell already has a div containing all of its content: just
     // act on this div.
-    return htmlEditor->SetAttributeOrEquivalent(firstChild->AsElement(),
-                                                nsGkAtoms::align,
-                                                aAlignType, false);
+    return HTMLEditorRef().SetAttributeOrEquivalent(firstChild->AsElement(),
+                                                    nsGkAtoms::align,
+                                                    aAlignType, false);
   }
 
   // else we need to put in a div, set the alignment, and toss in all the
   // children
   EditorRawDOMPoint atStartOfNode(&aNode, 0);
   RefPtr<Element> divElem =
-    htmlEditor->CreateNodeWithTransaction(*nsGkAtoms::div, atStartOfNode);
+    HTMLEditorRef().CreateNodeWithTransaction(*nsGkAtoms::div, atStartOfNode);
   if (NS_WARN_IF(!divElem)) {
     return NS_ERROR_FAILURE;
   }
   // set up the alignment on the div
   nsresult rv =
-    htmlEditor->SetAttributeOrEquivalent(divElem, nsGkAtoms::align,
-                                         aAlignType, false);
+    HTMLEditorRef().SetAttributeOrEquivalent(divElem, nsGkAtoms::align,
+                                             aAlignType, false);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   // tuck the children into the end of the active div
   while (lastChild && (lastChild != divElem)) {
     nsresult rv =
-      htmlEditor->MoveNodeWithTransaction(*lastChild,
-                                          EditorRawDOMPoint(divElem, 0));
+      HTMLEditorRef().MoveNodeWithTransaction(*lastChild,
+                                              EditorRawDOMPoint(divElem, 0));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
-    lastChild = htmlEditor->GetLastEditableChild(aNode);
+    lastChild = HTMLEditorRef().GetLastEditableChild(aNode);
   }
   return NS_OK;
 }
 
 /**
  * CheckForEmptyBlock() is called by WillDeleteSelection() to detect and handle
  * case of deleting from inside an empty block.
  */
 nsresult
 HTMLEditRules::CheckForEmptyBlock(nsINode* aStartNode,
                                   Element* aBodyNode,
                                   Selection* aSelection,
                                   nsIEditor::EDirection aAction,
                                   bool* aHandled)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   // If the editing host is an inline element, bail out early.
   if (aBodyNode && IsInlineNode(*aBodyNode)) {
     return NS_OK;
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   // If we are inside an empty block, delete it.  Note: do NOT delete table
   // elements this way.
-  RefPtr<Element> block = htmlEditor->GetBlock(*aStartNode);
+  RefPtr<Element> block = HTMLEditorRef().GetBlock(*aStartNode);
   bool bIsEmptyNode;
   RefPtr<Element> emptyBlock;
   if (block && block != aBodyNode) {
     // Efficiency hack, avoiding IsEmptyNode() call when in body
-    nsresult rv = htmlEditor->IsEmptyNode(block, &bIsEmptyNode, true, false);
-    NS_ENSURE_SUCCESS(rv, rv);
+    nsresult rv =
+      HTMLEditorRef().IsEmptyNode(block, &bIsEmptyNode, true, false);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
     while (block && bIsEmptyNode && !HTMLEditUtils::IsTableElement(block) &&
            block != aBodyNode) {
       emptyBlock = block;
-      block = htmlEditor->GetBlockNodeParent(emptyBlock);
+      block = HTMLEditorRef().GetBlockNodeParent(emptyBlock);
       if (block) {
-        rv = htmlEditor->IsEmptyNode(block, &bIsEmptyNode, true, false);
-        NS_ENSURE_SUCCESS(rv, rv);
+        rv = HTMLEditorRef().IsEmptyNode(block, &bIsEmptyNode, true, false);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
       }
     }
   }
 
   if (emptyBlock && emptyBlock->IsEditable()) {
     nsCOMPtr<nsINode> blockParent = emptyBlock->GetParentNode();
     NS_ENSURE_TRUE(blockParent, NS_ERROR_FAILURE);
 
     if (HTMLEditUtils::IsListItem(emptyBlock)) {
       // Are we the first list item in the list?
-      if (htmlEditor->IsFirstEditableChild(emptyBlock)) {
+      if (HTMLEditorRef().IsFirstEditableChild(emptyBlock)) {
         EditorDOMPoint atBlockParent(blockParent);
         if (NS_WARN_IF(!atBlockParent.IsSet())) {
           return NS_ERROR_FAILURE;
         }
         // If we are a sublist, skip the br creation
         if (!HTMLEditUtils::IsList(atBlockParent.GetContainer())) {
           // Create a br before list
           RefPtr<Element> brElement =
-            htmlEditor->InsertBrElementWithTransaction(*aSelection,
-                                                       atBlockParent);
+            HTMLEditorRef().InsertBrElementWithTransaction(*aSelection,
+                                                           atBlockParent);
           if (NS_WARN_IF(!brElement)) {
             return NS_ERROR_FAILURE;
           }
           // Adjust selection to be right before it
           ErrorResult error;
           aSelection->Collapse(EditorRawDOMPoint(brElement), error);
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
@@ -5760,17 +5750,17 @@ HTMLEditRules::CheckForEmptyBlock(nsINod
       if (aAction == nsIEditor::eNext || aAction == nsIEditor::eNextWord ||
           aAction == nsIEditor::eToEndOfLine) {
         // Move to the start of the next node, if any
         EditorRawDOMPoint afterEmptyBlock(emptyBlock);
         DebugOnly<bool> advanced = afterEmptyBlock.AdvanceOffset();
         NS_WARNING_ASSERTION(advanced,
           "Failed to set selection to the after the empty block");
         nsCOMPtr<nsIContent> nextNode =
-          htmlEditor->GetNextNode(afterEmptyBlock);
+          HTMLEditorRef().GetNextNode(afterEmptyBlock);
         if (nextNode) {
           EditorDOMPoint pt = GetGoodSelPointForNode(*nextNode, aAction);
           ErrorResult error;
           aSelection->Collapse(pt, error);
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
         } else {
@@ -5786,17 +5776,17 @@ HTMLEditRules::CheckForEmptyBlock(nsINod
           }
         }
       } else if (aAction == nsIEditor::ePrevious ||
                  aAction == nsIEditor::ePreviousWord ||
                  aAction == nsIEditor::eToBeginningOfLine) {
         // Move to the end of the previous node
         EditorRawDOMPoint atEmptyBlock(emptyBlock);
         nsCOMPtr<nsIContent> priorNode =
-          htmlEditor->GetPreviousEditableNode(atEmptyBlock);
+          HTMLEditorRef().GetPreviousEditableNode(atEmptyBlock);
         if (priorNode) {
           EditorDOMPoint pt = GetGoodSelPointForNode(*priorNode, aAction);
           nsresult rv = aSelection->Collapse(pt);
           NS_ENSURE_SUCCESS(rv, rv);
         } else {
           EditorRawDOMPoint afterEmptyBlock(emptyBlock);
           if (NS_WARN_IF(!afterEmptyBlock.AdvanceOffset())) {
             return NS_ERROR_FAILURE;
@@ -5804,36 +5794,38 @@ HTMLEditRules::CheckForEmptyBlock(nsINod
           nsresult rv = aSelection->Collapse(afterEmptyBlock);
           NS_ENSURE_SUCCESS(rv, rv);
         }
       } else if (aAction != nsIEditor::eNone) {
         MOZ_CRASH("CheckForEmptyBlock doesn't support this action yet");
       }
     }
     *aHandled = true;
-    nsresult rv = htmlEditor->DeleteNodeWithTransaction(*emptyBlock);
+    nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(*emptyBlock);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
   return NS_OK;
 }
 
 Element*
 HTMLEditRules::CheckForInvisibleBR(Element& aBlock,
                                    BRLocation aWhere,
                                    int32_t aOffset)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   nsCOMPtr<nsINode> testNode;
   int32_t testOffset = 0;
 
   if (aWhere == BRLocation::blockEnd) {
     // No block crossing
     nsCOMPtr<nsIContent> rightmostNode =
-      mHTMLEditor->GetRightmostChild(&aBlock, true);
+      HTMLEditorRef().GetRightmostChild(&aBlock, true);
 
     if (!rightmostNode) {
       return nullptr;
     }
 
     testNode = rightmostNode->GetParentNode();
     // Since rightmostNode is always the last child, its index is equal to the
     // child count, so instead of ComputeIndexOf() we use the faster
@@ -5845,17 +5837,17 @@ HTMLEditRules::CheckForInvisibleBR(Eleme
   } else if (aOffset) {
     testNode = &aBlock;
     // We'll check everything to the left of the input position
     testOffset = aOffset;
   } else {
     return nullptr;
   }
 
-  WSRunObject wsTester(mHTMLEditor, testNode, testOffset);
+  WSRunObject wsTester(&HTMLEditorRef(), testNode, testOffset);
   if (WSType::br == wsTester.mStartReason) {
     return wsTester.mStartReasonNode->AsElement();
   }
 
   return nullptr;
 }
 
 /**
@@ -5868,19 +5860,20 @@ HTMLEditRules::CheckForInvisibleBR(Eleme
 void
 HTMLEditRules::GetInnerContent(
                  nsINode& aNode,
                  nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
                  int32_t* aIndex,
                  Lists aLists,
                  Tables aTables)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aIndex);
 
-  for (nsCOMPtr<nsIContent> node = mHTMLEditor->GetFirstEditableChild(aNode);
+  for (nsCOMPtr<nsIContent> node = HTMLEditorRef().GetFirstEditableChild(aNode);
        node; node = node->GetNextSibling()) {
     if ((aLists == Lists::yes && (HTMLEditUtils::IsList(node) ||
                                   HTMLEditUtils::IsListItem(node))) ||
         (aTables == Tables::yes && HTMLEditUtils::IsTableElement(node))) {
       GetInnerContent(*node, aOutArrayOfNodes, aIndex, aLists, aTables);
     } else {
       aOutArrayOfNodes.InsertElementAt(*aIndex, *node);
       (*aIndex)++;
@@ -5889,16 +5882,18 @@ HTMLEditRules::GetInnerContent(
 }
 
 /**
  * Promotes selection to include blocks that have all their children selected.
  */
 nsresult
 HTMLEditRules::ExpandSelectionForDeletion(Selection& aSelection)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   // Don't need to touch collapsed selections
   if (aSelection.IsCollapsed()) {
     return NS_OK;
   }
 
   // We don't need to mess with cell selections, and we assume multirange
   // selections are those.
   if (aSelection.RangeCount() != 1) {
@@ -5919,23 +5914,25 @@ HTMLEditRules::ExpandSelectionForDeletio
     HTMLEditor::GetBlock(*range->GetCommonAncestor());
   NS_ENSURE_STATE(selCommon);
 
   // Set up for loops and cache our root element
   nsCOMPtr<nsINode> firstBRParent;
   nsCOMPtr<nsINode> unused;
   int32_t visOffset = 0, firstBROffset = 0;
   WSType wsType;
-  nsCOMPtr<Element> root = mHTMLEditor->GetActiveEditingHost();
-  NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
+  RefPtr<Element> root = HTMLEditorRef().GetActiveEditingHost();
+  if (NS_WARN_IF(!root)) {
+    return NS_ERROR_FAILURE;
+  }
 
   // Find previous visible thingy before start of selection
   if (selStartNode != selCommon && selStartNode != root) {
     while (true) {
-      WSRunObject wsObj(mHTMLEditor, selStartNode, selStartOffset);
+      WSRunObject wsObj(&HTMLEditorRef(), selStartNode, selStartOffset);
       wsObj.PriorVisibleNode(EditorRawDOMPoint(selStartNode, selStartOffset),
                              address_of(unused), &visOffset, &wsType);
       if (wsType != WSType::thisBlock) {
         break;
       }
       // We want to keep looking up.  But stop if we are crossing table
       // element boundaries, or if we hit the root.
       if (HTMLEditUtils::IsTableElement(wsObj.mStartReasonNode) ||
@@ -5947,21 +5944,21 @@ HTMLEditRules::ExpandSelectionForDeletio
       selStartOffset = selStartNode ?
         selStartNode->ComputeIndexOf(wsObj.mStartReasonNode) : -1;
     }
   }
 
   // Find next visible thingy after end of selection
   if (selEndNode != selCommon && selEndNode != root) {
     for (;;) {
-      WSRunObject wsObj(mHTMLEditor, selEndNode, selEndOffset);
+      WSRunObject wsObj(&HTMLEditorRef(), selEndNode, selEndOffset);
       wsObj.NextVisibleNode(EditorRawDOMPoint(selEndNode, selEndOffset),
                             address_of(unused), &visOffset, &wsType);
       if (wsType == WSType::br) {
-        if (mHTMLEditor->IsVisibleBRElement(wsObj.mEndReasonNode)) {
+        if (HTMLEditorRef().IsVisibleBRElement(wsObj.mEndReasonNode)) {
           break;
         }
         if (!firstBRParent) {
           firstBRParent = selEndNode;
           firstBROffset = selEndOffset;
         }
         selEndNode = wsObj.mEndReasonNode->GetParentNode();
         selEndOffset = selEndNode
@@ -6027,35 +6024,34 @@ HTMLEditRules::ExpandSelectionForDeletio
  * Idea here is to adjust selection endpoint so that they do not cross breaks
  * or block boundaries unless something editable beyond that boundary is also
  * selected.  This adjustment makes it much easier for the various block
  * operations to determine what nodes to act on.
  */
 nsresult
 HTMLEditRules::NormalizeSelection(Selection* inSelection)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   NS_ENSURE_TRUE(inSelection, NS_ERROR_NULL_POINTER);
 
   // don't need to touch collapsed selections
   if (inSelection->IsCollapsed()) {
     return NS_OK;
   }
 
   // we don't need to mess with cell selections, and we assume multirange selections are those.
   if (inSelection->RangeCount() != 1) {
     return NS_OK;
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-  RefPtr<HTMLEditor> htmlEditor = mHTMLEditor;
-
   RefPtr<nsRange> range = inSelection->GetRangeAt(0);
-  NS_ENSURE_TRUE(range, NS_ERROR_NULL_POINTER);
+  if (NS_WARN_IF(!range)) {
+    return NS_ERROR_FAILURE;
+  }
 
   nsCOMPtr<nsINode> startNode = range->GetStartContainer();
   if (NS_WARN_IF(!startNode)) {
     return NS_ERROR_FAILURE;
   }
   nsCOMPtr<nsINode> endNode = range->GetEndContainer();
   if (NS_WARN_IF(!endNode)) {
     return NS_ERROR_FAILURE;
@@ -6072,39 +6068,40 @@ HTMLEditRules::NormalizeSelection(Select
   uint32_t newEndOffset = endOffset;
 
   // some locals we need for whitespace code
   nsCOMPtr<nsINode> unused;
   int32_t offset = -1;
   WSType wsType;
 
   // let the whitespace code do the heavy lifting
-  WSRunObject wsEndObj(htmlEditor, endNode, static_cast<int32_t>(endOffset));
+  WSRunObject wsEndObj(&HTMLEditorRef(), endNode,
+                       static_cast<int32_t>(endOffset));
   // is there any intervening visible whitespace?  if so we can't push selection past that,
   // it would visibly change maening of users selection
   wsEndObj.PriorVisibleNode(EditorRawDOMPoint(endNode, endOffset),
                             address_of(unused), &offset, &wsType);
   if (wsType != WSType::text && wsType != WSType::normalWS) {
     // eThisBlock and eOtherBlock conveniently distinquish cases
     // of going "down" into a block and "up" out of a block.
     if (wsEndObj.mStartReason == WSType::otherBlock) {
       // endpoint is just after the close of a block.
       nsINode* child =
-        htmlEditor->GetRightmostChild(wsEndObj.mStartReasonNode, true);
+        HTMLEditorRef().GetRightmostChild(wsEndObj.mStartReasonNode, true);
       if (child) {
         int32_t offset = -1;
         newEndNode = EditorBase::GetNodeLocation(child, &offset);
         // offset *after* child
         newEndOffset = static_cast<uint32_t>(offset + 1);
       }
       // else block is empty - we can leave selection alone here, i think.
     } else if (wsEndObj.mStartReason == WSType::thisBlock) {
       // endpoint is just after start of this block
       EditorRawDOMPoint atEnd(endNode, endChild, endOffset);
-      nsINode* child = htmlEditor->GetPreviousEditableHTMLNode(atEnd);
+      nsINode* child = HTMLEditorRef().GetPreviousEditableHTMLNode(atEnd);
       if (child) {
         int32_t offset = -1;
         newEndNode = EditorBase::GetNodeLocation(child, &offset);
         // offset *after* child
         newEndOffset = static_cast<uint32_t>(offset + 1);
       }
       // else block is empty - we can leave selection alone here, i think.
     } else if (wsEndObj.mStartReason == WSType::br) {
@@ -6113,40 +6110,41 @@ HTMLEditRules::NormalizeSelection(Select
       newEndNode =
         EditorBase::GetNodeLocation(wsEndObj.mStartReasonNode, &offset);
       newEndOffset = static_cast<uint32_t>(offset);;
     }
   }
 
 
   // similar dealio for start of range
-  WSRunObject wsStartObj(htmlEditor, startNode,
+  WSRunObject wsStartObj(&HTMLEditorRef(), startNode,
                          static_cast<int32_t>(startOffset));
   // is there any intervening visible whitespace?  if so we can't push selection past that,
   // it would visibly change maening of users selection
   wsStartObj.NextVisibleNode(EditorRawDOMPoint(startNode, startOffset),
                              address_of(unused), &offset, &wsType);
   if (wsType != WSType::text && wsType != WSType::normalWS) {
     // eThisBlock and eOtherBlock conveniently distinquish cases
     // of going "down" into a block and "up" out of a block.
     if (wsStartObj.mEndReason == WSType::otherBlock) {
       // startpoint is just before the start of a block.
       nsINode* child =
-        htmlEditor->GetLeftmostChild(wsStartObj.mEndReasonNode, true);
+        HTMLEditorRef().GetLeftmostChild(wsStartObj.mEndReasonNode, true);
       if (child) {
         int32_t offset = -1;
         newStartNode = EditorBase::GetNodeLocation(child, &offset);
         newStartOffset = static_cast<uint32_t>(offset);
       }
       // else block is empty - we can leave selection alone here, i think.
     } else if (wsStartObj.mEndReason == WSType::thisBlock) {
       // startpoint is just before end of this block
       nsINode* child =
-        htmlEditor->GetNextEditableHTMLNode(
-                      EditorRawDOMPoint(startNode, startChild, startOffset));
+        HTMLEditorRef().GetNextEditableHTMLNode(
+                          EditorRawDOMPoint(startNode,
+                                            startChild, startOffset));
       if (child) {
         int32_t offset = -1;
         newStartNode = EditorBase::GetNodeLocation(child, &offset);
         newStartOffset = static_cast<uint32_t>(offset);
       }
       // else block is empty - we can leave selection alone here, i think.
     } else if (wsStartObj.mEndReason == WSType::br) {
       // startpoint is just before a break.  lets adjust it to after it.
@@ -6189,20 +6187,17 @@ HTMLEditRules::NormalizeSelection(Select
  * operation really is.
  */
 EditorDOMPoint
 HTMLEditRules::GetPromotedPoint(RulesEndpoint aWhere,
                                 nsINode& aNode,
                                 int32_t aOffset,
                                 EditAction actionID)
 {
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return EditorDOMPoint(&aNode, aOffset);
-  }
-  RefPtr<HTMLEditor> htmlEditor = mHTMLEditor;
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   // we do one thing for text actions, something else entirely for other
   // actions
   if (actionID == EditAction::insertText ||
       actionID == EditAction::insertIMEText ||
       actionID == EditAction::insertBreak ||
       actionID == EditAction::deleteText) {
     bool isSpace, isNBSP;
@@ -6212,23 +6207,25 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
     int32_t newOffset = aOffset;
     // for text actions, we want to look backwards (or forwards, as
     // appropriate) for additional whitespace or nbsp's.  We may have to act on
     // these later even though they are outside of the initial selection.  Even
     // if they are in another node!
     while (content) {
       int32_t offset;
       if (aWhere == kStart) {
-        htmlEditor->IsPrevCharInNodeWhitespace(content, newOffset,
-                                               &isSpace, &isNBSP,
-                                               getter_AddRefs(temp), &offset);
+        HTMLEditorRef().IsPrevCharInNodeWhitespace(content, newOffset,
+                                                   &isSpace, &isNBSP,
+                                                   getter_AddRefs(temp),
+                                                   &offset);
       } else {
-        htmlEditor->IsNextCharInNodeWhitespace(content, newOffset,
-                                               &isSpace, &isNBSP,
-                                               getter_AddRefs(temp), &offset);
+        HTMLEditorRef().IsNextCharInNodeWhitespace(content, newOffset,
+                                                   &isSpace, &isNBSP,
+                                                   getter_AddRefs(temp),
+                                                   &offset);
       }
       if (isSpace || isNBSP) {
         content = temp;
         newOffset = offset;
       } else {
         break;
       }
     }
@@ -6248,30 +6245,30 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
         return point;
       }
       point.Set(point.GetContainer());
     }
 
     // look back through any further inline nodes that aren't across a <br>
     // from us, and that are enclosed in the same block.
     nsCOMPtr<nsINode> priorNode =
-      htmlEditor->GetPreviousEditableHTMLNodeInBlock(point);
+      HTMLEditorRef().GetPreviousEditableHTMLNodeInBlock(point);
 
     while (priorNode && priorNode->GetParentNode() &&
-           !htmlEditor->IsVisibleBRElement(priorNode) &&
+           !HTMLEditorRef().IsVisibleBRElement(priorNode) &&
            !IsBlockNode(*priorNode)) {
       point.Set(priorNode);
-      priorNode = htmlEditor->GetPreviousEditableHTMLNodeInBlock(point);
+      priorNode = HTMLEditorRef().GetPreviousEditableHTMLNodeInBlock(point);
     }
 
     // finding the real start for this point.  look up the tree for as long as
     // we are the first node in the container, and as long as we haven't hit
     // the body node.
     nsCOMPtr<nsIContent> nearNode =
-      htmlEditor->GetPreviousEditableHTMLNodeInBlock(point);
+      HTMLEditorRef().GetPreviousEditableHTMLNodeInBlock(point);
     while (!nearNode &&
            !point.IsContainerHTMLElement(nsGkAtoms::body) &&
            point.GetContainer()->GetParentNode()) {
       // some cutoffs are here: we don't need to also include them in the
       // aWhere == kEnd case.  as long as they are in one or the other it will
       // work.  special case for outdent: don't keep looking up if we have
       // found a blockquote element to act on
       if (actionID == EditAction::outdent &&
@@ -6282,25 +6279,25 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
       // Don't walk past the editable section. Note that we need to check
       // before walking up to a parent because we need to return the parent
       // object, so the parent itself might not be in the editable area, but
       // it's OK if we're not performing a block-level action.
       bool blockLevelAction = actionID == EditAction::indent ||
                               actionID == EditAction::outdent ||
                               actionID == EditAction::align ||
                               actionID == EditAction::makeBasicBlock;
-      if (!htmlEditor->IsDescendantOfEditorRoot(
-                         point.GetContainer()->GetParentNode()) &&
+      if (!HTMLEditorRef().IsDescendantOfEditorRoot(
+                             point.GetContainer()->GetParentNode()) &&
           (blockLevelAction ||
-           !htmlEditor->IsDescendantOfEditorRoot(point.GetContainer()))) {
+           !HTMLEditorRef().IsDescendantOfEditorRoot(point.GetContainer()))) {
         break;
       }
 
       point.Set(point.GetContainer());
-      nearNode = htmlEditor->GetPreviousEditableHTMLNodeInBlock(point);
+      nearNode = HTMLEditorRef().GetPreviousEditableHTMLNodeInBlock(point);
     }
     return point;
   }
 
   // aWhere == kEnd
   // some special casing for text nodes
   if (point.IsInTextNode()) {
     if (!point.GetContainer()->GetParentNode()) {
@@ -6324,24 +6321,24 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
   //     inline elements even if it's non-editable.  For example, following
   //     examples with insertParagraph causes different result:
   //     * <div contenteditable>foo[]<b contenteditable="false">bar</b></div>
   //     * <div contenteditable>foo[]<b>bar</b></div>
   //     * <div contenteditable>foo[]<b contenteditable="false">bar</b>baz</div>
   //     Only in the first case, after the caret position isn't wrapped with
   //     new <div> element.
   nsCOMPtr<nsIContent> nextNode =
-    htmlEditor->GetNextEditableHTMLNodeInBlock(point);
+    HTMLEditorRef().GetNextEditableHTMLNodeInBlock(point);
 
   while (nextNode && !IsBlockNode(*nextNode) && nextNode->GetParentNode()) {
     point.Set(nextNode);
     if (NS_WARN_IF(!point.AdvanceOffset())) {
       break;
     }
-    if (htmlEditor->IsVisibleBRElement(nextNode)) {
+    if (HTMLEditorRef().IsVisibleBRElement(nextNode)) {
       break;
     }
 
     // Check for newlines in pre-formatted text nodes.
     if (EditorBase::IsPreformatted(nextNode) &&
         EditorBase::IsTextNode(nextNode)) {
       nsAutoString tempString;
       nextNode->GetAsText()->GetData(tempString);
@@ -6349,41 +6346,41 @@ HTMLEditRules::GetPromotedPoint(RulesEnd
       if (newlinePos >= 0) {
         if (static_cast<uint32_t>(newlinePos) + 1 == tempString.Length()) {
           // No need for special processing if the newline is at the end.
           break;
         }
         return EditorDOMPoint(nextNode, newlinePos + 1);
       }
     }
-    nextNode = htmlEditor->GetNextEditableHTMLNodeInBlock(point);
+    nextNode = HTMLEditorRef().GetNextEditableHTMLNodeInBlock(point);
   }
 
   // finding the real end for this point.  look up the tree for as long as we
   // are the last node in the container, and as long as we haven't hit the body
   // node.
   nsCOMPtr<nsIContent> nearNode =
-    htmlEditor->GetNextEditableHTMLNodeInBlock(point);
+    HTMLEditorRef().GetNextEditableHTMLNodeInBlock(point);
   while (!nearNode &&
          !point.IsContainerHTMLElement(nsGkAtoms::body) &&
          point.GetContainer()->GetParentNode()) {
     // Don't walk past the editable section. Note that we need to check before
     // walking up to a parent because we need to return the parent object, so
     // the parent itself might not be in the editable area, but it's OK.
-    if (!htmlEditor->IsDescendantOfEditorRoot(point.GetContainer()) &&
-        !htmlEditor->IsDescendantOfEditorRoot(
-                       point.GetContainer()->GetParentNode())) {
+    if (!HTMLEditorRef().IsDescendantOfEditorRoot(point.GetContainer()) &&
+        !HTMLEditorRef().IsDescendantOfEditorRoot(
+                           point.GetContainer()->GetParentNode())) {
       break;
     }
 
     point.Set(point.GetContainer());
     if (NS_WARN_IF(!point.AdvanceOffset())) {
       break;
     }
-    nearNode = htmlEditor->GetNextEditableHTMLNodeInBlock(point);
+    nearNode = HTMLEditorRef().GetNextEditableHTMLNodeInBlock(point);
   }
   return point;
 }
 
 /**
  * GetPromotedRanges() runs all the selection range endpoint through
  * GetPromotedPoint().
  */
@@ -6414,41 +6411,42 @@ HTMLEditRules::GetPromotedRanges(Selecti
 /**
  * PromoteRange() expands a range to include any parents for which all editable
  * children are already in range.
  */
 void
 HTMLEditRules::PromoteRange(nsRange& aRange,
                             EditAction aOperationType)
 {
-  NS_ENSURE_TRUE(mHTMLEditor, );
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   if (!aRange.IsPositioned()) {
     return;
   }
 
   nsCOMPtr<nsINode> startNode = aRange.GetStartContainer();
   nsCOMPtr<nsINode> endNode = aRange.GetEndContainer();
   int32_t startOffset = aRange.StartOffset();
   int32_t endOffset = aRange.EndOffset();
 
   // MOOSE major hack:
   // GetPromotedPoint doesn't really do the right thing for collapsed ranges
   // inside block elements that contain nothing but a solo <br>.  It's easier
   // to put a workaround here than to revamp GetPromotedPoint.  :-(
   if (startNode == endNode && startOffset == endOffset) {
-    nsCOMPtr<Element> block = htmlEditor->GetBlock(*startNode);
+    RefPtr<Element> block = HTMLEditorRef().GetBlock(*startNode);
     if (block) {
       bool bIsEmptyNode = false;
-      nsCOMPtr<nsIContent> root = htmlEditor->GetActiveEditingHost();
+      nsIContent* host = HTMLEditorRef().GetActiveEditingHost();
+      if (NS_WARN_IF(!host)) {
+        return;
+      }
       // Make sure we don't go higher than our root element in the content tree
-      NS_ENSURE_TRUE(root, );
-      if (!nsContentUtils::ContentIsDescendantOf(root, block)) {
-        htmlEditor->IsEmptyNode(block, &bIsEmptyNode, true, false);
+      if (!nsContentUtils::ContentIsDescendantOf(host, block)) {
+        HTMLEditorRef().IsEmptyNode(block, &bIsEmptyNode, true, false);
       }
       if (bIsEmptyNode) {
         startNode = block;
         endNode = block;
         startOffset = 0;
         endOffset = block->Length();
       }
     }
@@ -6471,26 +6469,26 @@ HTMLEditRules::PromoteRange(nsRange& aRa
   // truly enclose the blocks that we will affect.
 
   // Make sure that the new range ends up to be in the editable section.
   // XXX Looks like that this check wastes the time.  Perhaps, we should
   //     implement a method which checks both two DOM points in the editor
   //     root.
   EditorDOMPoint startPoint =
     GetPromotedPoint(kStart, *startNode, startOffset, aOperationType);
-  if (!htmlEditor->IsDescendantOfEditorRoot(
-         EditorBase::GetNodeAtRangeOffsetPoint(startPoint))) {
+  if (!HTMLEditorRef().IsDescendantOfEditorRoot(
+                         EditorBase::GetNodeAtRangeOffsetPoint(startPoint))) {
     return;
   }
   EditorDOMPoint endPoint =
     GetPromotedPoint(kEnd, *endNode, endOffset, aOperationType);
   EditorRawDOMPoint lastRawPoint(endPoint);
   lastRawPoint.RewindOffset();
-  if (!htmlEditor->IsDescendantOfEditorRoot(
-         EditorBase::GetNodeAtRangeOffsetPoint(lastRawPoint))) {
+  if (!HTMLEditorRef().IsDescendantOfEditorRoot(
+                         EditorBase::GetNodeAtRangeOffsetPoint(lastRawPoint))) {
     return;
   }
 
   DebugOnly<nsresult> rv = aRange.SetStartAndEnd(startPoint, endPoint);
   MOZ_ASSERT(NS_SUCCEEDED(rv));
 }
 
 class UniqueFunctor final : public BoolDomIterFunctor
@@ -6520,34 +6518,33 @@ private:
  */
 nsresult
 HTMLEditRules::GetNodesForOperation(
                  nsTArray<RefPtr<nsRange>>& aArrayOfRanges,
                  nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
                  EditAction aOperationType,
                  TouchContent aTouchContent)
 {
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   if (aTouchContent == TouchContent::yes) {
     // Split text nodes. This is necessary, since GetPromotedPoint() may return a
     // range ending in a text node in case where part of a pre-formatted
     // elements needs to be moved.
     for (RefPtr<nsRange>& range : aArrayOfRanges) {
       EditorDOMPoint atEnd(range->EndRef());
       if (NS_WARN_IF(!atEnd.IsSet()) || !atEnd.IsInTextNode()) {
         continue;
       }
 
       if (!atEnd.IsStartOfContainer() && !atEnd.IsEndOfContainer()) {
         // Split the text node.
         ErrorResult error;
         nsCOMPtr<nsIContent> newLeftNode =
-          htmlEditor->SplitNodeWithTransaction(atEnd, error);
+          HTMLEditorRef().SplitNodeWithTransaction(atEnd, error);
         if (NS_WARN_IF(error.Failed())) {
           return error.StealNSResult();
         }
 
         // Correct the range.
         // The new end parent becomes the parent node of the text.
         // XXX We want nsRange::SetEnd(const RawRangeBoundary&)
         EditorRawDOMPoint atContainerOfSplitNode(atEnd.GetContainer());
@@ -6565,42 +6562,42 @@ HTMLEditRules::GetNodesForOperation(
   if (aTouchContent == TouchContent::yes) {
     nsTArray<OwningNonNull<RangeItem>> rangeItemArray;
     rangeItemArray.AppendElements(aArrayOfRanges.Length());
 
     // First register ranges for special editor gravity
     for (auto& rangeItem : rangeItemArray) {
       rangeItem = new RangeItem();
       rangeItem->StoreRange(aArrayOfRanges[0]);
-      htmlEditor->mRangeUpdater.RegisterRangeItem(rangeItem);
+      HTMLEditorRef().mRangeUpdater.RegisterRangeItem(rangeItem);
       aArrayOfRanges.RemoveElementAt(0);
     }
     // Now bust up inlines.
-    nsresult rv = NS_OK;
     for (auto& item : Reversed(rangeItemArray)) {
-      rv = BustUpInlinesAtRangeEndpoints(*item);
+      nsresult rv = BustUpInlinesAtRangeEndpoints(*item);
       if (NS_FAILED(rv)) {
         break;
       }
     }
     // Then unregister the ranges
     for (auto& item : rangeItemArray) {
-      htmlEditor->mRangeUpdater.DropRangeItem(item);
+      HTMLEditorRef().mRangeUpdater.DropRangeItem(item);
       RefPtr<nsRange> range = item->GetRange();
       if (range) {
         aArrayOfRanges.AppendElement(range);
       }
     }
-    NS_ENSURE_SUCCESS(rv, rv);
   }
   // Gather up a list of all the nodes
   for (auto& range : aArrayOfRanges) {
     DOMSubtreeIterator iter;
     nsresult rv = iter.Init(*range);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
     if (aOutArrayOfNodes.IsEmpty()) {
       iter.AppendList(TrivialFunctor(), aOutArrayOfNodes);
     } else {
       // We don't want duplicates in aOutArrayOfNodes, so we use an
       // iterator/functor that only return nodes that are not already in
       // aOutArrayOfNodes.
       nsTArray<OwningNonNull<nsINode>> nodes;
       iter.AppendList(UniqueFunctor(aOutArrayOfNodes), nodes);
@@ -6618,17 +6615,17 @@ HTMLEditRules::GetNodesForOperation(
         aOutArrayOfNodes.RemoveElementAt(i);
         GetInnerContent(*node, aOutArrayOfNodes, &j);
       }
     }
     // Empty text node shouldn't be selected if unnecessary
     for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
       if (Text* text = aOutArrayOfNodes[i]->GetAsText()) {
         // Don't select empty text except to empty block
-        if (!htmlEditor->IsVisibleTextNode(*text)) {
+        if (!HTMLEditorRef().IsVisibleTextNode(*text)) {
           aOutArrayOfNodes.RemoveElementAt(i);
         }
       }
     }
   }
   // Indent/outdent already do something special for list items, but we still
   // need to make sure we don't act on table elements
   else if (aOperationType == EditAction::outdent ||
@@ -6640,17 +6637,17 @@ HTMLEditRules::GetNodesForOperation(
         int32_t j = i;
         aOutArrayOfNodes.RemoveElementAt(i);
         GetInnerContent(*node, aOutArrayOfNodes, &j);
       }
     }
   }
   // Outdent should look inside of divs.
   if (aOperationType == EditAction::outdent &&
-      !htmlEditor->IsCSSEnabled()) {
+      !HTMLEditorRef().IsCSSEnabled()) {
     for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
       OwningNonNull<nsINode> node = aOutArrayOfNodes[i];
       if (node->IsHTMLElement(nsGkAtoms::div)) {
         int32_t j = i;
         aOutArrayOfNodes.RemoveElementAt(i);
         GetInnerContent(*node, aOutArrayOfNodes, &j, Lists::no, Tables::no);
       }
     }
@@ -6663,20 +6660,22 @@ HTMLEditRules::GetNodesForOperation(
       aOperationType == EditAction::makeList ||
       aOperationType == EditAction::align ||
       aOperationType == EditAction::setAbsolutePosition ||
       aOperationType == EditAction::indent ||
       aOperationType == EditAction::outdent) {
     for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
       OwningNonNull<nsINode> node = aOutArrayOfNodes[i];
       if (aTouchContent == TouchContent::yes && IsInlineNode(node) &&
-          htmlEditor->IsContainer(node) && !EditorBase::IsTextNode(node)) {
+          HTMLEditorRef().IsContainer(node) && !EditorBase::IsTextNode(node)) {
         nsTArray<OwningNonNull<nsINode>> arrayOfInlines;
         nsresult rv = BustUpInlinesAtBRs(*node->AsContent(), arrayOfInlines);
-        NS_ENSURE_SUCCESS(rv, rv);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
 
         // Put these nodes in aOutArrayOfNodes, replacing the current node
         aOutArrayOfNodes.RemoveElementAt(i);
         aOutArrayOfNodes.InsertElementsAt(i, arrayOfInlines);
       }
     }
   }
   return NS_OK;
@@ -6694,20 +6693,19 @@ HTMLEditRules::GetChildNodesForOperation
 }
 
 nsresult
 HTMLEditRules::GetListActionNodes(
                  nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes,
                  EntireList aEntireList,
                  TouchContent aTouchContent)
 {
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
-  RefPtr<Selection> selection = htmlEditor->GetSelection();
+  MOZ_ASSERT(IsEditorDataAvailable());
+
+  RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
   NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
 
   // Added this in so that ui code can ask to change an entire list, even if
   // selection is only in part of it.  used by list item dialog.
   if (aEntireList == EntireList::yes) {
     uint32_t rangeCount = selection->RangeCount();
     for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
       RefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
@@ -6723,30 +6721,30 @@ HTMLEditRules::GetListActionNodes(
     // the selection spans multiple lists but with no common list parent.
     if (!aOutArrayOfNodes.IsEmpty()) {
       return NS_OK;
     }
   }
 
   {
     // We don't like other people messing with our selection!
-    AutoTransactionsConserveSelection dontChangeMySelection(htmlEditor);
+    AutoTransactionsConserveSelection dontChangeMySelection(&HTMLEditorRef());
 
     // contruct a list of nodes to act on.
     nsresult rv = GetNodesFromSelection(*selection, EditAction::makeList,
                                         aOutArrayOfNodes, aTouchContent);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Pre-process our list of nodes
   for (int32_t i = aOutArrayOfNodes.Length() - 1; i >= 0; i--) {
     OwningNonNull<nsINode> testNode = aOutArrayOfNodes[i];
 
     // Remove all non-editable nodes.  Leave them be.
-    if (!htmlEditor->IsEditable(testNode)) {
+    if (!HTMLEditorRef().IsEditable(testNode)) {
       aOutArrayOfNodes.RemoveElementAt(i);
       continue;
     }
 
     // Scan for table elements and divs.  If we find table elements other than
     // table, replace it with a list of any editable non-table content.
     if (HTMLEditUtils::IsTableElementButNotTable(testNode)) {
       int32_t j = i;
@@ -6761,32 +6759,31 @@ HTMLEditRules::GetListActionNodes(
 
   return NS_OK;
 }
 
 void
 HTMLEditRules::LookInsideDivBQandList(
                  nsTArray<OwningNonNull<nsINode>>& aNodeArray)
 {
-  NS_ENSURE_TRUE(mHTMLEditor, );
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   // If there is only one node in the array, and it is a list, div, or
   // blockquote, then look inside of it until we find inner list or content.
   if (aNodeArray.Length() != 1) {
     return;
   }
 
   OwningNonNull<nsINode> curNode = aNodeArray[0];
 
   while (curNode->IsHTMLElement(nsGkAtoms::div) ||
          HTMLEditUtils::IsList(curNode) ||
          curNode->IsHTMLElement(nsGkAtoms::blockquote)) {
     // Dive as long as there's only one child, and it's a list, div, blockquote
-    uint32_t numChildren = htmlEditor->CountEditableChildren(curNode);
+    uint32_t numChildren = HTMLEditorRef().CountEditableChildren(curNode);
     if (numChildren != 1) {
       break;
     }
 
     // Keep diving!  XXX One would expect to dive into the one editable node.
     nsCOMPtr<nsIContent> child = curNode->GetFirstChild();
     if (!child->IsHTMLElement(nsGkAtoms::div) &&
         !HTMLEditUtils::IsList(child) &&
@@ -6833,33 +6830,32 @@ HTMLEditRules::GetDefinitionListItemType
   }
 }
 
 nsresult
 HTMLEditRules::GetParagraphFormatNodes(
                  nsTArray<OwningNonNull<nsINode>>& outArrayOfNodes,
                  TouchContent aTouchContent)
 {
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
-  RefPtr<Selection> selection = htmlEditor->GetSelection();
+  MOZ_ASSERT(IsEditorDataAvailable());
+
+  RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
   NS_ENSURE_STATE(selection);
 
   // Contruct a list of nodes to act on.
   nsresult rv = GetNodesFromSelection(*selection, EditAction::makeBasicBlock,
                                       outArrayOfNodes, aTouchContent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Pre-process our list of nodes
   for (int32_t i = outArrayOfNodes.Length() - 1; i >= 0; i--) {
     OwningNonNull<nsINode> testNode = outArrayOfNodes[i];
 
     // Remove all non-editable nodes.  Leave them be.
-    if (!htmlEditor->IsEditable(testNode)) {
+    if (!HTMLEditorRef().IsEditable(testNode)) {
       outArrayOfNodes.RemoveElementAt(i);
       continue;
     }
 
     // Scan for table elements.  If we find table elements other than table,
     // replace it with a list of any editable non-table content.  Ditto for
     // list elements.
     if (HTMLEditUtils::IsTableElement(testNode) ||
@@ -6871,82 +6867,66 @@ HTMLEditRules::GetParagraphFormatNodes(
     }
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::BustUpInlinesAtRangeEndpoints(RangeItem& item)
 {
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   bool isCollapsed = item.mStartContainer == item.mEndContainer &&
                      item.mStartOffset == item.mEndOffset;
 
   nsCOMPtr<nsIContent> endInline = GetHighestInlineParent(*item.mEndContainer);
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_FAILURE;
-  }
 
   // XXX Oh, then, if the range is collapsed, we don't need to call
   //     GetHighestInlineParent(), isn't it?
   if (endInline && !isCollapsed) {
-    RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
     SplitNodeResult splitEndInlineResult =
-      htmlEditor->SplitNodeDeepWithTransaction(
-                    *endInline,
-                    EditorRawDOMPoint(item.mEndContainer, item.mEndOffset),
-                    SplitAtEdges::eDoNotCreateEmptyContainer);
+      HTMLEditorRef().SplitNodeDeepWithTransaction(
+                        *endInline,
+                        EditorRawDOMPoint(item.mEndContainer, item.mEndOffset),
+                        SplitAtEdges::eDoNotCreateEmptyContainer);
     if (NS_WARN_IF(splitEndInlineResult.Failed())) {
       return splitEndInlineResult.Rv();
     }
-    if (NS_WARN_IF(!mHTMLEditor)) {
-      return NS_ERROR_FAILURE;
-    }
     EditorRawDOMPoint splitPointAtEnd(splitEndInlineResult.SplitPoint());
     item.mEndContainer = splitPointAtEnd.GetContainer();
     item.mEndOffset = splitPointAtEnd.Offset();
   }
 
   nsCOMPtr<nsIContent> startInline =
     GetHighestInlineParent(*item.mStartContainer);
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_FAILURE;
-  }
 
   if (startInline) {
-    RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
     SplitNodeResult splitStartInlineResult =
-      htmlEditor->SplitNodeDeepWithTransaction(
-                    *startInline,
-                    EditorRawDOMPoint(item.mStartContainer, item.mStartOffset),
-                    SplitAtEdges::eDoNotCreateEmptyContainer);
+      HTMLEditorRef().SplitNodeDeepWithTransaction(
+                        *startInline,
+                        EditorRawDOMPoint(item.mStartContainer,
+                                          item.mStartOffset),
+                        SplitAtEdges::eDoNotCreateEmptyContainer);
     if (NS_WARN_IF(splitStartInlineResult.Failed())) {
       return splitStartInlineResult.Rv();
     }
-    if (NS_WARN_IF(!mHTMLEditor)) {
-      return NS_ERROR_FAILURE;
-    }
     EditorRawDOMPoint splitPointAtStart(splitStartInlineResult.SplitPoint());
     item.mStartContainer = splitPointAtStart.GetContainer();
     item.mStartOffset = splitPointAtStart.Offset();
   }
 
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::BustUpInlinesAtBRs(
                  nsIContent& aNode,
                  nsTArray<OwningNonNull<nsINode>>& aOutArrayOfNodes)
 {
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   // First build up a list of all the break nodes inside the inline container.
   nsTArray<OwningNonNull<nsINode>> arrayOfBreaks;
   BRNodeFunctor functor;
   DOMIterator iter(aNode);
   iter.AppendList(functor, arrayOfBreaks);
 
   // If there aren't any breaks, just put inNode itself in the array
@@ -6958,35 +6938,35 @@ HTMLEditRules::BustUpInlinesAtBRs(
   // Else we need to bust up aNode along all the breaks
   nsCOMPtr<nsIContent> nextNode = &aNode;
   for (OwningNonNull<nsINode>& brNode : arrayOfBreaks) {
     EditorRawDOMPoint atBrNode(brNode);
     if (NS_WARN_IF(!atBrNode.IsSet())) {
       return NS_ERROR_FAILURE;
     }
     SplitNodeResult splitNodeResult =
-      htmlEditor->SplitNodeDeepWithTransaction(
-                    *nextNode, atBrNode,
-                    SplitAtEdges::eAllowToCreateEmptyContainer);
+      HTMLEditorRef().SplitNodeDeepWithTransaction(
+                        *nextNode, atBrNode,
+                        SplitAtEdges::eAllowToCreateEmptyContainer);
     if (NS_WARN_IF(splitNodeResult.Failed())) {
       return splitNodeResult.Rv();
     }
 
     // Put previous node at the split point.
     if (splitNodeResult.GetPreviousNode()) {
       // Might not be a left node.  A break might have been at the very
       // beginning of inline container, in which case
       // SplitNodeDeepWithTransaction() would not actually split anything.
       aOutArrayOfNodes.AppendElement(*splitNodeResult.GetPreviousNode());
     }
 
     // Move break outside of container and also put in node list
     EditorRawDOMPoint atNextNode(splitNodeResult.GetNextNode());
     nsresult rv =
-      htmlEditor->MoveNodeWithTransaction(*brNode->AsContent(), atNextNode);
+      HTMLEditorRef().MoveNodeWithTransaction(*brNode->AsContent(), atNextNode);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     aOutArrayOfNodes.AppendElement(*brNode);
 
     nextNode = splitNodeResult.GetNextNode();
   }
 
@@ -6994,25 +6974,23 @@ HTMLEditRules::BustUpInlinesAtBRs(
   aOutArrayOfNodes.AppendElement(*nextNode);
 
   return NS_OK;
 }
 
 nsIContent*
 HTMLEditRules::GetHighestInlineParent(nsINode& aNode)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (!aNode.IsContent() || IsBlockNode(aNode)) {
     return nullptr;
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return nullptr;
-  }
-
-  Element* host = mHTMLEditor->GetActiveEditingHost();
+  Element* host = HTMLEditorRef().GetActiveEditingHost();
   if (NS_WARN_IF(!host)) {
     return nullptr;
   }
 
   // If aNode is the editing host itself, there is no modifiable inline parent.
   if (&aNode == host) {
     return nullptr;
   }
@@ -7125,126 +7103,129 @@ HTMLEditRules::MakeTransitionList(nsTArr
 /**
  * If aNode is the descendant of a listitem, return that li.  But table element
  * boundaries are stoppers on the search.  Also stops on the active editor host
  * (contenteditable).  Also test if aNode is an li itself.
  */
 Element*
 HTMLEditRules::IsInListItem(nsINode* aNode)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   NS_ENSURE_TRUE(aNode, nullptr);
   if (HTMLEditUtils::IsListItem(aNode)) {
     return aNode->AsElement();
   }
 
   Element* parent = aNode->GetParentElement();
   while (parent &&
-         mHTMLEditor && mHTMLEditor->IsDescendantOfEditorRoot(parent) &&
+         HTMLEditorRef().IsDescendantOfEditorRoot(parent) &&
          !HTMLEditUtils::IsTableElement(parent)) {
     if (HTMLEditUtils::IsListItem(parent)) {
       return parent;
     }
     parent = parent->GetParentElement();
   }
   return nullptr;
 }
 
 nsAtom&
 HTMLEditRules::DefaultParagraphSeparator()
 {
-  MOZ_ASSERT(mHTMLEditor);
-  if (!mHTMLEditor) {
-    return *nsGkAtoms::div;
-  }
-  return ParagraphSeparatorElement(mHTMLEditor->GetDefaultParagraphSeparator());
+  MOZ_ASSERT(IsEditorDataAvailable());
+  return ParagraphSeparatorElement(
+           HTMLEditorRef().GetDefaultParagraphSeparator());
 }
 
 /**
  * ReturnInHeader: do the right thing for returns pressed in headers
  */
 nsresult
 HTMLEditRules::ReturnInHeader(Selection& aSelection,
                               Element& aHeader,
                               nsINode& aNode,
                               int32_t aOffset)
 {
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   // Remember where the header is
   nsCOMPtr<nsINode> headerParent = aHeader.GetParentNode();
   int32_t offset = headerParent ? headerParent->ComputeIndexOf(&aHeader) : -1;
 
   // Get ws code to adjust any ws
   nsCOMPtr<nsINode> node = &aNode;
-  nsresult rv = WSRunObject::PrepareToSplitAcrossBlocks(htmlEditor,
+  nsresult rv = WSRunObject::PrepareToSplitAcrossBlocks(&HTMLEditorRef(),
                                                         address_of(node),
                                                         &aOffset);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
   if (NS_WARN_IF(!node->IsContent())) {
     return NS_ERROR_FAILURE;
   }
 
   // Split the header
   ErrorResult error;
   SplitNodeResult splitHeaderResult =
-    htmlEditor->SplitNodeDeepWithTransaction(
-                  aHeader, EditorRawDOMPoint(node, aOffset),
-                  SplitAtEdges::eAllowToCreateEmptyContainer);
+    HTMLEditorRef().SplitNodeDeepWithTransaction(
+                      aHeader, EditorRawDOMPoint(node, aOffset),
+                      SplitAtEdges::eAllowToCreateEmptyContainer);
   NS_WARNING_ASSERTION(splitHeaderResult.Succeeded(),
     "Failed to split aHeader");
 
   // If the previous heading of split point is empty, put a mozbr into it.
-  nsCOMPtr<nsIContent> prevItem = htmlEditor->GetPriorHTMLSibling(&aHeader);
+  nsCOMPtr<nsIContent> prevItem = HTMLEditorRef().GetPriorHTMLSibling(&aHeader);
   if (prevItem) {
     MOZ_DIAGNOSTIC_ASSERT(
       HTMLEditUtils::IsHeader(*prevItem));
     bool isEmptyNode;
-    rv = htmlEditor->IsEmptyNode(prevItem, &isEmptyNode);
-    NS_ENSURE_SUCCESS(rv, rv);
+    rv = HTMLEditorRef().IsEmptyNode(prevItem, &isEmptyNode);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
     if (isEmptyNode) {
       RefPtr<Element> brElement = CreateMozBR(EditorRawDOMPoint(prevItem, 0));
       if (NS_WARN_IF(!brElement)) {
         return NS_ERROR_FAILURE;
       }
     }
   }
 
   // If the new (righthand) header node is empty, delete it
   if (IsEmptyBlockElement(aHeader, IgnoreSingleBR::eYes)) {
-    rv = htmlEditor->DeleteNodeWithTransaction(aHeader);
+    rv = HTMLEditorRef().DeleteNodeWithTransaction(aHeader);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     // Layout tells the caret to blink in a weird place if we don't place a
     // break after the header.
     nsCOMPtr<nsIContent> sibling;
     if (aHeader.GetNextSibling()) {
-      sibling = htmlEditor->GetNextHTMLSibling(aHeader.GetNextSibling());
+      sibling = HTMLEditorRef().GetNextHTMLSibling(aHeader.GetNextSibling());
     }
     if (!sibling || !sibling->IsHTMLElement(nsGkAtoms::br)) {
       ClearCachedStyles();
-      htmlEditor->mTypeInState->ClearAllProps();
+      HTMLEditorRef().mTypeInState->ClearAllProps();
 
       // Create a paragraph
       nsAtom& paraAtom = DefaultParagraphSeparator();
       // We want a wrapper element even if we separate with <br>
       EditorRawDOMPoint nextToHeader(headerParent, offset + 1);
       RefPtr<Element> pNode =
-        htmlEditor->CreateNodeWithTransaction(&paraAtom == nsGkAtoms::br ?
-                                                *nsGkAtoms::p : paraAtom,
-                                              nextToHeader);
+        HTMLEditorRef().CreateNodeWithTransaction(&paraAtom == nsGkAtoms::br ?
+                                                    *nsGkAtoms::p : paraAtom,
+                                                  nextToHeader);
       if (NS_WARN_IF(!pNode)) {
         return NS_ERROR_FAILURE;
       }
 
       // Append a <br> to it
       RefPtr<Element> brElement =
-        htmlEditor->InsertBrElementWithTransaction(aSelection,
-                                                   EditorRawDOMPoint(pNode, 0));
+        HTMLEditorRef().InsertBrElementWithTransaction(
+                          aSelection, EditorRawDOMPoint(pNode, 0));
       if (NS_WARN_IF(!brElement)) {
         return NS_ERROR_FAILURE;
       }
 
       // Set selection to before the break
       ErrorResult error;
       aSelection.Collapse(EditorRawDOMPoint(pNode, 0), error);
       if (NS_WARN_IF(error.Failed())) {
@@ -7266,21 +7247,17 @@ HTMLEditRules::ReturnInHeader(Selection&
   }
   return NS_OK;
 }
 
 EditActionResult
 HTMLEditRules::ReturnInParagraph(Selection& aSelection,
                                  Element& aParentDivOrP)
 {
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return EditActionResult(NS_ERROR_NOT_AVAILABLE);
-  }
-
-  RefPtr<HTMLEditor> htmlEditor = mHTMLEditor;
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   nsRange* firstRange = aSelection.GetRangeAt(0);
   if (NS_WARN_IF(!firstRange)) {
     return EditActionResult(NS_ERROR_FAILURE);
   }
 
   EditorDOMPoint atStartOfSelection(firstRange->StartRef());
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
@@ -7348,59 +7325,61 @@ HTMLEditRules::ReturnInParagraph(Selecti
         if (!nextSibling->IsHTMLElement(nsGkAtoms::br)) {
           break;
         }
         foundBRElement = true;
       }
     }
   }
 
-  bool doesCRCreateNewP = htmlEditor->GetReturnInParagraphCreatesNewParagraph();
+  bool doesCRCreateNewP =
+    HTMLEditorRef().GetReturnInParagraphCreatesNewParagraph();
 
   bool splitAfterNewBR = false;
   nsCOMPtr<nsIContent> brContent;
 
   EditorDOMPoint pointToSplitParentDivOrP(atStartOfSelection);
 
   EditorRawDOMPoint pointToInsertBR;
   if (doesCRCreateNewP &&
       atStartOfSelection.GetContainer() == &aParentDivOrP) {
     // We are at the edges of the block, so, we don't need to create new <br>.
     brContent = nullptr;
   } else if (atStartOfSelection.IsInTextNode()) {
     // at beginning of text node?
     if (atStartOfSelection.IsStartOfContainer()) {
       // is there a BR prior to it?
       brContent =
-        htmlEditor->GetPriorHTMLSibling(atStartOfSelection.GetContainer());
+        HTMLEditorRef().GetPriorHTMLSibling(atStartOfSelection.GetContainer());
       if (!brContent ||
-          !htmlEditor->IsVisibleBRElement(brContent) ||
+          !HTMLEditorRef().IsVisibleBRElement(brContent) ||
           TextEditUtils::HasMozAttr(brContent)) {
         pointToInsertBR.Set(atStartOfSelection.GetContainer());
         brContent = nullptr;
       }
     } else if (atStartOfSelection.IsEndOfContainer()) {
       // we're at the end of text node...
       // is there a BR after to it?
       brContent =
-        htmlEditor->GetNextHTMLSibling(atStartOfSelection.GetContainer());
+        HTMLEditorRef().GetNextHTMLSibling(atStartOfSelection.GetContainer());
       if (!brContent ||
-          !htmlEditor->IsVisibleBRElement(brContent) ||
+          !HTMLEditorRef().IsVisibleBRElement(brContent) ||
           TextEditUtils::HasMozAttr(brContent)) {
         pointToInsertBR.Set(atStartOfSelection.GetContainer());
         DebugOnly<bool> advanced = pointToInsertBR.AdvanceOffset();
         NS_WARNING_ASSERTION(advanced,
           "Failed to advance offset to after the container of selection start");
         brContent = nullptr;
       }
     } else {
       if (doesCRCreateNewP) {
         ErrorResult error;
         nsCOMPtr<nsIContent> newLeftDivOrP =
-          htmlEditor->SplitNodeWithTransaction(pointToSplitParentDivOrP, error);
+          HTMLEditorRef().SplitNodeWithTransaction(pointToSplitParentDivOrP,
+                                                   error);
         if (NS_WARN_IF(error.Failed())) {
           return EditActionResult(error.StealNSResult());
         }
         pointToSplitParentDivOrP.SetToEndOf(newLeftDivOrP);
       }
 
       // We need to put new <br> after the left node if given node was split
       // above.
@@ -7408,46 +7387,45 @@ HTMLEditRules::ReturnInParagraph(Selecti
       DebugOnly<bool> advanced = pointToInsertBR.AdvanceOffset();
       NS_WARNING_ASSERTION(advanced,
         "Failed to advance offset to after the container of selection start");
     }
   } else {
     // not in a text node.
     // is there a BR prior to it?
     nsCOMPtr<nsIContent> nearNode;
-    nearNode =
-      htmlEditor->GetPreviousEditableHTMLNode(atStartOfSelection);
-    if (!nearNode || !htmlEditor->IsVisibleBRElement(nearNode) ||
+    nearNode = HTMLEditorRef().GetPreviousEditableHTMLNode(atStartOfSelection);
+    if (!nearNode || !HTMLEditorRef().IsVisibleBRElement(nearNode) ||
         TextEditUtils::HasMozAttr(nearNode)) {
       // is there a BR after it?
-      nearNode =
-        htmlEditor->GetNextEditableHTMLNode(atStartOfSelection);
-      if (!nearNode || !htmlEditor->IsVisibleBRElement(nearNode) ||
+      nearNode = HTMLEditorRef().GetNextEditableHTMLNode(atStartOfSelection);
+      if (!nearNode || !HTMLEditorRef().IsVisibleBRElement(nearNode) ||
           TextEditUtils::HasMozAttr(nearNode)) {
         pointToInsertBR = atStartOfSelection;
         splitAfterNewBR = true;
       }
     }
     if (!pointToInsertBR.IsSet() && TextEditUtils::IsBreak(nearNode)) {
       brContent = nearNode;
     }
   }
   if (pointToInsertBR.IsSet()) {
-    // Don't modify the DOM tree if mHTMLEditor disappeared.
-    if (NS_WARN_IF(!mHTMLEditor)) {
+    // Don't modify the DOM tree if HTMLEditor is destroyed.
+    if (NS_WARN_IF(HTMLEditorRef().Destroyed())) {
       return EditActionResult(NS_ERROR_NOT_AVAILABLE);
     }
 
     // if CR does not create a new P, default to BR creation
     if (NS_WARN_IF(!doesCRCreateNewP)) {
       return EditActionResult(NS_OK);
     }
 
     brContent =
-      htmlEditor->InsertBrElementWithTransaction(aSelection, pointToInsertBR);
+      HTMLEditorRef().InsertBrElementWithTransaction(aSelection,
+                                                     pointToInsertBR);
     NS_WARNING_ASSERTION(brContent, "Failed to create a <br> element");
     if (splitAfterNewBR) {
       // We split the parent after the br we've just inserted.
       pointToSplitParentDivOrP.Set(brContent);
       DebugOnly<bool> advanced = pointToSplitParentDivOrP.AdvanceOffset();
       NS_WARNING_ASSERTION(advanced,
         "Failed to advance offset after the new <br>");
     }
@@ -7465,76 +7443,76 @@ HTMLEditRules::ReturnInParagraph(Selecti
 template<typename PT, typename CT>
 nsresult
 HTMLEditRules::SplitParagraph(
                  Selection& aSelection,
                  Element& aParentDivOrP,
                  const EditorDOMPointBase<PT, CT>& aStartOfRightNode,
                  nsIContent* aNextBRNode)
 {
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  RefPtr<HTMLEditor> htmlEditor = mHTMLEditor;
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   // split para
   // get ws code to adjust any ws
   nsCOMPtr<nsINode> selNode = aStartOfRightNode.GetContainer();
   int32_t selOffset = aStartOfRightNode.Offset();
   nsresult rv =
-    WSRunObject::PrepareToSplitAcrossBlocks(htmlEditor,
+    WSRunObject::PrepareToSplitAcrossBlocks(&HTMLEditorRef(),
                                             address_of(selNode), &selOffset);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
   if (NS_WARN_IF(!selNode->IsContent())) {
     return NS_ERROR_FAILURE;
   }
 
   // Split the paragraph.
   SplitNodeResult splitDivOrPResult =
-    htmlEditor->SplitNodeDeepWithTransaction(
-                  aParentDivOrP,
-                  EditorRawDOMPoint(selNode, selOffset),
-                  SplitAtEdges::eAllowToCreateEmptyContainer);
+    HTMLEditorRef().SplitNodeDeepWithTransaction(
+                      aParentDivOrP,
+                      EditorRawDOMPoint(selNode, selOffset),
+                      SplitAtEdges::eAllowToCreateEmptyContainer);
   if (NS_WARN_IF(splitDivOrPResult.Failed())) {
     return splitDivOrPResult.Rv();
   }
   if (NS_WARN_IF(!splitDivOrPResult.DidSplit())) {
     return NS_ERROR_FAILURE;
   }
 
   // Get rid of the break, if it is visible (otherwise it may be needed to
   // prevent an empty p).
-  if (aNextBRNode && htmlEditor->IsVisibleBRElement(aNextBRNode)) {
-    rv = htmlEditor->DeleteNodeWithTransaction(*aNextBRNode);
+  if (aNextBRNode && HTMLEditorRef().IsVisibleBRElement(aNextBRNode)) {
+    rv = HTMLEditorRef().DeleteNodeWithTransaction(*aNextBRNode);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   // Remove ID attribute on the paragraph from the existing right node.
-  rv = htmlEditor->RemoveAttributeWithTransaction(aParentDivOrP,
-                                                  *nsGkAtoms::id);
-  NS_ENSURE_SUCCESS(rv, rv);
+  rv = HTMLEditorRef().RemoveAttributeWithTransaction(aParentDivOrP,
+                                                      *nsGkAtoms::id);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   // We need to ensure to both paragraphs visible even if they are empty.
   // However, moz-<br> element isn't useful in this case because moz-<br>
   // elements will be ignored by PlaintextSerializer.  Additionally,
   // moz-<br> will be exposed as <br> with Element.innerHTML.  Therefore,
   // we can use normal <br> elements for placeholder in this case.
   // Note that Chromium also behaves so.
   rv = InsertBRIfNeeded(*splitDivOrPResult.GetPreviousNode());
   NS_ENSURE_SUCCESS(rv, rv);
   rv = InsertBRIfNeeded(*splitDivOrPResult.GetNextNode());
   NS_ENSURE_SUCCESS(rv, rv);
 
   // selection to beginning of right hand para;
   // look inside any containers that are up front.
-  nsIContent* child = htmlEditor->GetLeftmostChild(&aParentDivOrP, true);
-  if (EditorBase::IsTextNode(child) || htmlEditor->IsContainer(child)) {
+  nsIContent* child = HTMLEditorRef().GetLeftmostChild(&aParentDivOrP, true);
+  if (EditorBase::IsTextNode(child) || HTMLEditorRef().IsContainer(child)) {
     EditorRawDOMPoint atStartOfChild(child, 0);
     ErrorResult error;
     aSelection.Collapse(atStartOfChild, error);
     if (NS_WARN_IF(error.Failed())) {
       error.SuppressException();
     }
   } else {
     EditorRawDOMPoint atChild(child);
@@ -7551,87 +7529,86 @@ HTMLEditRules::SplitParagraph(
  * ReturnInListItem: do the right thing for returns pressed in list items
  */
 nsresult
 HTMLEditRules::ReturnInListItem(Selection& aSelection,
                                 Element& aListItem,
                                 nsINode& aNode,
                                 int32_t aOffset)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(HTMLEditUtils::IsListItem(&aListItem));
 
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   // Get the item parent and the active editing host.
-  nsCOMPtr<Element> root = htmlEditor->GetActiveEditingHost();
+  RefPtr<Element> host = HTMLEditorRef().GetActiveEditingHost();
 
   // If we are in an empty item, then we want to pop up out of the list, but
   // only if prefs say it's okay and if the parent isn't the active editing
   // host.
   if (mReturnInEmptyLIKillsList &&
-      root != aListItem.GetParentElement() &&
+      host != aListItem.GetParentElement() &&
       IsEmptyBlockElement(aListItem, IgnoreSingleBR::eYes)) {
     nsCOMPtr<nsIContent> leftListNode = aListItem.GetParent();
     // Are we the last list item in the list?
-    if (!htmlEditor->IsLastEditableChild(&aListItem)) {
+    if (!HTMLEditorRef().IsLastEditableChild(&aListItem)) {
       // We need to split the list!
       EditorRawDOMPoint atListItem(&aListItem);
       ErrorResult error;
-      leftListNode = htmlEditor->SplitNodeWithTransaction(atListItem, error);
+      leftListNode =
+        HTMLEditorRef().SplitNodeWithTransaction(atListItem, error);
       if (NS_WARN_IF(error.Failed())) {
         return error.StealNSResult();
       }
     }
 
     // Are we in a sublist?
     EditorRawDOMPoint atNextSiblingOfLeftList(leftListNode);
     DebugOnly<bool> advanced = atNextSiblingOfLeftList.AdvanceOffset();
     NS_WARNING_ASSERTION(advanced,
       "Failed to advance offset after the right list node");
     if (HTMLEditUtils::IsList(atNextSiblingOfLeftList.GetContainer())) {
       // If so, move item out of this list and into the grandparent list
       nsresult rv =
-        htmlEditor->MoveNodeWithTransaction(aListItem,
-                                            atNextSiblingOfLeftList);
+        HTMLEditorRef().MoveNodeWithTransaction(aListItem,
+                                                atNextSiblingOfLeftList);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       ErrorResult error;
       aSelection.Collapse(RawRangeBoundary(&aListItem, 0), error);
       if (NS_WARN_IF(error.Failed())) {
         return error.StealNSResult();
       }
     } else {
       // Otherwise kill this item
-      nsresult rv = htmlEditor->DeleteNodeWithTransaction(aListItem);
+      nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(aListItem);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       // Time to insert a paragraph
       nsAtom& paraAtom = DefaultParagraphSeparator();
       // We want a wrapper even if we separate with <br>
       RefPtr<Element> pNode =
-        htmlEditor->CreateNodeWithTransaction(&paraAtom == nsGkAtoms::br ?
-                                                *nsGkAtoms::p : paraAtom,
-                                              atNextSiblingOfLeftList);
+        HTMLEditorRef().CreateNodeWithTransaction(&paraAtom == nsGkAtoms::br ?
+                                                    *nsGkAtoms::p : paraAtom,
+                                                  atNextSiblingOfLeftList);
       if (NS_WARN_IF(!pNode)) {
         return NS_ERROR_FAILURE;
       }
 
-      RefPtr<Selection> selection = htmlEditor->GetSelection();
+      RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
       if (NS_WARN_IF(!selection)) {
         return NS_ERROR_FAILURE;
       }
 
       // Append a <br> to it
       RefPtr<Element> brElement =
-        htmlEditor->InsertBrElementWithTransaction(*selection,
-                                                   EditorRawDOMPoint(pNode, 0));
+        HTMLEditorRef().InsertBrElementWithTransaction(
+                          *selection, EditorRawDOMPoint(pNode, 0));
       if (NS_WARN_IF(!brElement)) {
         return NS_ERROR_FAILURE;
       }
 
       // Set selection to before the break
       ErrorResult error;
       aSelection.Collapse(EditorRawDOMPoint(pNode, 0), error);
       if (NS_WARN_IF(error.Failed())) {
@@ -7640,97 +7617,105 @@ HTMLEditRules::ReturnInListItem(Selectio
     }
     return NS_OK;
   }
 
   // Else we want a new list item at the same list level.  Get ws code to
   // adjust any ws.
   nsCOMPtr<nsINode> selNode = &aNode;
   nsresult rv =
-    WSRunObject::PrepareToSplitAcrossBlocks(htmlEditor,
+    WSRunObject::PrepareToSplitAcrossBlocks(&HTMLEditorRef(),
                                             address_of(selNode), &aOffset);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
   if (NS_WARN_IF(!selNode->IsContent())) {
     return NS_ERROR_FAILURE;
   }
 
   // Now split the list item.
   SplitNodeResult splitListItemResult =
-    htmlEditor->SplitNodeDeepWithTransaction(
-                  aListItem, EditorRawDOMPoint(selNode, aOffset),
-                  SplitAtEdges::eAllowToCreateEmptyContainer);
+    HTMLEditorRef().SplitNodeDeepWithTransaction(
+                      aListItem, EditorRawDOMPoint(selNode, aOffset),
+                      SplitAtEdges::eAllowToCreateEmptyContainer);
   NS_WARNING_ASSERTION(splitListItemResult.Succeeded(),
     "Failed to split the list item");
 
   // Hack: until I can change the damaged doc range code back to being
   // extra-inclusive, I have to manually detect certain list items that may be
   // left empty.
-  nsCOMPtr<nsIContent> prevItem = htmlEditor->GetPriorHTMLSibling(&aListItem);
+  nsCOMPtr<nsIContent> prevItem =
+    HTMLEditorRef().GetPriorHTMLSibling(&aListItem);
   if (prevItem && HTMLEditUtils::IsListItem(prevItem)) {
     bool isEmptyNode;
-    rv = htmlEditor->IsEmptyNode(prevItem, &isEmptyNode);
-    NS_ENSURE_SUCCESS(rv, rv);
+    rv = HTMLEditorRef().IsEmptyNode(prevItem, &isEmptyNode);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
     if (isEmptyNode) {
       RefPtr<Element> brElement = CreateMozBR(EditorRawDOMPoint(prevItem, 0));
       if (NS_WARN_IF(!brElement)) {
         return NS_ERROR_FAILURE;
       }
     } else {
-      rv = htmlEditor->IsEmptyNode(&aListItem, &isEmptyNode, true);
-      NS_ENSURE_SUCCESS(rv, rv);
+      rv = HTMLEditorRef().IsEmptyNode(&aListItem, &isEmptyNode, true);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
       if (isEmptyNode) {
         RefPtr<nsAtom> nodeAtom = aListItem.NodeInfo()->NameAtom();
         if (nodeAtom == nsGkAtoms::dd || nodeAtom == nsGkAtoms::dt) {
           nsCOMPtr<nsINode> list = aListItem.GetParentNode();
           int32_t itemOffset = list ? list->ComputeIndexOf(&aListItem) : -1;
 
           nsAtom* listAtom = nodeAtom == nsGkAtoms::dt ? nsGkAtoms::dd
                                                         : nsGkAtoms::dt;
           MOZ_DIAGNOSTIC_ASSERT(itemOffset != -1);
           EditorRawDOMPoint atNextListItem(list, aListItem.GetNextSibling(),
                                            itemOffset + 1);
           RefPtr<Element> newListItem =
-            htmlEditor->CreateNodeWithTransaction(*listAtom, atNextListItem);
+            HTMLEditorRef().CreateNodeWithTransaction(*listAtom,
+                                                      atNextListItem);
           if (NS_WARN_IF(!newListItem)) {
             return NS_ERROR_FAILURE;
           }
-          rv = htmlEditor->DeleteNodeWithTransaction(aListItem);
+          rv = HTMLEditorRef().DeleteNodeWithTransaction(aListItem);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
           ErrorResult error;
           aSelection.Collapse(EditorRawDOMPoint(newListItem, 0), error);
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
           return NS_OK;
         }
 
         RefPtr<Element> brElement;
         nsresult rv =
-          htmlEditor->CopyLastEditableChildStylesWithTransaction(
-                        *prevItem->AsElement(), aListItem,
-                        address_of(brElement));
+          HTMLEditorRef().CopyLastEditableChildStylesWithTransaction(
+                            *prevItem->AsElement(), aListItem,
+                            address_of(brElement));
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return NS_ERROR_FAILURE;
         }
         if (brElement) {
           EditorRawDOMPoint atBrNode(brElement);
           if (NS_WARN_IF(!atBrNode.IsSetAndValid())) {
             return NS_ERROR_FAILURE;
           }
           ErrorResult error;
           aSelection.Collapse(atBrNode, error);
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
           return NS_OK;
         }
       } else {
-        WSRunObject wsObj(htmlEditor, &aListItem, 0);
+        WSRunObject wsObj(&HTMLEditorRef(), &aListItem, 0);
         nsCOMPtr<nsINode> visNode;
         int32_t visOffset = 0;
         WSType wsType;
         wsObj.NextVisibleNode(EditorRawDOMPoint(&aListItem, 0),
                               address_of(visNode), &visOffset, &wsType);
         if (wsType == WSType::special || wsType == WSType::br ||
             visNode->IsHTMLElement(nsGkAtoms::hr)) {
           EditorRawDOMPoint atVisNode(visNode);
@@ -7761,20 +7746,17 @@ HTMLEditRules::ReturnInListItem(Selectio
 }
 
 /**
  * MakeBlockquote() puts the list of nodes into one or more blockquotes.
  */
 nsresult
 HTMLEditRules::MakeBlockquote(nsTArray<OwningNonNull<nsINode>>& aNodeArray)
 {
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   // The idea here is to put the nodes into a minimal number of blockquotes.
   // When the user blockquotes something, they expect one blockquote.  That may
   // not be possible (for instance, if they have two table cells selected, you
   // need two blockquotes inside the cells).
   nsCOMPtr<Element> curBlock;
   nsCOMPtr<nsINode> prevParent;
 
@@ -7811,171 +7793,184 @@ HTMLEditRules::MakeBlockquote(nsTArray<O
       EditorDOMPoint atCurNode(curNode);
       SplitNodeResult splitNodeResult =
         MaybeSplitAncestorsForInsertWithTransaction(*nsGkAtoms::blockquote,
                                                     atCurNode);
       if (NS_WARN_IF(splitNodeResult.Failed())) {
         return splitNodeResult.Rv();
       }
       curBlock =
-        htmlEditor->CreateNodeWithTransaction(*nsGkAtoms::blockquote,
-                                              splitNodeResult.SplitPoint());
+        HTMLEditorRef().CreateNodeWithTransaction(*nsGkAtoms::blockquote,
+                                                  splitNodeResult.SplitPoint());
       if (NS_WARN_IF(!curBlock)) {
         return NS_ERROR_FAILURE;
       }
       // remember our new block for postprocessing
       mNewBlock = curBlock;
       // note: doesn't matter if we set mNewBlock multiple times.
     }
 
     nsresult rv =
-      htmlEditor->MoveNodeToEndWithTransaction(*curNode->AsContent(),
-                                               *curBlock);
+      HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode->AsContent(),
+                                                   *curBlock);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
   return NS_OK;
 }
 
 /**
  * RemoveBlockStyle() makes the nodes have no special block type.
  */
 nsresult
 HTMLEditRules::RemoveBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray)
 {
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   // Intent of this routine is to be used for converting to/from headers,
   // paragraphs, pre, and address.  Those blocks that pretty much just contain
   // inline things...
   nsCOMPtr<Element> curBlock;
   nsCOMPtr<nsIContent> firstNode, lastNode;
   for (auto& curNode : aNodeArray) {
     // If curNode is a address, p, header, address, or pre, remove it
     if (HTMLEditUtils::IsFormatNode(curNode)) {
       // Process any partial progress saved
       if (curBlock) {
         nsresult rv = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
-        NS_ENSURE_SUCCESS(rv, rv);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
         firstNode = lastNode = curBlock = nullptr;
       }
-      if (!mHTMLEditor->IsEditable(curNode)) {
+      if (!HTMLEditorRef().IsEditable(curNode)) {
         continue;
       }
       // Remove current block
       nsresult rv =
-        htmlEditor->RemoveBlockContainerWithTransaction(*curNode->AsElement());
-      NS_ENSURE_SUCCESS(rv, rv);
+        HTMLEditorRef().RemoveBlockContainerWithTransaction(
+                          *curNode->AsElement());
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
     } else if (curNode->IsAnyOfHTMLElements(nsGkAtoms::table,
                                             nsGkAtoms::tr,
                                             nsGkAtoms::tbody,
                                             nsGkAtoms::td,
                                             nsGkAtoms::li,
                                             nsGkAtoms::blockquote,
                                             nsGkAtoms::div) ||
                 HTMLEditUtils::IsList(curNode)) {
       // Process any partial progress saved
       if (curBlock) {
         nsresult rv = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
-        NS_ENSURE_SUCCESS(rv, rv);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
         firstNode = lastNode = curBlock = nullptr;
       }
-      if (!mHTMLEditor->IsEditable(curNode)) {
+      if (!HTMLEditorRef().IsEditable(curNode)) {
         continue;
       }
       // Recursion time
       nsTArray<OwningNonNull<nsINode>> childArray;
       GetChildNodesForOperation(*curNode, childArray);
       nsresult rv = RemoveBlockStyle(childArray);
-      NS_ENSURE_SUCCESS(rv, rv);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
     } else if (IsInlineNode(curNode)) {
       if (curBlock) {
         // If so, is this node a descendant?
         if (EditorUtils::IsDescendantOf(*curNode, *curBlock)) {
           // Then we don't need to do anything different for this node
           lastNode = curNode->AsContent();
           continue;
         }
         // Otherwise, we have progressed beyond end of curBlock, so let's
         // handle it now.  We need to remove the portion of curBlock that
         // contains [firstNode - lastNode].
         nsresult rv = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
-        NS_ENSURE_SUCCESS(rv, rv);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
         firstNode = lastNode = curBlock = nullptr;
         // Fall out and handle curNode
       }
-      curBlock = htmlEditor->GetBlockNodeParent(curNode);
+      curBlock = HTMLEditorRef().GetBlockNodeParent(curNode);
       if (!curBlock || !HTMLEditUtils::IsFormatNode(curBlock) ||
-          !mHTMLEditor->IsEditable(curBlock)) {
+          !HTMLEditorRef().IsEditable(curBlock)) {
         // Not a block kind that we care about.
         curBlock = nullptr;
       } else {
         firstNode = lastNode = curNode->AsContent();
       }
     } else if (curBlock) {
       // Some node that is already sans block style.  Skip over it and process
       // any partial progress saved.
       nsresult rv = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
-      NS_ENSURE_SUCCESS(rv, rv);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
       firstNode = lastNode = curBlock = nullptr;
     }
   }
   // Process any partial progress saved
   if (curBlock) {
     nsresult rv = RemovePartOfBlock(*curBlock, *firstNode, *lastNode);
-    NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
     firstNode = lastNode = curBlock = nullptr;
   }
   return NS_OK;
 }
 
 /**
  * ApplyBlockStyle() does whatever it takes to make the list of nodes into one
  * or more blocks of type aBlockTag.
  */
 nsresult
 HTMLEditRules::ApplyBlockStyle(nsTArray<OwningNonNull<nsINode>>& aNodeArray,
                                nsAtom& aBlockTag)
 {
   // Intent of this routine is to be used for converting to/from headers,
   // paragraphs, pre, and address.  Those blocks that pretty much just contain
   // inline things...
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   nsCOMPtr<Element> newBlock;
 
   nsCOMPtr<Element> curBlock;
   for (auto& curNode : aNodeArray) {
     EditorDOMPoint atCurNode(curNode);
 
     // Is it already the right kind of block, or an uneditable block?
     if (curNode->IsHTMLElement(&aBlockTag) ||
-        (!mHTMLEditor->IsEditable(curNode) && IsBlockNode(curNode))) {
+        (!HTMLEditorRef().IsEditable(curNode) && IsBlockNode(curNode))) {
       // Forget any previous block used for previous inline nodes
       curBlock = nullptr;
       // Do nothing to this block
       continue;
     }
 
     // If curNode is a address, p, header, address, or pre, replace it with a
     // new block of correct type.
     // XXX: pre can't hold everything the others can
     if (HTMLEditUtils::IsMozDiv(curNode) ||
         HTMLEditUtils::IsFormatNode(curNode)) {
       // Forget any previous block used for previous inline nodes
       curBlock = nullptr;
       newBlock =
-        htmlEditor->ReplaceContainerAndCloneAttributesWithTransaction(
-                      *curNode->AsElement(), aBlockTag);
-      NS_ENSURE_STATE(newBlock);
+        HTMLEditorRef().ReplaceContainerAndCloneAttributesWithTransaction(
+                          *curNode->AsElement(), aBlockTag);
+      if (NS_WARN_IF(!newBlock)) {
+        return NS_ERROR_FAILURE;
+      }
       continue;
     }
 
     if (HTMLEditUtils::IsTable(curNode) ||
         HTMLEditUtils::IsList(curNode) ||
         curNode->IsAnyOfHTMLElements(nsGkAtoms::tbody,
                                      nsGkAtoms::tr,
                                      nsGkAtoms::td,
@@ -7984,100 +7979,103 @@ HTMLEditRules::ApplyBlockStyle(nsTArray<
                                      nsGkAtoms::div)) {
       // Forget any previous block used for previous inline nodes
       curBlock = nullptr;
       // Recursion time
       nsTArray<OwningNonNull<nsINode>> childArray;
       GetChildNodesForOperation(*curNode, childArray);
       if (!childArray.IsEmpty()) {
         nsresult rv = ApplyBlockStyle(childArray, aBlockTag);
-        NS_ENSURE_SUCCESS(rv, rv);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
         continue;
       }
 
       // Make sure we can put a block here
       SplitNodeResult splitNodeResult =
         MaybeSplitAncestorsForInsertWithTransaction(aBlockTag, atCurNode);
       if (NS_WARN_IF(splitNodeResult.Failed())) {
         return splitNodeResult.Rv();
       }
       RefPtr<Element> theBlock =
-        htmlEditor->CreateNodeWithTransaction(aBlockTag,
-                                              splitNodeResult.SplitPoint());
+        HTMLEditorRef().CreateNodeWithTransaction(aBlockTag,
+                                                  splitNodeResult.SplitPoint());
       if (NS_WARN_IF(!theBlock)) {
         return NS_ERROR_FAILURE;
       }
       // Remember our new block for postprocessing
       mNewBlock = theBlock;
       continue;
     }
 
     if (curNode->IsHTMLElement(nsGkAtoms::br)) {
       // If the node is a break, we honor it by putting further nodes in a new
       // parent
       if (curBlock) {
         // Forget any previous block used for previous inline nodes
         curBlock = nullptr;
-        nsresult rv = htmlEditor->DeleteNodeWithTransaction(*curNode);
+        nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(*curNode);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
         continue;
       }
 
       // The break is the first (or even only) node we encountered.  Create a
       // block for it.
       SplitNodeResult splitNodeResult =
         MaybeSplitAncestorsForInsertWithTransaction(aBlockTag, atCurNode);
       if (NS_WARN_IF(splitNodeResult.Failed())) {
         return splitNodeResult.Rv();
       }
       curBlock =
-        htmlEditor->CreateNodeWithTransaction(aBlockTag,
-                                              splitNodeResult.SplitPoint());
+        HTMLEditorRef().CreateNodeWithTransaction(aBlockTag,
+                                                  splitNodeResult.SplitPoint());
       if (NS_WARN_IF(!curBlock)) {
         return NS_ERROR_FAILURE;
       }
       // Remember our new block for postprocessing
       mNewBlock = curBlock;
       // Note: doesn't matter if we set mNewBlock multiple times.
       nsresult rv =
-        htmlEditor->MoveNodeToEndWithTransaction(*curNode->AsContent(),
-                                                 *curBlock);
+        HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode->AsContent(),
+                                                     *curBlock);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       continue;
     }
 
     if (IsInlineNode(curNode)) {
       // If curNode is inline, pull it into curBlock.  Note: it's assumed that
       // consecutive inline nodes in aNodeArray are actually members of the
       // same block parent.  This happens to be true now as a side effect of
       // how aNodeArray is contructed, but some additional logic should be
       // added here if that should change
       //
       // If curNode is a non editable, drop it if we are going to <pre>.
-      if (&aBlockTag == nsGkAtoms::pre && !htmlEditor->IsEditable(curNode)) {
+      if (&aBlockTag == nsGkAtoms::pre &&
+          !HTMLEditorRef().IsEditable(curNode)) {
         // Do nothing to this block
         continue;
       }
 
       // If no curBlock, make one
       if (!curBlock) {
         AutoEditorDOMPointOffsetInvalidator lockChild(atCurNode);
 
         SplitNodeResult splitNodeResult =
           MaybeSplitAncestorsForInsertWithTransaction(aBlockTag, atCurNode);
         if (NS_WARN_IF(splitNodeResult.Failed())) {
           return splitNodeResult.Rv();
         }
         curBlock =
-          htmlEditor->CreateNodeWithTransaction(aBlockTag,
-                                                splitNodeResult.SplitPoint());
+          HTMLEditorRef().CreateNodeWithTransaction(
+                            aBlockTag, splitNodeResult.SplitPoint());
         if (NS_WARN_IF(!curBlock)) {
           return NS_ERROR_FAILURE;
         }
         // Remember our new block for postprocessing
         mNewBlock = curBlock;
         // Note: doesn't matter if we set mNewBlock multiple times.
       }
 
@@ -8086,43 +8084,40 @@ HTMLEditRules::ApplyBlockStyle(nsTArray<
         return NS_ERROR_UNEXPECTED;
       }
 
       // XXX If curNode is a br, replace it with a return if going to <pre>
 
       // This is a continuation of some inline nodes that belong together in
       // the same block item.  Use curBlock.
       nsresult rv =
-        htmlEditor->MoveNodeToEndWithTransaction(*curNode->AsContent(),
-                                                 *curBlock);
+        HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode->AsContent(),
+                                                     *curBlock);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
   }
   return NS_OK;
 }
 
 template<typename PT, typename CT>
 SplitNodeResult
 HTMLEditRules::MaybeSplitAncestorsForInsertWithTransaction(
                  nsAtom& aTag,
                  const EditorDOMPointBase<PT, CT>& aStartOfDeepestRightNode)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (NS_WARN_IF(!aStartOfDeepestRightNode.IsSet())) {
     return SplitNodeResult(NS_ERROR_INVALID_ARG);
   }
   MOZ_ASSERT(aStartOfDeepestRightNode.IsSetAndValid());
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return SplitNodeResult(NS_ERROR_NOT_AVAILABLE);
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
-  RefPtr<Element> host = htmlEditor->GetActiveEditingHost();
+  RefPtr<Element> host = HTMLEditorRef().GetActiveEditingHost();
   if (NS_WARN_IF(!host)) {
     return SplitNodeResult(NS_ERROR_FAILURE);
   }
 
   // The point must be descendant of editing host.
   if (NS_WARN_IF(aStartOfDeepestRightNode.GetContainer() != host &&
                  !EditorUtils::IsDescendantOf(
                    *aStartOfDeepestRightNode.GetContainer(), *host))) {
@@ -8134,115 +8129,104 @@ HTMLEditRules::MaybeSplitAncestorsForIns
   for (; pointToInsert.IsSet();
        pointToInsert.Set(pointToInsert.GetContainer())) {
     // We cannot split active editing host and its ancestor.  So, there is
     // no element to contain the specified element.
     if (NS_WARN_IF(pointToInsert.GetChild() == host)) {
       return SplitNodeResult(NS_ERROR_FAILURE);
     }
 
-    if (htmlEditor->CanContainTag(*pointToInsert.GetContainer(), aTag)) {
+    if (HTMLEditorRef().CanContainTag(*pointToInsert.GetContainer(), aTag)) {
       // Found an ancestor node which can contain the element.
       break;
     }
   }
 
   MOZ_DIAGNOSTIC_ASSERT(pointToInsert.IsSet());
 
   // If the point itself can contain the tag, we don't need to split any
   // ancestor nodes.  In this case, we should return the given split point
   // as is.
   if (pointToInsert.GetContainer() == aStartOfDeepestRightNode.GetContainer()) {
     return SplitNodeResult(aStartOfDeepestRightNode);
   }
 
   SplitNodeResult splitNodeResult =
-    htmlEditor->SplitNodeDeepWithTransaction(
-                  *pointToInsert.GetChild(),
-                  aStartOfDeepestRightNode,
-                  SplitAtEdges::eAllowToCreateEmptyContainer);
+    HTMLEditorRef().SplitNodeDeepWithTransaction(
+                      *pointToInsert.GetChild(),
+                      aStartOfDeepestRightNode,
+                      SplitAtEdges::eAllowToCreateEmptyContainer);
   NS_WARNING_ASSERTION(splitNodeResult.Succeeded(),
     "Failed to split the node for insert the element");
   return splitNodeResult;
 }
 
 EditorDOMPoint
 HTMLEditRules::JoinNearestEditableNodesWithTransaction(nsIContent& aNodeLeft,
                                                        nsIContent& aNodeRight)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   // Caller responsible for left and right node being the same type
   nsCOMPtr<nsINode> parent = aNodeLeft.GetParentNode();
   if (NS_WARN_IF(!parent)) {
     return EditorDOMPoint();
   }
   int32_t parOffset = parent->ComputeIndexOf(&aNodeLeft);
   nsCOMPtr<nsINode> rightParent = aNodeRight.GetParentNode();
 
   // If they don't have the same parent, first move the right node to after the
   // left one
   if (parent != rightParent) {
-    if (NS_WARN_IF(!mHTMLEditor)) {
-      return EditorDOMPoint();
-    }
     nsresult rv =
-      mHTMLEditor->MoveNodeWithTransaction(aNodeRight,
-                                           EditorRawDOMPoint(parent,
-                                                             parOffset));
+      HTMLEditorRef().MoveNodeWithTransaction(
+                        aNodeRight, EditorRawDOMPoint(parent, parOffset));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return EditorDOMPoint();
     }
   }
 
   EditorDOMPoint ret(&aNodeRight, aNodeLeft.Length());
 
   // Separate join rules for differing blocks
   if (HTMLEditUtils::IsList(&aNodeLeft) || aNodeLeft.GetAsText()) {
     // For lists, merge shallow (wouldn't want to combine list items)
-    nsresult rv = mHTMLEditor->JoinNodesWithTransaction(aNodeLeft, aNodeRight);
+    nsresult rv =
+      HTMLEditorRef().JoinNodesWithTransaction(aNodeLeft, aNodeRight);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return EditorDOMPoint();
     }
     return ret;
   }
 
   // Remember the last left child, and first right child
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return EditorDOMPoint();
-  }
-  nsCOMPtr<nsIContent> lastLeft = mHTMLEditor->GetLastEditableChild(aNodeLeft);
+  nsCOMPtr<nsIContent> lastLeft =
+    HTMLEditorRef().GetLastEditableChild(aNodeLeft);
   if (NS_WARN_IF(!lastLeft)) {
     return EditorDOMPoint();
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return EditorDOMPoint();
-  }
-  nsCOMPtr<nsIContent> firstRight = mHTMLEditor->GetFirstEditableChild(aNodeRight);
+  nsCOMPtr<nsIContent> firstRight =
+    HTMLEditorRef().GetFirstEditableChild(aNodeRight);
   if (NS_WARN_IF(!firstRight)) {
     return EditorDOMPoint();
   }
 
   // For list items, divs, etc., merge smart
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return EditorDOMPoint();
-  }
-  nsresult rv = mHTMLEditor->JoinNodesWithTransaction(aNodeLeft, aNodeRight);
+  nsresult rv = HTMLEditorRef().JoinNodesWithTransaction(aNodeLeft, aNodeRight);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return EditorDOMPoint();
   }
 
-  if (lastLeft && firstRight && mHTMLEditor &&
-      mHTMLEditor->AreNodesSameType(lastLeft, firstRight) &&
-      (lastLeft->GetAsText() || !mHTMLEditor ||
+  if (lastLeft && firstRight &&
+      HTMLEditorRef().AreNodesSameType(lastLeft, firstRight) &&
+      (lastLeft->GetAsText() ||
        (lastLeft->IsElement() && firstRight->IsElement() &&
         CSSEditUtils::ElementsSameStyle(lastLeft->AsElement(),
                                         firstRight->AsElement())))) {
-    if (NS_WARN_IF(!mHTMLEditor)) {
-      return EditorDOMPoint();
-    }
     return JoinNearestEditableNodesWithTransaction(*lastLeft, *firstRight);
   }
   return ret;
 }
 
 Element*
 HTMLEditRules::GetTopEnclosingMailCite(nsINode& aNode)
 {
@@ -8259,85 +8243,84 @@ HTMLEditRules::GetTopEnclosingMailCite(n
   }
 
   return ret;
 }
 
 nsresult
 HTMLEditRules::CacheInlineStyles(nsINode* aNode)
 {
-  NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER);
-
-  NS_ENSURE_STATE(mHTMLEditor);
+  MOZ_ASSERT(IsEditorDataAvailable());
+
+  if (NS_WARN_IF(!aNode)) {
+    return NS_ERROR_INVALID_ARG;
+  }
 
   nsresult rv = GetInlineStyles(aNode, mCachedStyles);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::GetInlineStyles(nsINode* aNode,
                                StyleCache aStyleCache[SIZE_STYLE_TABLE])
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aNode);
-  MOZ_ASSERT(mHTMLEditor);
-
-  bool useCSS = mHTMLEditor->IsCSSEnabled();
+
+  bool useCSS = HTMLEditorRef().IsCSSEnabled();
 
   for (size_t j = 0; j < SIZE_STYLE_TABLE; ++j) {
     // If type-in state is set, don't intervene
     bool typeInSet, unused;
-    if (NS_WARN_IF(!mHTMLEditor)) {
-      return NS_ERROR_UNEXPECTED;
-    }
-    mHTMLEditor->mTypeInState->GetTypingState(typeInSet, unused,
-      aStyleCache[j].tag, aStyleCache[j].attr, nullptr);
+    HTMLEditorRef().mTypeInState->GetTypingState(
+                                    typeInSet, unused, aStyleCache[j].tag,
+                                    aStyleCache[j].attr, nullptr);
     if (typeInSet) {
       continue;
     }
 
     bool isSet = false;
     nsAutoString outValue;
     // Don't use CSS for <font size>, we don't support it usefully (bug 780035)
     if (!useCSS || (aStyleCache[j].tag == nsGkAtoms::font &&
                     aStyleCache[j].attr == nsGkAtoms::size)) {
-      NS_ENSURE_STATE(mHTMLEditor);
-      isSet = mHTMLEditor->IsTextPropertySetByContent(aNode, aStyleCache[j].tag,
-                                                      aStyleCache[j].attr,
-                                                      nullptr,
-                                                      &outValue);
+      isSet =
+        HTMLEditorRef().IsTextPropertySetByContent(aNode, aStyleCache[j].tag,
+                                                   aStyleCache[j].attr,
+                                                   nullptr, &outValue);
     } else {
       isSet = CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(
                 aNode, aStyleCache[j].tag, aStyleCache[j].attr, outValue,
                 CSSEditUtils::eComputed);
     }
     if (isSet) {
       aStyleCache[j].mPresent = true;
       aStyleCache[j].value.Assign(outValue);
     }
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::ReapplyCachedStyles()
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   // The idea here is to examine our cached list of styles and see if any have
   // been removed.  If so, add typeinstate for them, so that they will be
   // reinserted when new content is added.
 
   // remember if we are in css mode
-  NS_ENSURE_STATE(mHTMLEditor);
-  bool useCSS = mHTMLEditor->IsCSSEnabled();
+  bool useCSS = HTMLEditorRef().IsCSSEnabled();
 
   // get selection point; if it doesn't exist, we have nothing to do
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<Selection> selection = mHTMLEditor->GetSelection();
+  RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
   if (!selection) {
     // If the document is removed from its parent document during executing an
     // editor operation with DOMMutationEvent or something, there may be no
     // selection.
     return NS_OK;
   }
   if (!selection->RangeCount()) {
     // Nothing to do
@@ -8366,34 +8349,34 @@ HTMLEditRules::ReapplyCachedStyles()
       if (useCSS) {
         // check computed style first in css case
         bAny = CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(
                  selNode, mCachedStyles[i].tag, mCachedStyles[i].attr, curValue,
                  CSSEditUtils::eComputed);
       }
       if (!bAny) {
         // then check typeinstate and html style
-        NS_ENSURE_STATE(mHTMLEditor);
         nsresult rv =
-          mHTMLEditor->GetInlinePropertyBase(*mCachedStyles[i].tag,
-                                             mCachedStyles[i].attr,
-                                             &(mCachedStyles[i].value),
-                                             &bFirst, &bAny, &bAll,
-                                             &curValue);
-        NS_ENSURE_SUCCESS(rv, rv);
+          HTMLEditorRef().GetInlinePropertyBase(*mCachedStyles[i].tag,
+                                                mCachedStyles[i].attr,
+                                                &(mCachedStyles[i].value),
+                                                &bFirst, &bAny, &bAll,
+                                                &curValue);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
       }
       // This style has disappeared through deletion.  Let's add the styles to
       // mTypeInState when same style isn't applied to the node already.
       if ((!bAny || IsStyleCachePreservingAction(mTheAction)) &&
            (!styleAtInsertionPoint[i].mPresent ||
             styleAtInsertionPoint[i].value != mCachedStyles[i].value)) {
-        NS_ENSURE_STATE(mHTMLEditor);
-        mHTMLEditor->mTypeInState->SetProp(mCachedStyles[i].tag,
-                                           mCachedStyles[i].attr,
-                                           mCachedStyles[i].value);
+        HTMLEditorRef().mTypeInState->SetProp(mCachedStyles[i].tag,
+                                              mCachedStyles[i].attr,
+                                              mCachedStyles[i].value);
       }
     }
   }
 
   return NS_OK;
 }
 
 void
@@ -8404,21 +8387,21 @@ HTMLEditRules::ClearCachedStyles()
     mCachedStyles[j].mPresent = false;
     mCachedStyles[j].value.Truncate();
   }
 }
 
 void
 HTMLEditRules::AdjustSpecialBreaks()
 {
-  NS_ENSURE_TRUE_VOID(mHTMLEditor);
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   // Gather list of empty nodes
   nsTArray<OwningNonNull<nsINode>> nodeArray;
-  EmptyEditableFunctor functor(mHTMLEditor);
+  EmptyEditableFunctor functor(&HTMLEditorRef());
   DOMIterator iter;
   if (NS_WARN_IF(NS_FAILED(iter.Init(*mDocChangeRange)))) {
     return;
   }
   iter.AppendList(functor, nodeArray);
 
   // Put moz-br's into these empty li's and td's
   for (auto& node : nodeArray) {
@@ -8433,31 +8416,37 @@ HTMLEditRules::AdjustSpecialBreaks()
       return;
     }
   }
 }
 
 nsresult
 HTMLEditRules::AdjustWhitespace(Selection* aSelection)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   EditorRawDOMPoint selectionStartPoint(EditorBase::GetStartPoint(aSelection));
   if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // Ask whitespace object to tweak nbsp's
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  return WSRunObject(mHTMLEditor, selectionStartPoint).AdjustWhitespace();
+  nsresult rv =
+    WSRunObject(&HTMLEditorRef(), selectionStartPoint).AdjustWhitespace();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 nsresult
 HTMLEditRules::PinSelectionToNewBlock(Selection* aSelection)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   NS_ENSURE_TRUE(aSelection, NS_ERROR_NULL_POINTER);
   if (!aSelection->IsCollapsed()) {
     return NS_OK;
   }
 
   if (NS_WARN_IF(!mNewBlock)) {
     return NS_ERROR_NULL_POINTER;
   }
@@ -8482,153 +8471,149 @@ HTMLEditRules::PinSelectionToNewBlock(Se
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (nodeBefore && nodeAfter) {
     return NS_OK;  // selection is inside block
   }
 
   if (nodeBefore) {
     // selection is after block.  put at end of block.
-    NS_ENSURE_STATE(mHTMLEditor);
-    nsCOMPtr<nsINode> tmp = mHTMLEditor->GetLastEditableChild(*mNewBlock);
+    nsCOMPtr<nsINode> tmp = HTMLEditorRef().GetLastEditableChild(*mNewBlock);
     if (!tmp) {
       tmp = mNewBlock;
     }
     EditorRawDOMPoint endPoint;
     if (EditorBase::IsTextNode(tmp) ||
-        mHTMLEditor->IsContainer(tmp)) {
+        HTMLEditorRef().IsContainer(tmp)) {
       endPoint.SetToEndOf(tmp);
     } else {
       endPoint.Set(tmp);
       if (NS_WARN_IF(!endPoint.AdvanceOffset())) {
         return NS_ERROR_FAILURE;
       }
     }
     return aSelection->Collapse(endPoint);
   }
 
   // selection is before block.  put at start of block.
-  NS_ENSURE_STATE(mHTMLEditor);
-  nsCOMPtr<nsINode> tmp = mHTMLEditor->GetFirstEditableChild(*mNewBlock);
+  nsCOMPtr<nsINode> tmp = HTMLEditorRef().GetFirstEditableChild(*mNewBlock);
   if (!tmp) {
     tmp = mNewBlock;
   }
   EditorRawDOMPoint atStartOfBlock;
   if (EditorBase::IsTextNode(tmp) ||
-      mHTMLEditor->IsContainer(tmp)) {
+      HTMLEditorRef().IsContainer(tmp)) {
     atStartOfBlock.Set(tmp);
   } else {
     atStartOfBlock.Set(tmp, 0);
   }
   return aSelection->Collapse(atStartOfBlock);
 }
 
 void
 HTMLEditRules::CheckInterlinePosition(Selection& aSelection)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   // If the selection isn't collapsed, do nothing.
   if (!aSelection.IsCollapsed()) {
     return;
   }
 
-  NS_ENSURE_TRUE_VOID(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   // Get the (collapsed) selection location
   nsRange* firstRange = aSelection.GetRangeAt(0);
   if (NS_WARN_IF(!firstRange)) {
     return;
   }
 
   EditorDOMPoint atStartOfSelection(firstRange->StartRef());
   if (NS_WARN_IF(!atStartOfSelection.IsSet())) {
     return;
   }
   MOZ_ASSERT(atStartOfSelection.IsSetAndValid());
 
   // First, let's check to see if we are after a <br>.  We take care of this
   // special-case first so that we don't accidentally fall through into one of
   // the other conditionals.
   nsCOMPtr<nsIContent> node =
-    htmlEditor->GetPreviousEditableHTMLNodeInBlock(atStartOfSelection);
+    HTMLEditorRef().GetPreviousEditableHTMLNodeInBlock(atStartOfSelection);
   if (node && node->IsHTMLElement(nsGkAtoms::br)) {
     aSelection.SetInterlinePosition(true, IgnoreErrors());
     return;
   }
 
   // Are we after a block?  If so try set caret to following content
   if (atStartOfSelection.GetChild()) {
-    node = htmlEditor->GetPriorHTMLSibling(atStartOfSelection.GetChild());
+    node = HTMLEditorRef().GetPriorHTMLSibling(atStartOfSelection.GetChild());
   } else {
     node = nullptr;
   }
   if (node && IsBlockNode(*node)) {
     aSelection.SetInterlinePosition(true, IgnoreErrors());
     return;
   }
 
   // Are we before a block?  If so try set caret to prior content
   if (atStartOfSelection.GetChild()) {
-    node = htmlEditor->GetNextHTMLSibling(atStartOfSelection.GetChild());
+    node = HTMLEditorRef().GetNextHTMLSibling(atStartOfSelection.GetChild());
   } else {
     node = nullptr;
   }
   if (node && IsBlockNode(*node)) {
     aSelection.SetInterlinePosition(false, IgnoreErrors());
   }
 }
 
 nsresult
 HTMLEditRules::AdjustSelection(Selection* aSelection,
                                nsIEditor::EDirection aAction)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (NS_WARN_IF(!aSelection)) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   // if the selection isn't collapsed, do nothing.
   // moose: one thing to do instead is check for the case of
   // only a single break selected, and collapse it.  Good thing?  Beats me.
   if (!aSelection->IsCollapsed()) {
     return NS_OK;
   }
 
   // get the (collapsed) selection location
   EditorDOMPoint point(EditorBase::GetStartPoint(aSelection));
   if (NS_WARN_IF(!point.IsSet())) {
     return NS_ERROR_FAILURE;
   }
 
   // are we in an editable node?
-  while (!htmlEditor->IsEditable(point.GetContainer())) {
+  while (!HTMLEditorRef().IsEditable(point.GetContainer())) {
     // scan up the tree until we find an editable place to be
     point.Set(point.GetContainer());
     if (NS_WARN_IF(!point.IsSet())) {
       return NS_ERROR_FAILURE;
     }
   }
 
   // make sure we aren't in an empty block - user will see no cursor.  If this
   // is happening, put a <br> in the block if allowed.
-  RefPtr<Element> theblock = htmlEditor->GetBlock(*point.GetContainer());
-
-  if (theblock && htmlEditor->IsEditable(theblock)) {
+  RefPtr<Element> theblock = HTMLEditorRef().GetBlock(*point.GetContainer());
+
+  if (theblock && HTMLEditorRef().IsEditable(theblock)) {
     bool bIsEmptyNode;
     nsresult rv =
-      htmlEditor->IsEmptyNode(theblock, &bIsEmptyNode, false, false);
-    NS_ENSURE_SUCCESS(rv, rv);
+      HTMLEditorRef().IsEmptyNode(theblock, &bIsEmptyNode, false, false);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
     // check if br can go into the destination node
     if (bIsEmptyNode &&
-        htmlEditor->CanContainTag(*point.GetContainer(), *nsGkAtoms::br)) {
-      Element* rootElement = htmlEditor->GetRoot();
+        HTMLEditorRef().CanContainTag(*point.GetContainer(), *nsGkAtoms::br)) {
+      Element* rootElement = HTMLEditorRef().GetRoot();
       if (NS_WARN_IF(!rootElement)) {
         return NS_ERROR_FAILURE;
       }
       if (point.GetContainer() == rootElement) {
         // Our root node is completely empty. Don't add a <br> here.
         // AfterEditInner() will add one for us when it calls
         // CreateBogusNodeIfNeeded()!
         return NS_OK;
@@ -8649,24 +8634,24 @@ HTMLEditRules::AdjustSelection(Selection
   }
 
   // do we need to insert a special mozBR?  We do if we are:
   // 1) prior node is in same block where selection is AND
   // 2) prior node is a br AND
   // 3) that br is not visible
 
   nsCOMPtr<nsIContent> nearNode =
-    htmlEditor->GetPreviousEditableHTMLNode(point);
+    HTMLEditorRef().GetPreviousEditableHTMLNode(point);
   if (nearNode) {
     // is nearNode also a descendant of same block?
-    RefPtr<Element> block = htmlEditor->GetBlock(*point.GetContainer());
-    RefPtr<Element> nearBlock = htmlEditor->GetBlockNodeParent(nearNode);
+    RefPtr<Element> block = HTMLEditorRef().GetBlock(*point.GetContainer());
+    RefPtr<Element> nearBlock = HTMLEditorRef().GetBlockNodeParent(nearNode);
     if (block && block == nearBlock) {
       if (nearNode && TextEditUtils::IsBreak(nearNode)) {
-        if (!htmlEditor->IsVisibleBRElement(nearNode)) {
+        if (!HTMLEditorRef().IsVisibleBRElement(nearNode)) {
           // need to insert special moz BR. Why?  Because if we don't
           // the user will see no new line for the break.  Also, things
           // like table cells won't grow in height.
           RefPtr<Element> brElement = CreateMozBR(point);
           if (NS_WARN_IF(!brElement)) {
             return NS_ERROR_FAILURE;
           }
           point.Set(brElement);
@@ -8674,37 +8659,37 @@ HTMLEditRules::AdjustSelection(Selection
           aSelection->SetInterlinePosition(true, IgnoreErrors());
           ErrorResult error;
           aSelection->Collapse(point, error);
           if (NS_WARN_IF(error.Failed())) {
             return error.StealNSResult();
           }
         } else {
           nsCOMPtr<nsIContent> nextNode =
-            htmlEditor->GetNextEditableHTMLNodeInBlock(*nearNode);
+            HTMLEditorRef().GetNextEditableHTMLNodeInBlock(*nearNode);
           if (nextNode && TextEditUtils::IsMozBR(nextNode)) {
             // selection between br and mozbr.  make it stick to mozbr
             // so that it will be on blank line.
             aSelection->SetInterlinePosition(true, IgnoreErrors());
           }
         }
       }
     }
   }
 
   // we aren't in a textnode: are we adjacent to text or a break or an image?
-  nearNode = htmlEditor->GetPreviousEditableHTMLNodeInBlock(point);
+  nearNode = HTMLEditorRef().GetPreviousEditableHTMLNodeInBlock(point);
   if (nearNode && (TextEditUtils::IsBreak(nearNode) ||
                    EditorBase::IsTextNode(nearNode) ||
                    HTMLEditUtils::IsImage(nearNode) ||
                    nearNode->IsHTMLElement(nsGkAtoms::hr))) {
     // this is a good place for the caret to be
     return NS_OK;
   }
-  nearNode = htmlEditor->GetNextEditableHTMLNodeInBlock(point);
+  nearNode = HTMLEditorRef().GetNextEditableHTMLNodeInBlock(point);
   if (nearNode && (TextEditUtils::IsBreak(nearNode) ||
                    EditorBase::IsTextNode(nearNode) ||
                    nearNode->IsAnyOfHTMLElements(nsGkAtoms::img,
                                                  nsGkAtoms::hr))) {
     return NS_OK; // this is a good place for the caret to be
   }
 
   // look for a nearby text node.
@@ -8723,53 +8708,52 @@ HTMLEditRules::AdjustSelection(Selection
   return NS_OK;
 }
 
 template<typename PT, typename CT>
 nsIContent*
 HTMLEditRules::FindNearEditableNode(const EditorDOMPointBase<PT, CT>& aPoint,
                                     nsIEditor::EDirection aDirection)
 {
-  if (NS_WARN_IF(!aPoint.IsSet()) ||
-      NS_WARN_IF(!mHTMLEditor)) {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
+  if (NS_WARN_IF(!aPoint.IsSet())) {
     return nullptr;
   }
   MOZ_ASSERT(aPoint.IsSetAndValid());
 
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   nsIContent* nearNode = nullptr;
   if (aDirection == nsIEditor::ePrevious) {
-    nearNode = htmlEditor->GetPreviousEditableHTMLNode(aPoint);
+    nearNode = HTMLEditorRef().GetPreviousEditableHTMLNode(aPoint);
     if (!nearNode) {
       return nullptr; // Not illegal.
     }
   } else {
-    nearNode = htmlEditor->GetNextEditableHTMLNode(aPoint);
+    nearNode = HTMLEditorRef().GetNextEditableHTMLNode(aPoint);
     if (NS_WARN_IF(!nearNode)) {
       // Perhaps, illegal because the node pointed by aPoint isn't editable
       // and nobody of previous nodes is editable.
       return nullptr;
     }
   }
 
   // scan in the right direction until we find an eligible text node,
   // but don't cross any breaks, images, or table elements.
   // XXX This comment sounds odd.  |nearNode| may have already crossed breaks
   //     and/or images.
   while (nearNode && !(EditorBase::IsTextNode(nearNode) ||
                        TextEditUtils::IsBreak(nearNode) ||
                        HTMLEditUtils::IsImage(nearNode))) {
     if (aDirection == nsIEditor::ePrevious) {
-      nearNode = htmlEditor->GetPreviousEditableHTMLNode(*nearNode);
+      nearNode = HTMLEditorRef().GetPreviousEditableHTMLNode(*nearNode);
       if (NS_WARN_IF(!nearNode)) {
         return nullptr;
       }
     } else {
-      nearNode = htmlEditor->GetNextEditableHTMLNode(*nearNode);
+      nearNode = HTMLEditorRef().GetNextEditableHTMLNode(*nearNode);
       if (NS_WARN_IF(!nearNode)) {
         return nullptr;
       }
     }
   }
 
   // don't cross any table elements
   if (InDifferentTableElements(nearNode, aPoint.GetContainer())) {
@@ -8796,18 +8780,17 @@ HTMLEditRules::InDifferentTableElements(
 
   return aNode1 != aNode2;
 }
 
 
 nsresult
 HTMLEditRules::RemoveEmptyNodes()
 {
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   // Some general notes on the algorithm used here: the goal is to examine all
   // the nodes in mDocChangeRange, and remove the empty ones.  We do this by
   // using a content iterator to traverse all the nodes in the range, and
   // placing the empty nodes into an array.  After finishing the iteration, we
   // delete the empty nodes in the array.  (They cannot be deleted as we find
   // them because that would invalidate the iterator.)
   //
@@ -8879,18 +8862,21 @@ HTMLEditRules::RemoveEmptyNodes()
             bIsCandidate = true;
           }
         }
       }
 
       if (bIsCandidate) {
         // We delete mailcites even if they have a solo br in them.  Other
         // nodes we require to be empty.
-        rv = htmlEditor->IsEmptyNode(node, &bIsEmptyNode, bIsMailCite, true);
-        NS_ENSURE_SUCCESS(rv, rv);
+        rv = HTMLEditorRef().IsEmptyNode(node, &bIsEmptyNode,
+                                         bIsMailCite, true);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
         if (bIsEmptyNode) {
           if (bIsMailCite) {
             // mailcites go on a separate list from other empty nodes
             arrayOfEmptyCites.AppendElement(*node);
           } else {
             arrayOfEmptyNodes.AppendElement(*node);
           }
         }
@@ -8902,63 +8888,66 @@ HTMLEditRules::RemoveEmptyNodes()
       }
     }
 
     iter->Next();
   }
 
   // now delete the empty nodes
   for (OwningNonNull<nsINode>& delNode : arrayOfEmptyNodes) {
-    if (htmlEditor->IsModifiableNode(delNode)) {
-      rv = htmlEditor->DeleteNodeWithTransaction(*delNode);
+    if (HTMLEditorRef().IsModifiableNode(delNode)) {
+      rv = HTMLEditorRef().DeleteNodeWithTransaction(*delNode);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
   }
 
   // Now delete the empty mailcites.  This is a separate step because we want
   // to pull out any br's and preserve them.
   for (OwningNonNull<nsINode>& delNode : arrayOfEmptyCites) {
     bool bIsEmptyNode;
-    rv = htmlEditor->IsEmptyNode(delNode, &bIsEmptyNode, false, true);
-    NS_ENSURE_SUCCESS(rv, rv);
+    rv = HTMLEditorRef().IsEmptyNode(delNode, &bIsEmptyNode, false, true);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
     if (!bIsEmptyNode) {
-      RefPtr<Selection> selection = htmlEditor->GetSelection();
+      RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
       if (NS_WARN_IF(!selection)) {
         return NS_ERROR_FAILURE;
       }
       // We are deleting a cite that has just a br.  We want to delete cite,
       // but preserve br.
       RefPtr<Element> brElement =
-        htmlEditor->InsertBrElementWithTransaction(*selection,
-                                                   EditorRawDOMPoint(delNode));
+        HTMLEditorRef().InsertBrElementWithTransaction(
+                          *selection, EditorRawDOMPoint(delNode));
       if (NS_WARN_IF(!brElement)) {
         return NS_ERROR_FAILURE;
       }
     }
-    rv = htmlEditor->DeleteNodeWithTransaction(*delNode);
+    rv = HTMLEditorRef().DeleteNodeWithTransaction(*delNode);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::SelectionEndpointInNode(nsINode* aNode,
                                        bool* aResult)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   NS_ENSURE_TRUE(aNode && aResult, NS_ERROR_NULL_POINTER);
 
   *aResult = false;
 
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<Selection> selection = mHTMLEditor->GetSelection();
+  RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
   NS_ENSURE_STATE(selection);
 
   uint32_t rangeCount = selection->RangeCount();
   for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
     RefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
     nsINode* startContainer = range->GetStartContainer();
     if (startContainer) {
       if (aNode == startContainer) {
@@ -8989,43 +8978,42 @@ HTMLEditRules::SelectionEndpointInNode(n
 }
 
 /**
  * IsEmptyInline: Return true if aNode is an empty inline container
  */
 bool
 HTMLEditRules::IsEmptyInline(nsINode& aNode)
 {
-  NS_ENSURE_TRUE(mHTMLEditor, false);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
-  if (IsInlineNode(aNode) && htmlEditor->IsContainer(&aNode)) {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
+  if (IsInlineNode(aNode) && HTMLEditorRef().IsContainer(&aNode)) {
     bool isEmpty = true;
-    htmlEditor->IsEmptyNode(&aNode, &isEmpty);
+    HTMLEditorRef().IsEmptyNode(&aNode, &isEmpty);
     return isEmpty;
   }
   return false;
 }
 
 
 bool
 HTMLEditRules::ListIsEmptyLine(nsTArray<OwningNonNull<nsINode>>& aArrayOfNodes)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   // We have a list of nodes which we are candidates for being moved into a new
   // block.  Determine if it's anything more than a blank line.  Look for
   // editable content above and beyond one single BR.
-  NS_ENSURE_TRUE(aArrayOfNodes.Length(), true);
-
-  NS_ENSURE_TRUE(mHTMLEditor, false);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
+  if (NS_WARN_IF(!aArrayOfNodes.Length())) {
+    return true;
+  }
 
   int32_t brCount = 0;
-
   for (auto& node : aArrayOfNodes) {
-    if (!htmlEditor->IsEditable(node)) {
+    if (!HTMLEditorRef().IsEditable(node)) {
       continue;
     }
     if (TextEditUtils::IsBreak(node)) {
       // First break doesn't count
       if (brCount) {
         return false;
       }
       brCount++;
@@ -9038,60 +9026,52 @@ HTMLEditRules::ListIsEmptyLine(nsTArray<
   return true;
 }
 
 
 nsresult
 HTMLEditRules::PopListItem(nsIContent& aListItem,
                            bool* aOutOfList)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   // init out params
   if (aOutOfList) {
     *aOutOfList = false;
   }
 
   nsCOMPtr<nsIContent> kungFuDeathGrip(&aListItem);
   Unused << kungFuDeathGrip;
 
 
-  if (NS_WARN_IF(!mHTMLEditor) ||
-      NS_WARN_IF(!aListItem.GetParent()) ||
+  if (NS_WARN_IF(!aListItem.GetParent()) ||
       NS_WARN_IF(!aListItem.GetParent()->GetParentNode()) ||
       !HTMLEditUtils::IsListItem(&aListItem)) {
     return NS_ERROR_FAILURE;
   }
 
   // if it's first or last list item, don't need to split the list
   // otherwise we do.
-  bool bIsFirstListItem = mHTMLEditor->IsFirstEditableChild(&aListItem);
-  MOZ_ASSERT(mHTMLEditor);
-  bool bIsLastListItem = mHTMLEditor->IsLastEditableChild(&aListItem);
-  MOZ_ASSERT(mHTMLEditor);
+  bool bIsFirstListItem = HTMLEditorRef().IsFirstEditableChild(&aListItem);
+  bool bIsLastListItem = HTMLEditorRef().IsLastEditableChild(&aListItem);
 
   nsCOMPtr<nsIContent> leftListNode = aListItem.GetParent();
   if (!bIsFirstListItem && !bIsLastListItem) {
-    if (NS_WARN_IF(!mHTMLEditor)) {
-      return NS_ERROR_FAILURE;
-    }
-
     EditorDOMPoint atListItem(&aListItem);
     if (NS_WARN_IF(!atListItem.IsSet())) {
       return NS_ERROR_INVALID_ARG;
     }
     MOZ_ASSERT(atListItem.IsSetAndValid());
 
     // split the list
     ErrorResult error;
-    leftListNode = mHTMLEditor->SplitNodeWithTransaction(atListItem, error);
+    leftListNode = HTMLEditorRef().SplitNodeWithTransaction(atListItem, error);
     if (NS_WARN_IF(error.Failed())) {
       return error.StealNSResult();
     }
-    if (NS_WARN_IF(!mHTMLEditor)) {
-      return NS_ERROR_FAILURE;
-    }
   }
 
   // In most cases, insert the list item into the new left list node..
   EditorDOMPoint pointToInsertListItem(leftListNode);
   if (NS_WARN_IF(!pointToInsertListItem.IsSet())) {
     return NS_ERROR_FAILURE;
   }
   MOZ_ASSERT(pointToInsertListItem.IsSetAndValid());
@@ -9101,84 +9081,86 @@ HTMLEditRules::PopListItem(nsIContent& a
   // Enter twice at a list item breaks the parent list node.
   if (!bIsFirstListItem) {
     DebugOnly<bool> advanced = pointToInsertListItem.AdvanceOffset();
     NS_WARNING_ASSERTION(advanced,
       "Failed to advance offset to right list node");
   }
 
   nsresult rv =
-    mHTMLEditor->MoveNodeWithTransaction(aListItem, pointToInsertListItem);
+    HTMLEditorRef().MoveNodeWithTransaction(aListItem, pointToInsertListItem);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // unwrap list item contents if they are no longer in a list
   if (!HTMLEditUtils::IsList(pointToInsertListItem.GetContainer()) &&
       HTMLEditUtils::IsListItem(&aListItem)) {
-    NS_ENSURE_STATE(mHTMLEditor);
-    rv = mHTMLEditor->RemoveBlockContainerWithTransaction(
-                        *aListItem.AsElement());
-    NS_ENSURE_SUCCESS(rv, rv);
+    rv = HTMLEditorRef().RemoveBlockContainerWithTransaction(
+                           *aListItem.AsElement());
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
     if (aOutOfList) {
       *aOutOfList = true;
     }
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::RemoveListStructure(Element& aList)
 {
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   while (aList.GetFirstChild()) {
     OwningNonNull<nsIContent> child = *aList.GetFirstChild();
 
     if (HTMLEditUtils::IsListItem(child)) {
       bool isOutOfList;
       // Keep popping it out until it's not in a list anymore
       do {
         nsresult rv = PopListItem(child, &isOutOfList);
         NS_ENSURE_SUCCESS(rv, rv);
       } while (!isOutOfList);
     } else if (HTMLEditUtils::IsList(child)) {
       nsresult rv = RemoveListStructure(*child->AsElement());
-      NS_ENSURE_SUCCESS(rv, rv);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
     } else {
       // Delete any non-list items for now
-      nsresult rv = htmlEditor->DeleteNodeWithTransaction(*child);
+      nsresult rv = HTMLEditorRef().DeleteNodeWithTransaction(*child);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
   }
 
   // Delete the now-empty list
-  nsresult rv = htmlEditor->RemoveBlockContainerWithTransaction(aList);
-  NS_ENSURE_SUCCESS(rv, rv);
-
+  nsresult rv = HTMLEditorRef().RemoveBlockContainerWithTransaction(aList);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
   return NS_OK;
 }
 
 // XXX This method is not necessary because even if selection is outside the
 //     <body> element, the element can be editable.
 nsresult
 HTMLEditRules::ConfirmSelectionInBody()
 {
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  Element* rootElement = mHTMLEditor->GetRoot();
+  MOZ_ASSERT(IsEditorDataAvailable());
+
+  Element* rootElement = HTMLEditorRef().GetRoot();
   if (NS_WARN_IF(!rootElement)) {
     return NS_ERROR_UNEXPECTED;
   }
 
-  Selection* selection = mHTMLEditor->GetSelection();
+  Selection* selection = HTMLEditorRef().GetSelection();
   if (NS_WARN_IF(!selection)) {
     return NS_ERROR_UNEXPECTED;
   }
 
   EditorRawDOMPoint selectionStartPoint(EditorBase::GetStartPoint(selection));
   if (NS_WARN_IF(!selectionStartPoint.IsSet())) {
     return NS_ERROR_FAILURE;
   }
@@ -9214,29 +9196,27 @@ HTMLEditRules::ConfirmSelectionInBody()
   }
 
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::UpdateDocChangeRange(nsRange* aRange)
 {
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   // first make sure aRange is in the document.  It might not be if
   // portions of our editting action involved manipulating nodes
   // prior to placing them in the document (e.g., populating a list item
   // before placing it in its list)
   const RangeBoundary& atStart = aRange->StartRef();
   if (NS_WARN_IF(!atStart.IsSet())) {
     return NS_ERROR_FAILURE;
   }
-  if (!mHTMLEditor->IsDescendantOfRoot(atStart.Container())) {
+  if (!HTMLEditorRef().IsDescendantOfRoot(atStart.Container())) {
     // just return - we don't need to adjust mDocChangeRange in this case
     return NS_OK;
   }
 
   if (!mDocChangeRange) {
     // clone aRange.
     mDocChangeRange = aRange->CloneRange();
   } else {
@@ -9287,25 +9267,24 @@ HTMLEditRules::UpdateDocChangeRange(nsRa
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::InsertBRIfNeededInternal(nsINode& aNode,
                                         bool aInsertMozBR)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (!IsBlockNode(aNode)) {
     return NS_OK;
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_UNEXPECTED;
-  }
   bool isEmpty;
-  nsresult rv = mHTMLEditor->IsEmptyNode(&aNode, &isEmpty);
+  nsresult rv = HTMLEditorRef().IsEmptyNode(&aNode, &isEmpty);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   if (!isEmpty) {
     return NS_OK;
   }
 
   RefPtr<Element> brElement =
@@ -9520,156 +9499,162 @@ HTMLEditRules::WillDeleteSelection(Selec
 // be an ALIGN attribute (in case we just remove it) or a CENTER
 // element (here we have to remove the container and keep its
 // children). We break on tables and don't look at their children.
 nsresult
 HTMLEditRules::RemoveAlignment(nsINode& aNode,
                                const nsAString& aAlignType,
                                bool aChildrenOnly)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (EditorBase::IsTextNode(&aNode) || HTMLEditUtils::IsTable(&aNode)) {
     return NS_OK;
   }
 
   nsCOMPtr<nsINode> child, tmp;
   if (aChildrenOnly) {
     child = aNode.GetFirstChild();
   } else {
     child = &aNode;
   }
-  NS_ENSURE_STATE(mHTMLEditor);
-  bool useCSS = mHTMLEditor->IsCSSEnabled();
+
+  bool useCSS = HTMLEditorRef().IsCSSEnabled();
 
   while (child) {
     if (aChildrenOnly) {
       // get the next sibling right now because we could have to remove child
       tmp = child->GetNextSibling();
     } else {
       tmp = nullptr;
     }
 
     if (child->IsHTMLElement(nsGkAtoms::center)) {
       // the current node is a CENTER element
       // first remove children's alignment
       nsresult rv = RemoveAlignment(*child, aAlignType, true);
-      NS_ENSURE_SUCCESS(rv, rv);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
 
       // we may have to insert BRs in first and last position of element's children
       // if the nodes before/after are not blocks and not BRs
       rv = MakeSureElemStartsAndEndsOnCR(*child);
-      NS_ENSURE_SUCCESS(rv, rv);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
 
       // now remove the CENTER container
-      NS_ENSURE_STATE(mHTMLEditor);
-      rv = mHTMLEditor->RemoveContainerWithTransaction(*child->AsElement());
-      NS_ENSURE_SUCCESS(rv, rv);
+      rv = HTMLEditorRef().RemoveContainerWithTransaction(*child->AsElement());
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
     } else if (IsBlockNode(*child) || child->IsHTMLElement(nsGkAtoms::hr)) {
       // the current node is a block element
       if (HTMLEditUtils::SupportsAlignAttr(*child)) {
         // remove the ALIGN attribute if this element can have it
-        NS_ENSURE_STATE(mHTMLEditor);
         nsresult rv =
-          mHTMLEditor->RemoveAttributeWithTransaction(*child->AsElement(),
-                                                      *nsGkAtoms::align);
+          HTMLEditorRef().RemoveAttributeWithTransaction(*child->AsElement(),
+                                                         *nsGkAtoms::align);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
       if (useCSS) {
         if (child->IsAnyOfHTMLElements(nsGkAtoms::table, nsGkAtoms::hr)) {
-          NS_ENSURE_STATE(mHTMLEditor);
           nsresult rv =
-            mHTMLEditor->SetAttributeOrEquivalent(child->AsElement(),
-                                                  nsGkAtoms::align,
-                                                  aAlignType, false);
+            HTMLEditorRef().SetAttributeOrEquivalent(child->AsElement(),
+                                                     nsGkAtoms::align,
+                                                     aAlignType, false);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
         } else {
           nsAutoString dummyCssValue;
-          NS_ENSURE_STATE(mHTMLEditor);
-          nsresult rv = mHTMLEditor->mCSSEditUtils->RemoveCSSInlineStyle(
-                                                      *child,
-                                                      nsGkAtoms::textAlign,
-                                                      dummyCssValue);
+          nsresult rv = HTMLEditorRef().mCSSEditUtils->RemoveCSSInlineStyle(
+                                                         *child,
+                                                         nsGkAtoms::textAlign,
+                                                         dummyCssValue);
           if (NS_WARN_IF(NS_FAILED(rv))) {
             return rv;
           }
         }
       }
       if (!child->IsHTMLElement(nsGkAtoms::table)) {
         // unless this is a table, look at children
         nsresult rv = RemoveAlignment(*child, aAlignType, true);
-        NS_ENSURE_SUCCESS(rv, rv);
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
       }
     }
     child = tmp;
   }
   return NS_OK;
 }
 
 // Let's insert a BR as first (resp. last) child of aNode if its
 // first (resp. last) child is not a block nor a BR, and if the
 // previous (resp. next) sibling is not a block nor a BR
 nsresult
 HTMLEditRules::MakeSureElemStartsOrEndsOnCR(nsINode& aNode,
                                             bool aStarts)
 {
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
-  nsINode* child = aStarts ? htmlEditor->GetFirstEditableChild(aNode) :
-                             htmlEditor->GetLastEditableChild(aNode);
+  MOZ_ASSERT(IsEditorDataAvailable());
+
+  nsINode* child = aStarts ? HTMLEditorRef().GetFirstEditableChild(aNode) :
+                             HTMLEditorRef().GetLastEditableChild(aNode);
   if (NS_WARN_IF(!child)) {
     return NS_OK;
   }
 
   bool foundCR = false;
   if (IsBlockNode(*child) || child->IsHTMLElement(nsGkAtoms::br)) {
     foundCR = true;
   } else {
     nsINode* sibling =
-      aStarts ? htmlEditor->GetPriorHTMLSibling(&aNode) :
-                htmlEditor->GetNextHTMLSibling(&aNode);
+      aStarts ? HTMLEditorRef().GetPriorHTMLSibling(&aNode) :
+                HTMLEditorRef().GetNextHTMLSibling(&aNode);
     if (sibling) {
       if (IsBlockNode(*sibling) || sibling->IsHTMLElement(nsGkAtoms::br)) {
         foundCR = true;
       }
     } else {
       foundCR = true;
     }
   }
   if (!foundCR) {
-    RefPtr<Selection> selection = htmlEditor->GetSelection();
+    RefPtr<Selection> selection = HTMLEditorRef().GetSelection();
     if (NS_WARN_IF(!selection)) {
       return NS_ERROR_FAILURE;
     }
     EditorRawDOMPoint pointToInsert;
     if (!aStarts) {
       pointToInsert.SetToEndOf(&aNode);
     } else {
       pointToInsert.Set(&aNode, 0);
     }
     RefPtr<Element> brElement =
-      htmlEditor->InsertBrElementWithTransaction(*selection, pointToInsert);
+      HTMLEditorRef().InsertBrElementWithTransaction(*selection, pointToInsert);
     if (NS_WARN_IF(!brElement)) {
       return NS_ERROR_FAILURE;
     }
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::MakeSureElemStartsAndEndsOnCR(nsINode& aNode)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (NS_WARN_IF(!mHTMLEditor)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
+
   Selection* selection = mHTMLEditor->GetSelection();
   if (NS_WARN_IF(!selection)) {
     return NS_ERROR_FAILURE;
   }
 
   AutoSafeEditorData setData(*this, *mHTMLEditor, *selection);
 
   nsresult rv = MakeSureElemStartsOrEndsOnCR(aNode, false);
@@ -9683,51 +9668,55 @@ HTMLEditRules::MakeSureElemStartsAndEnds
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::AlignBlock(Element& aElement,
                           const nsAString& aAlignType,
                           ContentsOnly aContentsOnly)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (!IsBlockNode(aElement) && !aElement.IsHTMLElement(nsGkAtoms::hr)) {
     // We deal only with blocks; early way out
     return NS_OK;
   }
 
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   nsresult rv = RemoveAlignment(aElement, aAlignType,
                                 aContentsOnly == ContentsOnly::yes);
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (htmlEditor->IsCSSEnabled()) {
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  if (HTMLEditorRef().IsCSSEnabled()) {
     // Let's use CSS alignment; we use margin-left and margin-right for tables
     // and text-align for other block-level elements
-    return htmlEditor->SetAttributeOrEquivalent(
-                         &aElement, nsGkAtoms::align, aAlignType, false);
+    return HTMLEditorRef().SetAttributeOrEquivalent(
+                             &aElement, nsGkAtoms::align, aAlignType, false);
   }
 
   // HTML case; this code is supposed to be called ONLY if the element
   // supports the align attribute but we'll never know...
   if (NS_WARN_IF(!HTMLEditUtils::SupportsAlignAttr(aElement))) {
     // XXX error?
     return NS_OK;
   }
 
-  return htmlEditor->SetAttributeOrEquivalent(&aElement, nsGkAtoms::align,
-                                              aAlignType, false);
+  rv = HTMLEditorRef().SetAttributeOrEquivalent(&aElement, nsGkAtoms::align,
+                                                aAlignType, false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 nsresult
 HTMLEditRules::ChangeIndentation(Element& aElement,
                                  Change aChange)
 {
-  NS_ENSURE_STATE(mHTMLEditor);
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
+  MOZ_ASSERT(IsEditorDataAvailable());
 
   nsAtom& marginProperty = MarginPropertyAtomForIndent(aElement);
   nsAutoString value;
   CSSEditUtils::GetSpecifiedProperty(aElement, marginProperty, value);
   float f;
   RefPtr<nsAtom> unit;
   CSSEditUtils::ParseLength(value, &f, getter_AddRefs(unit));
   if (!f) {
@@ -9755,80 +9744,79 @@ HTMLEditRules::ChangeIndentation(Element
   } else if (nsGkAtoms::percentage == unit) {
     f += NS_EDITOR_INDENT_INCREMENT_PERCENT * multiplier;
   }
 
   if (0 < f) {
     nsAutoString newValue;
     newValue.AppendFloat(f);
     newValue.Append(nsDependentAtomString(unit));
-    htmlEditor->mCSSEditUtils->SetCSSProperty(aElement, marginProperty,
-                                              newValue);
+    HTMLEditorRef().mCSSEditUtils->SetCSSProperty(aElement, marginProperty,
+                                                  newValue);
     return NS_OK;
   }
 
-  htmlEditor->mCSSEditUtils->RemoveCSSProperty(aElement, marginProperty,
-                                               value);
+  HTMLEditorRef().mCSSEditUtils->RemoveCSSProperty(aElement, marginProperty,
+                                                   value);
 
   // Remove unnecessary divs
   if (!aElement.IsHTMLElement(nsGkAtoms::div) ||
-      &aElement == htmlEditor->GetActiveEditingHost() ||
-      !htmlEditor->IsDescendantOfEditorRoot(&aElement) ||
+      &aElement == HTMLEditorRef().GetActiveEditingHost() ||
+      !HTMLEditorRef().IsDescendantOfEditorRoot(&aElement) ||
       HTMLEditor::HasAttributes(&aElement)) {
     return NS_OK;
   }
 
-  nsresult rv = htmlEditor->RemoveContainerWithTransaction(aElement);
-  NS_ENSURE_SUCCESS(rv, rv);
-
+  nsresult rv = HTMLEditorRef().RemoveContainerWithTransaction(aElement);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::WillAbsolutePosition(Selection& aSelection,
                                     bool* aCancel,
                                     bool* aHandled)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
   MOZ_ASSERT(aCancel && aHandled);
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor(mHTMLEditor);
-
   WillInsert(aSelection, aCancel);
 
   // We want to ignore result of WillInsert()
   *aCancel = false;
   *aHandled = true;
 
-  nsCOMPtr<Element> focusElement = htmlEditor->GetSelectionContainer();
+  RefPtr<Element> focusElement = HTMLEditorRef().GetSelectionContainer();
   if (focusElement && HTMLEditUtils::IsImage(focusElement)) {
     mNewBlock = focusElement;
     return NS_OK;
   }
 
   nsresult rv = NormalizeSelection(&aSelection);
   NS_ENSURE_SUCCESS(rv, rv);
-  AutoSelectionRestorer selectionRestorer(&aSelection, htmlEditor);
+  AutoSelectionRestorer selectionRestorer(&aSelection, &HTMLEditorRef());
 
   // Convert the selection ranges into "promoted" selection ranges: this
   // basically just expands the range to include the immediate block parent,
   // and then further expands to include any ancestors whose children are all
   // in the range.
 
   nsTArray<RefPtr<nsRange>> arrayOfRanges;
   GetPromotedRanges(aSelection, arrayOfRanges,
                     EditAction::setAbsolutePosition);
 
   // Use these ranges to contruct a list of nodes to act on.
   nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
   rv = GetNodesForOperation(arrayOfRanges, arrayOfNodes,
                             EditAction::setAbsolutePosition);
-  NS_ENSURE_SUCCESS(rv, rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   // If nothing visible in list, make an empty block
   if (ListIsEmptyLine(arrayOfNodes)) {
     nsRange* firstRange = aSelection.GetRangeAt(0);
     if (NS_WARN_IF(!firstRange)) {
       return NS_ERROR_FAILURE;
     }
 
@@ -9840,27 +9828,27 @@ HTMLEditRules::WillAbsolutePosition(Sele
     // Make sure we can put a block here.
     SplitNodeResult splitNodeResult =
       MaybeSplitAncestorsForInsertWithTransaction(*nsGkAtoms::div,
                                                   atStartOfSelection);
     if (NS_WARN_IF(splitNodeResult.Failed())) {
       return splitNodeResult.Rv();
     }
     RefPtr<Element> positionedDiv =
-      htmlEditor->CreateNodeWithTransaction(*nsGkAtoms::div,
-                                            splitNodeResult.SplitPoint());
+      HTMLEditorRef().CreateNodeWithTransaction(*nsGkAtoms::div,
+                                                splitNodeResult.SplitPoint());
     if (NS_WARN_IF(!positionedDiv)) {
       return NS_ERROR_FAILURE;
     }
     // Remember our new block for postprocessing
     mNewBlock = positionedDiv;
     // Delete anything that was in the list of nodes
     while (!arrayOfNodes.IsEmpty()) {
       OwningNonNull<nsINode> curNode = arrayOfNodes[0];
-      rv = htmlEditor->DeleteNodeWithTransaction(*curNode);
+      rv = HTMLEditorRef().DeleteNodeWithTransaction(*curNode);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       arrayOfNodes.RemoveElementAt(0);
     }
     // Put selection in new block
     *aHandled = true;
     rv = aSelection.Collapse(positionedDiv, 0);
@@ -9876,62 +9864,62 @@ HTMLEditRules::WillAbsolutePosition(Sele
   for (OwningNonNull<nsINode>& curNode : arrayOfNodes) {
     // Here's where we actually figure out what to do.
     EditorDOMPoint atCurNode(curNode);
     if (NS_WARN_IF(!atCurNode.IsSet())) {
       return NS_ERROR_FAILURE; // XXX not continue??
     }
 
     // Ignore all non-editable nodes.  Leave them be.
-    if (!htmlEditor->IsEditable(curNode)) {
+    if (!HTMLEditorRef().IsEditable(curNode)) {
       continue;
     }
 
     nsCOMPtr<nsIContent> sibling;
 
     // Some logic for putting list items into nested lists...
     if (HTMLEditUtils::IsList(atCurNode.GetContainer())) {
       // Check to see if curList is still appropriate.  Which it is if curNode
       // is still right after it in the same list.
       if (curList) {
-        sibling = htmlEditor->GetPriorHTMLSibling(curNode);
+        sibling = HTMLEditorRef().GetPriorHTMLSibling(curNode);
       }
 
       if (!curList || (sibling && sibling != curList)) {
         nsAtom* containerName =
           atCurNode.GetContainer()->NodeInfo()->NameAtom();
         // Create a new nested list of correct type.
         SplitNodeResult splitNodeResult =
           MaybeSplitAncestorsForInsertWithTransaction(*containerName,
                                                       atCurNode);
         if (NS_WARN_IF(splitNodeResult.Failed())) {
           return splitNodeResult.Rv();
         }
         if (!curPositionedDiv) {
           curPositionedDiv =
-            htmlEditor->CreateNodeWithTransaction(*nsGkAtoms::div,
-                                                  splitNodeResult.SplitPoint());
+            HTMLEditorRef().CreateNodeWithTransaction(
+                              *nsGkAtoms::div, splitNodeResult.SplitPoint());
           NS_WARNING_ASSERTION(curPositionedDiv,
             "Failed to create current positioned div element");
           mNewBlock = curPositionedDiv;
         }
         EditorRawDOMPoint atEndOfCurPositionedDiv;
         atEndOfCurPositionedDiv.SetToEndOf(curPositionedDiv);
         curList =
-          htmlEditor->CreateNodeWithTransaction(*containerName,
-                                                atEndOfCurPositionedDiv);
+          HTMLEditorRef().CreateNodeWithTransaction(*containerName,
+                                                    atEndOfCurPositionedDiv);
         if (NS_WARN_IF(!curList)) {
           return NS_ERROR_FAILURE;
         }
         // curList is now the correct thing to put curNode in.  Remember our
         // new block for postprocessing.
       }
       // Tuck the node into the end of the active list
-      rv = htmlEditor->MoveNodeToEndWithTransaction(*curNode->AsContent(),
-                                                    *curList);
+      rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode->AsContent(),
+                                                        *curList);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       continue;
     }
 
     // Not a list item, use blockquote?  If we are inside a list item, we
     // don't want to blockquote, we want to sublist the list item.  We may
@@ -9943,17 +9931,17 @@ HTMLEditRules::WillAbsolutePosition(Sele
     if (listItem) {
       if (indentedLI == listItem) {
         // Already indented this list item
         continue;
       }
       // Check to see if curList is still appropriate.  Which it is if
       // curNode is still right after it in the same list.
       if (curList) {
-        sibling = htmlEditor->GetPriorHTMLSibling(listItem);
+        sibling = HTMLEditorRef().GetPriorHTMLSibling(listItem);
       }
 
       if (!curList || (sibling && sibling != curList)) {
         EditorDOMPoint atListItem(listItem);
         if (NS_WARN_IF(!atListItem.IsSet())) {
           return NS_ERROR_FAILURE;
         }
         nsAtom* containerName =
@@ -9963,32 +9951,32 @@ HTMLEditRules::WillAbsolutePosition(Sele
           MaybeSplitAncestorsForInsertWithTransaction(*containerName,
                                                       atListItem);
         if (NS_WARN_IF(splitNodeResult.Failed())) {
           return splitNodeResult.Rv();
         }
         if (!curPositionedDiv) {
           EditorRawDOMPoint atListItemParent(atListItem.GetContainer());
           curPositionedDiv =
-            htmlEditor->CreateNodeWithTransaction(*nsGkAtoms::div,
-                                                  atListItemParent);
+            HTMLEditorRef().CreateNodeWithTransaction(*nsGkAtoms::div,
+                                                      atListItemParent);
           NS_WARNING_ASSERTION(curPositionedDiv,
             "Failed to create current positioned div element");
           mNewBlock = curPositionedDiv;
         }
         EditorRawDOMPoint atEndOfCurPositionedDiv;
         atEndOfCurPositionedDiv.SetToEndOf(curPositionedDiv);
         curList =
-          htmlEditor->CreateNodeWithTransaction(*containerName,
-                                                atEndOfCurPositionedDiv);
+          HTMLEditorRef().CreateNodeWithTransaction(*containerName,
+                                                    atEndOfCurPositionedDiv);
         if (NS_WARN_IF(!curList)) {
           return NS_ERROR_FAILURE;
         }
       }
-      rv = htmlEditor->MoveNodeToEndWithTransaction(*listItem, *curList);
+      rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*listItem, *curList);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
       // Remember we indented this li
       indentedLI = listItem;
       continue;
     }
 
@@ -10002,112 +9990,120 @@ HTMLEditRules::WillAbsolutePosition(Sele
       }
       SplitNodeResult splitNodeResult =
         MaybeSplitAncestorsForInsertWithTransaction(*nsGkAtoms::div,
                                                     atCurNode);
       if (NS_WARN_IF(splitNodeResult.Failed())) {
         return splitNodeResult.Rv();
       }
       curPositionedDiv =
-        htmlEditor->CreateNodeWithTransaction(*nsGkAtoms::div,
-                                              splitNodeResult.SplitPoint());
+        HTMLEditorRef().CreateNodeWithTransaction(*nsGkAtoms::div,
+                                                  splitNodeResult.SplitPoint());
       if (NS_WARN_IF(!curPositionedDiv)) {
         return NS_ERROR_FAILURE;
       }
       // Remember our new block for postprocessing
       mNewBlock = curPositionedDiv;
       // curPositionedDiv is now the correct thing to put curNode in
     }
 
     // Tuck the node into the end of the active blockquote
-    rv = htmlEditor->MoveNodeToEndWithTransaction(*curNode->AsContent(),
-                                                  *curPositionedDiv);
-    NS_ENSURE_SUCCESS(rv, rv);
+    rv = HTMLEditorRef().MoveNodeToEndWithTransaction(*curNode->AsContent(),
+                                                      *curPositionedDiv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
     // Forget curList, if any
     curList = nullptr;
   }
   return NS_OK;
 }
 
 nsresult
 HTMLEditRules::DidAbsolutePosition()
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (!mNewBlock) {
     return NS_OK;
   }
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor = mHTMLEditor;
-  return htmlEditor->SetPositionToAbsoluteOrStatic(*mNewBlock, true);
+  nsresult rv = HTMLEditorRef().SetPositionToAbsoluteOrStatic(*mNewBlock, true);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 nsresult
 HTMLEditRules::WillRemoveAbsolutePosition(Selection* aSelection,
                                           bool* aCancel,
-                                          bool* aHandled) {
+                                          bool* aHandled)
+{
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (!aSelection || !aCancel || !aHandled) {
     return NS_ERROR_NULL_POINTER;
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor = mHTMLEditor;
-
   WillInsert(*aSelection, aCancel);
 
   // initialize out param
   // we want to ignore aCancel from WillInsert()
   *aCancel = false;
   *aHandled = true;
 
   RefPtr<Element> element =
-    htmlEditor->GetAbsolutelyPositionedSelectionContainer();
+    HTMLEditorRef().GetAbsolutelyPositionedSelectionContainer();
   if (NS_WARN_IF(!element)) {
     return NS_ERROR_FAILURE;
   }
 
-  AutoSelectionRestorer selectionRestorer(aSelection, htmlEditor);
-
-  return htmlEditor->SetPositionToAbsoluteOrStatic(*element, false);
+  AutoSelectionRestorer selectionRestorer(aSelection, &HTMLEditorRef());
+
+  nsresult rv = HTMLEditorRef().SetPositionToAbsoluteOrStatic(*element, false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 nsresult
 HTMLEditRules::WillRelativeChangeZIndex(Selection* aSelection,
                                         int32_t aChange,
                                         bool* aCancel,
                                         bool* aHandled)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   if (!aSelection || !aCancel || !aHandled) {
     return NS_ERROR_NULL_POINTER;
   }
 
-  if (NS_WARN_IF(!mHTMLEditor)) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-  RefPtr<HTMLEditor> htmlEditor = mHTMLEditor;
-
   WillInsert(*aSelection, aCancel);
 
   // initialize out param
   // we want to ignore aCancel from WillInsert()
   *aCancel = false;
   *aHandled = true;
 
   RefPtr<Element> element =
-    htmlEditor->GetAbsolutelyPositionedSelectionContainer();
+    HTMLEditorRef().GetAbsolutelyPositionedSelectionContainer();
   if (NS_WARN_IF(!element)) {
     return NS_ERROR_FAILURE;
   }
 
-  AutoSelectionRestorer selectionRestorer(aSelection, htmlEditor);
+  AutoSelectionRestorer selectionRestorer(aSelection, &HTMLEditorRef());
 
   int32_t zIndex;
-  return htmlEditor->RelativeChangeElementZIndex(*element, aChange, &zIndex);
+  nsresult rv = HTMLEditorRef().RelativeChangeElementZIndex(*element, aChange,
+                                                            &zIndex);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  return NS_OK;
 }
 
 nsresult
 HTMLEditRules::DocumentModified()
 {
   nsContentUtils::AddScriptRunner(
     NewRunnableMethod("HTMLEditRules::DocumentModifiedWorker",
                       this,
--- a/editor/libeditor/TextEditRulesBidi.cpp
+++ b/editor/libeditor/TextEditRulesBidi.cpp
@@ -46,27 +46,27 @@ TextEditRules::CheckBidiLevelForDeletion
   if (!presContext->BidiEnabled()) {
     return NS_OK;
   }
 
   if (!aSelectionPoint.GetContainerAsContent()) {
     return NS_ERROR_FAILURE;
   }
 
-  nsBidiLevel levelBefore;
-  nsBidiLevel levelAfter;
-  RefPtr<nsFrameSelection> frameSelection = aSelection->GetFrameSelection();
-  NS_ENSURE_TRUE(frameSelection, NS_ERROR_NULL_POINTER);
+  RefPtr<nsFrameSelection> frameSelection = SelectionRef().GetFrameSelection();
+  if (NS_WARN_IF(!frameSelection)) {
+    return NS_ERROR_FAILURE;
+  }
 
   nsPrevNextBidiLevels levels = frameSelection->
     GetPrevNextBidiLevels(aSelectionPoint.GetContainerAsContent(),
                           aSelectionPoint.Offset(), true);
 
-  levelBefore = levels.mLevelBefore;
-  levelAfter = levels.mLevelAfter;
+  nsBidiLevel levelBefore = levels.mLevelBefore;
+  nsBidiLevel levelAfter = levels.mLevelAfter;
 
   nsBidiLevel currentCaretLevel = frameSelection->GetCaretBidiLevel();
 
   nsBidiLevel levelOfDeletion;
   levelOfDeletion =
     (nsIEditor::eNext==aAction || nsIEditor::eNextWord==aAction) ?
     levelAfter : levelBefore;
 
@@ -82,23 +82,25 @@ TextEditRules::CheckBidiLevelForDeletion
   // character that will be (or would have been) deleted
   frameSelection->SetCaretBidiLevel(levelOfDeletion);
   return NS_OK;
 }
 
 void
 TextEditRules::UndefineCaretBidiLevel(Selection* aSelection)
 {
+  MOZ_ASSERT(IsEditorDataAvailable());
+
   /**
    * After inserting text the caret Bidi level must be set to the level of the
    * inserted text.This is difficult, because we cannot know what the level is
    * until after the Bidi algorithm is applied to the whole paragraph.
    *
    * So we set the caret Bidi level to UNDEFINED here, and the caret code will
    * set it correctly later
    */
-  RefPtr<nsFrameSelection> frameSelection = aSelection->GetFrameSelection();
+  RefPtr<nsFrameSelection> frameSelection = SelectionRef().GetFrameSelection();
   if (frameSelection) {
     frameSelection->UndefineCaretBidiLevel();
   }
 }
 
 } // namespace mozilla